protected override async Task LoadContent() { await base.LoadContent(); wireframeState = RasterizerState.New(GraphicsDevice, new RasterizerStateDescription(CullMode.Back) { FillMode = FillMode.Wireframe }); simpleEffect = new Effect(GraphicsDevice, SpriteEffect.Bytecode); parameterCollection = new ParameterCollection(); parameterCollectionGroup = new EffectParameterCollectionGroup(GraphicsDevice, simpleEffect, new [] { parameterCollection }); parameterCollection.Set(TexturingKeys.Texture0, UVTexture); primitives = new List<GeometricPrimitive>(); // Creates all primitives primitives = new List<GeometricPrimitive> { GeometricPrimitive.Plane.New(GraphicsDevice), GeometricPrimitive.Cube.New(GraphicsDevice), GeometricPrimitive.Sphere.New(GraphicsDevice), GeometricPrimitive.GeoSphere.New(GraphicsDevice), GeometricPrimitive.Cylinder.New(GraphicsDevice), GeometricPrimitive.Torus.New(GraphicsDevice), GeometricPrimitive.Teapot.New(GraphicsDevice), GeometricPrimitive.Capsule.New(GraphicsDevice, 0.5f, 0.3f), GeometricPrimitive.Cone.New(GraphicsDevice) }; view = Matrix.LookAtRH(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); Window.AllowUserResizing = true; }
protected override async Task LoadContent() { await base.LoadContent(); var view = Matrix.LookAtRH(new Vector3(2,2,2), new Vector3(0, 0, 0), Vector3.UnitY); var projection = Matrix.PerspectiveFovRH((float)Math.PI / 4.0f, (float)GraphicsDevice.BackBuffer.ViewWidth / GraphicsDevice.BackBuffer.ViewHeight, 0.1f, 100.0f); worldViewProjection = Matrix.Multiply(view, projection); geometry = GeometricPrimitive.Cube.New(GraphicsDevice); simpleEffect = new Effect(GraphicsDevice, SpriteEffect.Bytecode); parameterCollection = new ParameterCollection(); parameterCollectionGroup = new EffectParameterCollectionGroup(GraphicsDevice, simpleEffect, new[] { parameterCollection }); parameterCollection.Set(TexturingKeys.Texture0, UVTexture); // TODO DisposeBy is not working with device reset offlineTarget0 = Texture.New2D(GraphicsDevice, 512, 512, PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget).DisposeBy(this); offlineTarget1 = Texture.New2D(GraphicsDevice, 512, 512, PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget).DisposeBy(this); offlineTarget2 = Texture.New2D(GraphicsDevice, 512, 512, PixelFormat.R8G8B8A8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget).DisposeBy(this); depthBuffer = Texture.New2D(GraphicsDevice, 512, 512, PixelFormat.D16_UNorm, TextureFlags.DepthStencil).DisposeBy(this); width = GraphicsDevice.BackBuffer.ViewWidth; height = GraphicsDevice.BackBuffer.ViewHeight; }
public void Apply(GraphicsDevice graphicsDevice, EffectParameterResourceBinding[] bindings, EffectParameterCollectionGroup parameterCollectionGroup, ref EffectStateBindings effectStateBindings, bool applyEffectStates) { // Apply shader parameters for (int i = 0; i < bindings.Length; i++) { bindings[i].ApplyParameterWithUpdater(graphicsDevice, ref bindings[i].Description, parameterCollectionGroup); } if (applyEffectStates) { // Apply graphics states var rasterizerState = parameterCollectionGroup.GetValue<RasterizerState>(effectStateBindings.RasterizerStateKeyIndex); if (rasterizerState != null) { graphicsDevice.SetRasterizerState(rasterizerState); } var depthStencilState = parameterCollectionGroup.GetValue<DepthStencilState>(effectStateBindings.DepthStencilStateKeyIndex); if (depthStencilState != null) { graphicsDevice.SetDepthStencilState(depthStencilState); } var blendState = parameterCollectionGroup.GetValue<BlendState>(effectStateBindings.BlendStateKeyIndex); if (blendState != null) { graphicsDevice.SetBlendState(blendState); } } }
/// <summary> /// Initializes a new instance of the <see cref="PrimitiveQuad" /> class with a particular effect. /// </summary> /// <param name="graphicsDevice">The graphics device.</param> /// <param name="effect">The effect.</param> public PrimitiveQuad(GraphicsDevice graphicsDevice, Effect effect) { GraphicsDevice = graphicsDevice; simpleEffect = effect; parameters = new ParameterCollection(); parameters.Set(SpriteBaseKeys.MatrixTransform, Matrix.Identity); parameterCollectionGroup = new EffectParameterCollectionGroup(graphicsDevice, simpleEffect, new[] { parameters }); sharedData = GraphicsDevice.GetOrCreateSharedData(GraphicsDeviceSharedDataType.PerDevice, "PrimitiveQuad::VertexBuffer", d => new SharedData(GraphicsDevice, simpleEffect.InputSignature)); }
/// <summary> /// Draws a fullscreen quad with the specified effect and parameters. /// </summary> /// <param name="device">The device.</param> /// <param name="effect">The effect.</param> /// <param name="effectParameterCollectionGroup">The shader parameter updater.</param> /// <exception cref="System.ArgumentNullException">effect</exception> public static void DrawQuad(this GraphicsDevice device, Effect effect, EffectParameterCollectionGroup effectParameterCollectionGroup) { if (effect == null) throw new ArgumentNullException("effect"); // Apply the effect effect.Apply(device, effectParameterCollectionGroup, false); // Draw a full screen quad device.DrawQuad(); // Unapply effect.UnbindResources(device); }
public void Update(GraphicsDevice graphicsDevice, EffectParameterCollectionGroup parameterCollectionGroup) { var threadIndex = graphicsDevice.ThreadIndex; bool dataChanged = constantBufferDatas[threadIndex].Update(parameterCollectionGroup); // Check if update is really needed if (forceDataChanged) forceDataChanged = false; else if (!dataChanged) return; // Upload data to constant buffer Buffer.SetData(graphicsDevice, dataStreams[threadIndex]); }
private void DrawCustomEffect() { GraphicsDevice.Clear(GraphicsDevice.BackBuffer, Color.Black); GraphicsDevice.Clear(GraphicsDevice.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer); GraphicsDevice.SetDepthAndRenderTarget(GraphicsDevice.DepthStencilBuffer, GraphicsDevice.BackBuffer); effectParameters.Set(MyCustomShaderKeys.ColorFactor2, (Vector4)Color.Red); effectParameters.Set(CustomShaderKeys.SwitchEffectLevel, switchEffectLevel); effectParameters.Set(TexturingKeys.Texture0, UVTexture); switchEffectLevel++; // TODO: Add switch Effect to test and capture frames dynamicEffectCompiler.Update(effectInstance, null); parameterCollection = new EffectParameterCollectionGroup(GraphicsDevice, effectInstance.Effect, new[] { effectParameters }); GraphicsDevice.DrawQuad(effectInstance.Effect, parameterCollection); }
protected override async Task LoadContent() { await base.LoadContent(); var vertices = new Vertex[4]; vertices[0] = new Vertex { Position = new Vector3(-1, -1, 0.5f), TexCoords = new Vector2(0, 0) }; vertices[1] = new Vertex { Position = new Vector3(-1, 1, 0.5f), TexCoords = new Vector2(3, 0) }; vertices[2] = new Vertex { Position = new Vector3(1, 1, 0.5f), TexCoords = new Vector2(3, 3) }; vertices[3] = new Vertex { Position = new Vector3(1, -1, 0.5f), TexCoords = new Vector2(0, 3) }; var indices = new short[] { 0, 1, 2, 0, 2, 3 }; var vertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertices, GraphicsResourceUsage.Default); var indexBuffer = Buffer.Index.New(GraphicsDevice, indices, GraphicsResourceUsage.Default); var meshDraw = new MeshDraw { DrawCount = 4, PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, new VertexDeclaration(VertexElement.Position<Vector3>(), VertexElement.TextureCoordinate<Vector2>()), 4) }, IndexBuffer = new IndexBufferBinding(indexBuffer, false, indices.Length), }; var mesh = new Mesh { Draw = meshDraw, }; simpleEffect = new Effect(GraphicsDevice, SpriteEffect.Bytecode); parameterCollection = new ParameterCollection(); parameterCollectionGroup = new EffectParameterCollectionGroup(GraphicsDevice, simpleEffect, new[] { parameterCollection }); parameterCollection.Set(TexturingKeys.Texture0, UVTexture); vao = VertexArrayObject.New(GraphicsDevice, mesh.Draw.IndexBuffer, mesh.Draw.VertexBuffers); myDraws = new DrawOptions[3]; myDraws[0] = new DrawOptions { Sampler = GraphicsDevice.SamplerStates.LinearClamp, Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(-0.5f, 0.5f, 0f)) }; myDraws[1] = new DrawOptions { Sampler = GraphicsDevice.SamplerStates.LinearWrap, Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(0.5f, 0.5f, 0f)) }; myDraws[2] = new DrawOptions { Sampler = SamplerState.New(GraphicsDevice, new SamplerStateDescription(TextureFilter.Linear, TextureAddressMode.Mirror)), Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(0.5f, -0.5f, 0f)) }; //var borderDescription = new SamplerStateDescription(TextureFilter.Linear, TextureAddressMode.Border) { BorderColor = Color.Purple }; //var border = SamplerState.New(GraphicsDevice, borderDescription); //myDraws[3] = new DrawOptions { Sampler = border, Transform = Matrix.Multiply(Matrix.Scale(0.3f), Matrix.Translation(-0.5f, -0.5f, 0f)) }; }
public void UpdateParameters(GraphicsDevice graphicsDevice, EffectParameterCollectionGroup parameterCollectionGroup, EffectParameterUpdaterDefinition parameterUpdaterDefinition) { parameterCollectionGroup.Update(graphicsDevice, parameterUpdaterDefinition); }
private static void UpdateUnorderedAccessView(GraphicsDevice graphicsDevice, ref EffectParameterResourceData binding, EffectParameterCollectionGroup parameterCollectionGroup) { var unorderedAccessView = (GraphicsResource)parameterCollectionGroup.GetObject(binding.Param.KeyIndex); graphicsDevice.SetUnorderedAccessView(binding.Stage, binding.SlotStart, unorderedAccessView); }
private static void UpdateSampler(GraphicsDevice graphicsDevice, ref EffectParameterResourceData binding, EffectParameterCollectionGroup parameterCollectionGroup) { var samplerState = (SamplerState)parameterCollectionGroup.GetObject(binding.Param.KeyIndex); graphicsDevice.SetSamplerState(binding.Stage, binding.SlotStart, samplerState); }
private static void UpdateConstantBuffer(GraphicsDevice graphicsDevice, ref EffectParameterResourceData binding, EffectParameterCollectionGroup parameterCollectionGroup) { var constantBufferHelper = parameterCollectionGroup.GetValue<ParameterConstantBuffer>(binding.Param.KeyIndex); // Update constant buffer content (if required) constantBufferHelper.Update(graphicsDevice, parameterCollectionGroup); graphicsDevice.SetConstantBuffer(binding.Stage, binding.SlotStart, constantBufferHelper.Buffer); }
/// <summary> /// Updates the specified parameter updater. /// </summary> /// <param name="parameterCollectionGroup">The parameter updater.</param> /// <returns></returns> public unsafe bool Update(EffectParameterCollectionGroup parameterCollectionGroup) { bool dataChanged = false; Matrix tempMatrix; //fixed (BoundConstantBufferParam* paramReferences = &this.constantBufferParams[0]) if (constantBufferParams.Length > 0) { var shaderVariable = Interop.Pin(ref Desc.Members[0]); for (int i = 0; i < this.constantBufferParams.Length; ++i, shaderVariable = Interop.IncrementPinned(shaderVariable)) { if (shaderVariable.Param.KeyIndex == -1) { throw new InvalidOperationException(); } var paramReference = constantBufferParams[i]; var internalValue = parameterCollectionGroup.GetInternalValue(shaderVariable.Param.KeyIndex); // TODO: Comparing Counter+DataPointer is not enough (if realloc on same address) if (internalValue == paramReference.Value && internalValue.Counter == paramReference.DirtyCount) continue; constantBufferParams[i] = new ParameterCollectionGroup.BoundInternalValue { Value = internalValue, DirtyCount = internalValue.Counter }; var destination = (byte*)(Data + shaderVariable.Offset); int sourceOffset = 0; float* variableData = (float*)destination; // + shaderVariable.Offset); switch (shaderVariable.Param.Class) { case EffectParameterClass.Struct: internalValue.ReadFrom((IntPtr)variableData, sourceOffset, shaderVariable.Size); break; case EffectParameterClass.Scalar: for (int elt = 0; elt < shaderVariable.Count; ++elt) { internalValue.ReadFrom((IntPtr)variableData, sourceOffset, sizeof(float)); //*variableData = *source++; sourceOffset += 4; variableData += 4; // 4 floats } break; case EffectParameterClass.Vector: case EffectParameterClass.Color: for (int elt = 0; elt < shaderVariable.Count; ++elt) { //Framework.Utilities.CopyMemory((IntPtr)variableData, (IntPtr)source, (int)(shaderVariable.ColumnCount * sizeof(float))); internalValue.ReadFrom((IntPtr)variableData, sourceOffset, (int)(shaderVariable.ColumnCount * sizeof(float))); sourceOffset += (int)shaderVariable.ColumnCount * 4; variableData += 4; } break; case EffectParameterClass.MatrixColumns: for (int elt = 0; elt < shaderVariable.Count; ++elt) { //fixed (Matrix* p = &tempMatrix) { internalValue.ReadFrom((IntPtr)(byte*)&tempMatrix, sourceOffset, (int)(shaderVariable.ColumnCount * shaderVariable.RowCount * sizeof(float))); ((Matrix*)variableData)->CopyMatrixFrom((float*)&tempMatrix, unchecked((int)shaderVariable.ColumnCount), unchecked((int)shaderVariable.RowCount)); sourceOffset += (int)(shaderVariable.ColumnCount * shaderVariable.RowCount) * 4; variableData += 4 * shaderVariable.RowCount; } } break; case EffectParameterClass.MatrixRows: for (int elt = 0; elt < shaderVariable.Count; ++elt) { //fixed (Matrix* p = &tempMatrix) { internalValue.ReadFrom((IntPtr)(byte*)&tempMatrix, sourceOffset, (int)(shaderVariable.ColumnCount * shaderVariable.RowCount * sizeof(float))); ((Matrix*)variableData)->TransposeMatrixFrom((float*)&tempMatrix, unchecked((int)shaderVariable.ColumnCount), unchecked((int)shaderVariable.RowCount)); //source += shaderVariable.ColumnCount * shaderVariable.RowCount; sourceOffset += (int)(shaderVariable.ColumnCount * shaderVariable.RowCount) * 4; variableData += 4 * shaderVariable.RowCount; } } break; } dataChanged = true; } } return dataChanged; }
/// <summary> /// Begins a sprite batch rendering using the specified sorting mode and blend state, sampler, depth stencil, rasterizer state objects, plus a custom effect and a 2D transformation matrix. Passing null for any of the state objects selects the default default state objects (BlendState.AlphaBlend, DepthStencilState.Default, RasterizerState.CullCounterClockwise, SamplerState.LinearClamp). Passing a null effect selects the default SpriteBatch Class shader. /// </summary> /// <param name="viewMatrix">The view matrix to use for the batch session</param> /// <param name="sortMode">The sprite drawing order to use for the batch session</param> /// <param name="blendState">The blending state to use for the batch session</param> /// <param name="samplerState">The sampling state to use for the batch session</param> /// <param name="depthStencilState">The depth stencil state to use for the batch session</param> /// <param name="rasterizerState">The rasterizer state to use for the batch session</param> /// <param name="effect">The effect to use for the batch session</param> /// <param name="parameterCollectionGroup">The parameter collection group.</param> /// <param name="stencilValue">The value of the stencil buffer to take as reference for the batch session</param> public void Begin(Matrix viewMatrix, SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState blendState = null, SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null, Effect effect = null, EffectParameterCollectionGroup parameterCollectionGroup = null, int stencilValue = 0) { UpdateDefaultProjectionMatrix(); Begin(viewMatrix, defaultProjectionMatrix, sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, parameterCollectionGroup, stencilValue); }
/// <summary> /// Draw this effect mesh. /// </summary> public void Draw(RenderContext context) { // Retrieve effect parameters var graphicsDevice = context.GraphicsDevice; var mesh = Mesh; var currentRenderData = mesh.Draw; var material = Material; var vao = vertexArrayObject; var drawCount = currentRenderData.DrawCount; var primitiveType = currentRenderData.PrimitiveType; parameters.Set(TransformationKeys.World, WorldMatrix); // TODO: We should clarify exactly how to override rasterizer states. Currently setup here on Context.Parameters to allow Material/ModelComponent overrides, but this is ugly // Apply rasterizer var rasterizer = RasterizerState; if (!ForceRasterizer && Material.CullMode.HasValue && Material.CullMode.Value != RasterizerState.Description.CullMode) { switch (Material.CullMode.Value) { case CullMode.Back: rasterizer = graphicsDevice.RasterizerStates.CullBack; break; case CullMode.Front: rasterizer = graphicsDevice.RasterizerStates.CullFront; break; case CullMode.None: rasterizer = graphicsDevice.RasterizerStates.CullNone; break; } } context.Parameters.Set(Effect.RasterizerStateKey, rasterizer); // Handle picking if (context.IsPicking()) // TODO move this code corresponding to picking outside of the runtime code! { parameters.Set(ModelComponentPickingShaderKeys.ModelComponentId, new Color4(RuntimeIdHelper.ToRuntimeId(RenderModel.ModelComponent))); parameters.Set(ModelComponentPickingShaderKeys.MeshId, new Color4(RenderModel.ModelComponent.Model.Meshes.IndexOf(Mesh))); parameters.Set(ModelComponentPickingShaderKeys.MaterialId, new Color4(Mesh.MaterialIndex)); // Don't use the materials blend state on picking targets parameters.Set(Effect.BlendStateKey, null); } if (material != null && material.TessellationMethod != XenkoTessellationMethod.None) { var tessellationMethod = material.TessellationMethod; // adapt the primitive type and index buffer to the tessellation used if (tessellationMethod.PerformsAdjacentEdgeAverage()) { vao = GetOrCreateVertexArrayObjectAEN(context); drawCount = 12 / 3 * drawCount; } primitiveType = tessellationMethod.GetPrimitiveType(); } //using (Profiler.Begin(ProfilingKeys.PrepareMesh)) { // Order of application of parameters: // - RenderPass.Parameters // - ModelComponent.Parameters // - RenderMesh.Parameters (originally copied from mesh parameters) // The order is based on the granularity level of each element and how shared it can be. Material is heavily shared, a model contains many meshes. An renderMesh is unique. // TODO: really copy mesh parameters into renderMesh instead of just referencing the meshDraw parameters. //var modelComponent = RenderModel.ModelComponent; //var hasModelComponentParams = modelComponent != null && modelComponent.Parameters != null; //var materialParameters = material != null && material.Parameters != null ? material.Parameters : null; parameterCollections.Clear(); parameterCollections.Add(context.Parameters); FillParameterCollections(ref parameterCollections); // Check if we need to recreate the EffectParameterCollectionGroup // TODO: We can improve performance by redesigning FillParameterCollections to avoid ArrayExtensions.ArraysReferenceEqual (or directly check the appropriate parameter collections) // This also happens in another place: DynamicEffectCompiler (we probably want to factorize it when doing additional optimizations) if (parameterCollectionGroup == null || parameterCollectionGroup.Effect != Effect || !ArrayExtensions.ArraysReferenceEqual(ref previousParameterCollections, ref parameterCollections)) { previousParameterCollections.Clear(); previousParameterCollections.AddRange(parameterCollections); parameterCollectionGroup = new EffectParameterCollectionGroup(context.GraphicsDevice, Effect, previousParameterCollections.Count, previousParameterCollections.Items); } Effect.Apply(context.GraphicsDevice, parameterCollectionGroup, true); } //using (Profiler.Begin(ProfilingKeys.RenderMesh)) { if (currentRenderData != null) { graphicsDevice.SetVertexArrayObject(vao); if (currentRenderData.IndexBuffer == null) { graphicsDevice.Draw(primitiveType, drawCount, currentRenderData.StartLocation); } else { graphicsDevice.DrawIndexed(primitiveType, drawCount, currentRenderData.StartLocation); } } } }
protected override void DrawCore(RenderContext context) { if (string.IsNullOrEmpty(ShaderSourceName)) return; Parameters.Set(ComputeEffectShaderKeys.ThreadNumbers, ThreadNumbers); Parameters.Set(ComputeEffectShaderKeys.ComputeShaderName, ShaderSourceName); Parameters.Set(ComputeShaderBaseKeys.ThreadGroupCountGlobal, ThreadGroupCounts); UpdateEffect(); if (effectParameterCollections == null || effectParameterCollections.Effect != EffectInstance.Effect) { appliedParameterCollections.Clear(); if (context != null) { appliedParameterCollections.Add(context.Parameters); } appliedParameterCollections.AddRange(parameterCollections); effectParameterCollections = new EffectParameterCollectionGroup(GraphicsDevice, EffectInstance.Effect, appliedParameterCollections); } // Apply the effect EffectInstance.Effect.Apply(GraphicsDevice, effectParameterCollections, false); // Draw a full screen quad GraphicsDevice.Dispatch(ThreadGroupCounts.X, ThreadGroupCounts.Y, ThreadGroupCounts.Z); // Un-apply EffectInstance.Effect.UnbindResources(GraphicsDevice); }
protected override async Task LoadContent() { await base.LoadContent(); var vertices = new Vertex[4]; vertices[0] = new Vertex { Position = new Vector3(-1, -1, 0.5f), TexCoords = new Vector2(0, 0) }; vertices[1] = new Vertex { Position = new Vector3(-1, 1, 0.5f), TexCoords = new Vector2(3, 0) }; vertices[2] = new Vertex { Position = new Vector3(1, 1, 0.5f), TexCoords = new Vector2(3, 3) }; vertices[3] = new Vertex { Position = new Vector3(1, -1, 0.5f), TexCoords = new Vector2(0, 3) }; var indices = new short[] { 0, 1, 2, 0, 2, 3 }; var vertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertices, GraphicsResourceUsage.Default); var indexBuffer = Buffer.Index.New(GraphicsDevice, indices, GraphicsResourceUsage.Default); var meshDraw = new MeshDraw { DrawCount = 4, PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, new VertexDeclaration(VertexElement.Position <Vector3>(), VertexElement.TextureCoordinate <Vector2>()), 4) }, IndexBuffer = new IndexBufferBinding(indexBuffer, false, indices.Length), }; var mesh = new Mesh { Draw = meshDraw, }; simpleEffect = new Effect(GraphicsDevice, SpriteEffect.Bytecode); parameterCollection = new ParameterCollection(); parameterCollectionGroup = new EffectParameterCollectionGroup(GraphicsDevice, simpleEffect, new[] { parameterCollection }); parameterCollection.Set(TexturingKeys.Texture0, UVTexture); vao = VertexArrayObject.New(GraphicsDevice, mesh.Draw.IndexBuffer, mesh.Draw.VertexBuffers); myDraws = new DrawOptions[3]; myDraws[0] = new DrawOptions { Sampler = GraphicsDevice.SamplerStates.LinearClamp, Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(-0.5f, 0.5f, 0f)) }; myDraws[1] = new DrawOptions { Sampler = GraphicsDevice.SamplerStates.LinearWrap, Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(0.5f, 0.5f, 0f)) }; myDraws[2] = new DrawOptions { Sampler = SamplerState.New(GraphicsDevice, new SamplerStateDescription(TextureFilter.Linear, TextureAddressMode.Mirror)), Transform = Matrix.Multiply(Matrix.Scaling(0.4f), Matrix.Translation(0.5f, -0.5f, 0f)) }; //var borderDescription = new SamplerStateDescription(TextureFilter.Linear, TextureAddressMode.Border) { BorderColor = Color.Purple }; //var border = SamplerState.New(GraphicsDevice, borderDescription); //myDraws[3] = new DrawOptions { Sampler = border, Transform = Matrix.Multiply(Matrix.Scale(0.3f), Matrix.Translation(-0.5f, -0.5f, 0f)) }; }
/// <summary> /// Begins a sprite batch rendering using the specified sorting mode and blend state, sampler, depth stencil, rasterizer state objects, plus a custom effect and a 2D transformation matrix. Passing null for any of the state objects selects the default default state objects (BlendState.AlphaBlend, DepthStencilState.Default, RasterizerState.CullCounterClockwise, SamplerState.LinearClamp). Passing a null effect selects the default SpriteBatch Class shader. /// </summary> /// <param name="viewMatrix">The view matrix to use for the batch session</param> /// <param name="projectionMatrix">The projection matrix to use for the batch session</param> /// <param name="sortMode">The sprite drawing order to use for the batch session</param> /// <param name="blendState">The blending state to use for the batch session</param> /// <param name="samplerState">The sampling state to use for the batch session</param> /// <param name="depthStencilState">The depth stencil state to use for the batch session</param> /// <param name="rasterizerState">The rasterizer state to use for the batch session</param> /// <param name="effect">The effect to use for the batch session</param> /// <param name="parameterCollectionGroup">The parameter collection group.</param> /// <param name="stencilValue">The value of the stencil buffer to take as reference for the batch session</param> public void Begin(Matrix viewMatrix, Matrix projectionMatrix, SpriteSortMode sortMode = SpriteSortMode.Deferred, BlendState blendState = null, SamplerState samplerState = null, DepthStencilState depthStencilState = null, RasterizerState rasterizerState = null, Effect effect = null, EffectParameterCollectionGroup parameterCollectionGroup = null, int stencilValue = 0) { CheckEndHasBeenCalled("begin"); userViewMatrix = viewMatrix; userProjectionMatrix = projectionMatrix; Begin(effect, parameterCollectionGroup, sortMode, blendState, samplerState, depthStencilState, rasterizerState, stencilValue); }
/// <summary> /// Draw this effect mesh. /// </summary> public void Draw(RenderContext context) { // Retrieve effect parameters var mesh = Mesh; var currentRenderData = mesh.Draw; var material = Material; var vao = vertexArrayObject; var drawCount = currentRenderData.DrawCount; if (context.IsPicking()) // TODO move this code corresponding to picking outside of the runtime code! { parameters.Set(ModelComponentPickingShaderKeys.ModelComponentId, new Color4(RenderModel.ModelComponent.Id)); parameters.Set(ModelComponentPickingShaderKeys.MeshId, new Color4(Mesh.NodeIndex)); parameters.Set(ModelComponentPickingShaderKeys.MaterialId, new Color4(Mesh.MaterialIndex)); } if (material != null && material.TessellationMethod != ParadoxTessellationMethod.None) { var tessellationMethod = material.TessellationMethod; // adapt the primitive type and index buffer to the tessellation used if (tessellationMethod.PerformsAdjacentEdgeAverage()) { vao = GetOrCreateVertexArrayObjectAEN(context); drawCount = 12 / 3 * drawCount; } currentRenderData.PrimitiveType = tessellationMethod.GetPrimitiveType(); } //using (Profiler.Begin(ProfilingKeys.PrepareMesh)) { // Order of application of parameters: // - RenderPass.Parameters // - ModelComponent.Parameters // - RenderMesh.Parameters (originally copied from mesh parameters) // The order is based on the granularity level of each element and how shared it can be. Material is heavily shared, a model contains many meshes. An renderMesh is unique. // TODO: really copy mesh parameters into renderMesh instead of just referencing the meshDraw parameters. //var modelComponent = RenderModel.ModelComponent; //var hasModelComponentParams = modelComponent != null && modelComponent.Parameters != null; //var materialParameters = material != null && material.Parameters != null ? material.Parameters : null; parameterCollections.Clear(); parameterCollections.Add(context.Parameters); FillParameterCollections(parameterCollections); // Check if we need to recreate the EffectParameterCollectionGroup // TODO: We can improve performance by redesigning FillParameterCollections to avoid ArrayExtensions.ArraysReferenceEqual (or directly check the appropriate parameter collections) // This also happens in another place: DynamicEffectCompiler (we probably want to factorize it when doing additional optimizations) if (parameterCollectionGroup == null || parameterCollectionGroup.Effect != Effect || !ArrayExtensions.ArraysReferenceEqual(previousParameterCollections, parameterCollections)) { parameterCollectionGroup = new EffectParameterCollectionGroup(context.GraphicsDevice, Effect, parameterCollections); previousParameterCollections = parameterCollections.ToArray(); } Effect.Apply(context.GraphicsDevice, parameterCollectionGroup, true); } //using (Profiler.Begin(ProfilingKeys.RenderMesh)) { if (currentRenderData != null) { var graphicsDevice = context.GraphicsDevice; graphicsDevice.SetVertexArrayObject(vao); if (currentRenderData.IndexBuffer == null) { graphicsDevice.Draw(currentRenderData.PrimitiveType, drawCount, currentRenderData.StartLocation); } else { graphicsDevice.DrawIndexed(currentRenderData.PrimitiveType, drawCount, currentRenderData.StartLocation); } } } }
protected override void DrawCore(RenderContext context) { UpdateEffect(); if (effectParameterCollections == null || EffectInstance.Effect != effectParameterCollections.Effect) { // Update parameters appliedParameterCollections.Clear(); if (context != null) { appliedParameterCollections.Add(context.Parameters); } foreach (var parameterCollection in parameterCollections) { appliedParameterCollections.Add(parameterCollection); } effectParameterCollections = new EffectParameterCollectionGroup(GraphicsDevice, EffectInstance.Effect, appliedParameterCollections.ToArray()); } // Draw a full screen quad GraphicsDevice.DrawQuad(EffectInstance.Effect, effectParameterCollections); }
/// <summary> /// Draw this effect mesh. /// </summary> public void Draw(RenderContext context) { // Retrieve effect parameters var graphicsDevice = context.GraphicsDevice; var mesh = Mesh; var currentRenderData = mesh.Draw; var material = Material; var vao = vertexArrayObject; var drawCount = currentRenderData.DrawCount; var primitiveType = currentRenderData.PrimitiveType; parameters.Set(TransformationKeys.World, WorldMatrix); // TODO: We should clarify exactly how to override rasterizer states. Currently setup here on Context.Parameters to allow Material/ModelComponent overrides, but this is ugly // Apply rasterizer var rasterizer = RasterizerState; if (!ForceRasterizer && Material.CullMode.HasValue && Material.CullMode.Value != RasterizerState.Description.CullMode) { switch (Material.CullMode.Value) { case CullMode.Back: rasterizer = graphicsDevice.RasterizerStates.CullBack; break; case CullMode.Front: rasterizer = graphicsDevice.RasterizerStates.CullFront; break; case CullMode.None: rasterizer = graphicsDevice.RasterizerStates.CullNone; break; } } context.Parameters.Set(Effect.RasterizerStateKey, rasterizer); // Handle picking if (context.IsPicking()) // TODO move this code corresponding to picking outside of the runtime code! { parameters.Set(ModelComponentPickingShaderKeys.ModelComponentId, new Color4(RenderModel.ModelComponent.Id)); parameters.Set(ModelComponentPickingShaderKeys.MeshId, new Color4(RenderModel.ModelComponent.Model.Meshes.IndexOf(Mesh))); parameters.Set(ModelComponentPickingShaderKeys.MaterialId, new Color4(Mesh.MaterialIndex)); // Don't use the materials blend state on picking targets parameters.Set(Effect.BlendStateKey, null); } if (material != null && material.TessellationMethod != ParadoxTessellationMethod.None) { var tessellationMethod = material.TessellationMethod; // adapt the primitive type and index buffer to the tessellation used if (tessellationMethod.PerformsAdjacentEdgeAverage()) { vao = GetOrCreateVertexArrayObjectAEN(context); drawCount = 12 / 3 * drawCount; } primitiveType = tessellationMethod.GetPrimitiveType(); } //using (Profiler.Begin(ProfilingKeys.PrepareMesh)) { // Order of application of parameters: // - RenderPass.Parameters // - ModelComponent.Parameters // - RenderMesh.Parameters (originally copied from mesh parameters) // The order is based on the granularity level of each element and how shared it can be. Material is heavily shared, a model contains many meshes. An renderMesh is unique. // TODO: really copy mesh parameters into renderMesh instead of just referencing the meshDraw parameters. //var modelComponent = RenderModel.ModelComponent; //var hasModelComponentParams = modelComponent != null && modelComponent.Parameters != null; //var materialParameters = material != null && material.Parameters != null ? material.Parameters : null; parameterCollections.Clear(); parameterCollections.Add(context.Parameters); FillParameterCollections(ref parameterCollections); // Check if we need to recreate the EffectParameterCollectionGroup // TODO: We can improve performance by redesigning FillParameterCollections to avoid ArrayExtensions.ArraysReferenceEqual (or directly check the appropriate parameter collections) // This also happens in another place: DynamicEffectCompiler (we probably want to factorize it when doing additional optimizations) if (parameterCollectionGroup == null || parameterCollectionGroup.Effect != Effect || !ArrayExtensions.ArraysReferenceEqual(ref previousParameterCollections, ref parameterCollections)) { previousParameterCollections.Clear(); previousParameterCollections.AddRange(parameterCollections); parameterCollectionGroup = new EffectParameterCollectionGroup(context.GraphicsDevice, Effect, previousParameterCollections.Count, previousParameterCollections.Items); } Effect.Apply(context.GraphicsDevice, parameterCollectionGroup, true); } //using (Profiler.Begin(ProfilingKeys.RenderMesh)) { if (currentRenderData != null) { graphicsDevice.SetVertexArrayObject(vao); if (currentRenderData.IndexBuffer == null) { graphicsDevice.Draw(primitiveType, drawCount, currentRenderData.StartLocation); } else { graphicsDevice.DrawIndexed(primitiveType, drawCount, currentRenderData.StartLocation); } } } }