/// <inheritdoc/> public override void Prepare(RenderThreadContext context) { var renderViewObjectInfoData = RootRenderFeature.RenderData.GetData(renderViewObjectInfoKey); var resourceGroupPool = ((RootEffectRenderFeature)RootRenderFeature).ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RootRenderFeature.RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RootRenderFeature.RenderNodes[renderNodeIndex]; var renderViewObjectInfo = renderViewObjectInfoData[renderNode.ViewObjectNode]; if (renderViewObjectInfo == null) { continue; } // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) { continue; } if (!PrepareLightParameterEntry(context, renderViewObjectInfo, renderNode.RenderEffect)) { continue; } var resourceGroupPoolOffset = ((RootEffectRenderFeature)RootRenderFeature).ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[resourceGroupPoolOffset + perLightingDescriptorSetSlot.Index] = renderViewObjectInfo.Resources; } }
/// <inheritdoc/> public override void Prepare(RenderDrawContext context) { // Assign descriptor sets to each render node var resourceGroupPool = ((RootEffectRenderFeature)RootRenderFeature).ResourceGroupPool; Dispatcher.For(0, RootRenderFeature.RenderNodes.Count, () => context.RenderContext.GetThreadContext(), (renderNodeIndex, threadContext) => { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RootRenderFeature.RenderNodes[renderNodeIndex]; var renderMesh = (RenderMesh)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) { return; } // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderMesh.Material; var materialInfo = renderMesh.MaterialInfo; var materialParameters = material.Parameters; if (!UpdateMaterial(RenderSystem, threadContext, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) { return; } var descriptorSetPoolOffset = ((RootEffectRenderFeature)RootRenderFeature).ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; }); }
public override void Process(RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { if (renderNode.RenderStage == RenderStage) { pipelineState.BlendState = BlendStates.AlphaBlend; pipelineState.DepthStencilState = DepthStencilStates.DepthRead; } }
public override void Process(RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { if (renderNode.RenderStage == RenderStage) { pipelineState.BlendState = BlendStates.NonPremultiplied; pipelineState.DepthStencilState = DepthStencilStates.DepthRead; pipelineState.RasterizerState.MultisampleAntiAliasLine = true; } }
protected override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { // Bind VAO pipelineState.InputElements = PrimitiveQuad.VertexDeclaration.CreateInputElements(); pipelineState.PrimitiveType = PrimitiveQuad.PrimitiveType; // Don't clip nor write Z value (we are writing at 1.0f = infinity) pipelineState.DepthStencilState = DepthStencilStates.DepthRead; }
protected override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { base.ProcessPipelineState(context, renderNodeReference, ref renderNode, renderObject, pipelineState); pipelineState.DepthStencilState = new DepthStencilStateDescription(false, false); pipelineState.BlendState.AlphaToCoverageEnable = false; pipelineState.BlendState.IndependentBlendEnable = false; ref var blendState0 = ref pipelineState.BlendState.RenderTarget0;
/// <inheritdoc/> protected override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; pipelineState.InputElements = renderParticleEmitter.ParticleEmitter.VertexBuilder.VertexDeclaration.CreateInputElements(); pipelineState.PrimitiveType = PrimitiveType.TriangleList; var material = renderParticleEmitter.ParticleMaterialInfo.Material; material.SetupPipeline(context, pipelineState); }
public override bool Equals(object other) { if (other is RenderNodeReference) { RenderNodeReference p = (RenderNodeReference)other; return(Index == p.Index); } else { return(false); } }
public override void Process(RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { // Disable culling and depth clip if (VoxelRenderStage.Contains(renderNode.RenderStage)) { pipelineState.RasterizerState = new RasterizerStateDescription(CullMode.None) { DepthClipEnable = DepthClipping }; pipelineState.DepthStencilState.DepthBufferEnable = false; pipelineState.DepthStencilState.DepthBufferWriteEnable = false; pipelineState.DepthStencilState.StencilEnable = false; pipelineState.DepthStencilState.StencilWriteMask = 0; pipelineState.DepthStencilState.StencilMask = 0; pipelineState.BlendState.RenderTarget0.BlendEnable = false; pipelineState.BlendState.IndependentBlendEnable = false; } }
/// <summary> /// Builds the shared vertex and index buffers used by the particle systems /// </summary> /// <param name="renderDrawContext"><see cref="RenderDrawContext"/> to access the command list and the graphics context</param> private void BuildParticleBuffers(RenderDrawContext renderDrawContext) { // Build particle buffers var commandList = renderDrawContext.CommandList; // Build the vertex buffer with particles data if (particleBufferContext.VertexBuffer == null || particleBufferContext.VertexBufferSize == 0) { return; } var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); var mappedVertices = commandList.MapSubresource(particleBufferContext.VertexBuffer, 0, MapMode.WriteNoOverwrite, false, 0, particleBufferContext.VertexBufferSize); var sharedBufferPtr = mappedVertices.DataBox.DataPointer; //for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) Dispatcher.For(0, RenderNodes.Count, (renderNodeIndex) => { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; var renderNodeReference = new RenderNodeReference(renderNodeIndex); var nodeData = renderParticleNodeData[renderNodeReference]; if (nodeData.IndexCount <= 0) { return; // Nothing to draw, nothing to build } nodeData.VertexBuffer = particleBufferContext.VertexBuffer; nodeData.IndexBuffer = particleBufferContext.IndexBuffer; renderParticleNodeData[renderNodeReference] = nodeData; Matrix viewInverse; // TODO Build this per view, not per node!!! Matrix.Invert(ref renderNode.RenderView.View, out viewInverse); renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(sharedBufferPtr + nodeData.VertexBufferOffset, ref viewInverse, ref renderNode.RenderView.ViewProjection); }); commandList.UnmapSubresource(mappedVertices); }
public override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { base.ProcessPipelineState(context, renderNodeReference, ref renderNode, renderObject, pipelineState); // Check if this is a highlight rendering var perDrawLayout = renderNode.RenderEffect.Reflection?.PerDrawLayout; if (perDrawLayout == null) { return; } var colorOffset = perDrawLayout.GetConstantBufferOffset(this.color); if (colorOffset == -1) { return; } // Display using alpha blending and without depth-buffer writing pipelineState.BlendState = BlendStates.AlphaBlend; pipelineState.DepthStencilState = DepthStencilStates.DepthRead; }
public override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { base.ProcessPipelineState(context, renderNodeReference, ref renderNode, renderObject, pipelineState); // Check if this is a wireframe rendering var perDrawLayout = renderNode.RenderEffect.Reflection?.PerDrawLayout; if (perDrawLayout == null) { return; } var perDrawDataOffset = perDrawLayout.GetConstantBufferOffset(this.perDrawData); if (perDrawDataOffset == -1) { return; } // Display using wireframe and without depth-buffer pipelineState.BlendState = BlendStates.AlphaBlend; pipelineState.RasterizerState = RasterizerStates.Wireframe; pipelineState.DepthStencilState.DepthBufferEnable = false; }
public T this[RenderNodeReference index] { get { return(Data[index.Index]); } set { Data[index.Index] = value; } }
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { base.Prepare(context); for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderSkybox = (RenderSkybox)renderNode.RenderObject; var sourceParameters = renderSkybox.Background == SkyboxBackground.Irradiance ? renderSkybox.Skybox.DiffuseLightingParameters : renderSkybox.Skybox.Parameters; var skyboxInfo = renderSkybox.SkyboxInfo; if (skyboxInfo == null || skyboxInfo.Skybox != renderSkybox.Skybox) skyboxInfo = renderSkybox.SkyboxInfo = new SkyboxInfo(renderSkybox.Skybox); var parameters = skyboxInfo.ParameterCollection; var renderEffect = renderNode.RenderEffect; if (renderEffect.State != RenderEffectState.Normal) continue; // TODO GRAPHICS REFACTOR current system is not really safe with multiple renderers (parameters come from Skybox which is shared but ResourceGroupLayout from RenderSkybox is per RenderNode) if (skyboxInfo.ResourceGroupLayout == null || skyboxInfo.ResourceGroupLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index].Hash) { var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index]; var parameterCollectionLayout = skyboxInfo.ParameterCollectionLayout = new ParameterCollectionLayout(); parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout); // Find material cbuffer if (resourceGroupDescription.ConstantBufferReflection != null) { parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection); } //skyboxInfo.RotationParameter = parameters.GetAccessor(SkyboxKeys.Rotation); //skyboxInfo.SkyMatrixParameter = parameters.GetAccessor(SkyboxKeys.SkyMatrix); // TODO: Cache that skyboxInfo.ResourceGroupLayout = ResourceGroupLayout.New(RenderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode); parameters.UpdateLayout(parameterCollectionLayout); if (renderSkybox.Background == SkyboxBackground.Irradiance) { skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters, ".skyboxColor"); } else { skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters); } } skyboxInfo.ParameterCollectionCopier.Copy(); // Setup the intensity parameters.Set(SkyboxKeys.Intensity, renderSkybox.Intensity); // Update SkyMatrix Matrix skyMatrix; Matrix.RotationQuaternion(ref renderSkybox.Rotation, out skyMatrix); parameters.Set(SkyboxKeys.SkyMatrix, ref skyMatrix); // Update MatrixTransform // TODO: Use default values? var matrixTransformOffset = renderNode.RenderEffect.Reflection.PerDrawLayout.GetConstantBufferOffset(this.matrixTransform); if (matrixTransformOffset != -1) { var mappedCB = renderNode.Resources.ConstantBuffer.Data + matrixTransformOffset; Matrix.Translation(0.0f, 0.0f, 1.0f, out *(Matrix*)(byte*)mappedCB); } var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); context.ResourceGroupAllocator.PrepareResourceGroup(skyboxInfo.ResourceGroupLayout, BufferPoolAllocationType.UsedMultipleTime, skyboxInfo.Resources); ResourceGroupPool[descriptorSetPoolOffset + perLightingDescriptorSetSlot.Index] = skyboxInfo.Resources; var descriptorSet = skyboxInfo.Resources.DescriptorSet; // Set resource bindings in PerLighting resource set for (int resourceSlot = 0; resourceSlot < parameters.Layout.ResourceCount; ++resourceSlot) { descriptorSet.SetValue(resourceSlot, parameters.ObjectValues[resourceSlot]); } // Process PerLighting cbuffer if (skyboxInfo.Resources.ConstantBuffer.Size > 0) { var mappedCB = skyboxInfo.Resources.ConstantBuffer.Data; fixed (byte* dataValues = parameters.DataValues) Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, skyboxInfo.Resources.ConstantBuffer.Size); } } transformRenderFeature.Prepare(context); }
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Inspect each RenderObject (= ParticleEmitter) to determine if its required vertex buffer size has changed foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; renderParticleEmitter.ParticleEmitter.PrepareForDraw(out renderParticleEmitter.HasVertexBufferChanged, out renderParticleEmitter.VertexSize, out renderParticleEmitter.VertexCount); // TODO: ParticleMaterial should set this up var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo; var colorShade = renderParticleEmitter.Color.ToColorSpace(context.GraphicsDevice.ColorSpace); materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, colorShade); } // Calculate the total vertex buffer size required int totalVertexBufferSize = 0; int highestIndexCount = 0; var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); // Reset pipeline states if necessary for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.HasVertexBufferChanged) { // Reset pipeline state, so input layout is regenerated if (renderNode.RenderEffect != null) { renderNode.RenderEffect.PipelineState = null; } } // Write some attributes back which we will need for rendering later var vertexBuilder = renderParticleEmitter.ParticleEmitter.VertexBuilder; var newNodeData = new RenderAttributesPerNode { VertexBufferOffset = totalVertexBufferSize, VertexBufferSize = renderParticleEmitter.VertexSize * renderParticleEmitter.VertexCount, VertexBufferStride = renderParticleEmitter.VertexSize, IndexCount = vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, }; renderParticleNodeData[new RenderNodeReference(renderNodeIndex)] = newNodeData; totalVertexBufferSize += newNodeData.VertexBufferSize; if (newNodeData.IndexCount > highestIndexCount) { highestIndexCount = newNodeData.IndexCount; } } base.Prepare(context); // Assign descriptor sets to each render node var resourceGroupPool = ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) { continue; } // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderParticleEmitter.ParticleEmitter.Material; var materialInfo = renderParticleEmitter.ParticleMaterialInfo; var materialParameters = material.Parameters; if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) { continue; } var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } particleBufferContext.AllocateBuffers(context, totalVertexBufferSize, highestIndexCount); BuildParticleBuffers(context); }
internal RenderNodeReference CreateRenderNode(RenderObject renderObject, RenderView renderView, ViewObjectNodeReference renderPerViewNode, RenderStage renderStage) { var renderNode = new RenderNode(renderObject, renderView, renderPerViewNode, renderStage); // Create view node var index = RenderNodes.Add(renderNode); var result = new RenderNodeReference(index); return result; }
/// <summary> /// Builds the shared vertex and index buffers used by the particle systems /// </summary> /// <param name="renderDrawContext"><see cref="RenderDrawContext"/> to access the command list and the graphics context</param> private void BuildParticleBuffers(RenderDrawContext renderDrawContext) { // Build particle buffers var commandList = renderDrawContext.CommandList; // Build the vertex buffer with particles data if (particleBufferContext.VertexBuffer == null || particleBufferContext.VertexBufferSize == 0) return; var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); var mappedVertices = commandList.MapSubresource(particleBufferContext.VertexBuffer, 0, MapMode.WriteNoOverwrite, false, 0, particleBufferContext.VertexBufferSize); var sharedBufferPtr = mappedVertices.DataBox.DataPointer; //for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) Dispatcher.For(0, RenderNodes.Count, (renderNodeIndex) => { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; var renderNodeReference = new RenderNodeReference(renderNodeIndex); var nodeData = renderParticleNodeData[renderNodeReference]; if (nodeData.IndexCount <= 0) return; // Nothing to draw, nothing to build nodeData.VertexBuffer = particleBufferContext.VertexBuffer; nodeData.IndexBuffer = particleBufferContext.IndexBuffer; renderParticleNodeData[renderNodeReference] = nodeData; Matrix viewInverse; // TODO Build this per view, not per node!!! Matrix.Invert(ref renderNode.RenderView.View, out viewInverse); renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(sharedBufferPtr + nodeData.VertexBufferOffset, ref viewInverse); }); commandList.UnmapSubresource(mappedVertices); }
public override void Process(RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { pipelineState.RasterizerState = RasterizerStates.WireframeCullBack; }
public RenderNodeFeatureReference(RootRenderFeature rootRenderFeature, RenderNodeReference renderNode, RenderObject renderObject) { RootRenderFeature = rootRenderFeature; RenderNode = renderNode; RenderObject = renderObject; }
/// <inheritdoc/> public override void Prepare(RenderDrawContext context) { // Assign descriptor sets to each render node var resourceGroupPool = ((RootEffectRenderFeature)RootRenderFeature).ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RootRenderFeature.RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RootRenderFeature.RenderNodes[renderNodeIndex]; var renderMesh = (RenderMesh)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) continue; // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderMesh.Material; var materialInfo = renderMesh.MaterialInfo; var materialParameters = material.Parameters; if (!UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) continue; var descriptorSetPoolOffset = ((RootEffectRenderFeature)RootRenderFeature).ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } }
/// <inheritdoc/> public override unsafe void Prepare(RenderThreadContext context) { base.Prepare(context); for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderSkybox = (RenderSkybox)renderNode.RenderObject; var sourceParameters = renderSkybox.Background == SkyboxBackground.Irradiance ? renderSkybox.Skybox.DiffuseLightingParameters : renderSkybox.Skybox.Parameters; var skyboxInfo = renderSkybox.SkyboxInfo; if (skyboxInfo == null || skyboxInfo.Skybox != renderSkybox.Skybox) { skyboxInfo = renderSkybox.SkyboxInfo = new SkyboxInfo(renderSkybox.Skybox); } var parameters = skyboxInfo.ParameterCollection; var renderEffect = renderNode.RenderEffect; if (renderEffect.State != RenderEffectState.Normal) { continue; } // TODO GRAPHICS REFACTOR current system is not really safe with multiple renderers (parameters come from Skybox which is shared but ResourceGroupLayout from RenderSkybox is per RenderNode) if (skyboxInfo.ResourceGroupLayout == null || skyboxInfo.ResourceGroupLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index].Hash) { var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index]; var parameterCollectionLayout = skyboxInfo.ParameterCollectionLayout = new ParameterCollectionLayout(); parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout); // Find material cbuffer if (resourceGroupDescription.ConstantBufferReflection != null) { parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection); } //skyboxInfo.RotationParameter = parameters.GetAccessor(SkyboxKeys.Rotation); //skyboxInfo.SkyMatrixParameter = parameters.GetAccessor(SkyboxKeys.SkyMatrix); // TODO: Cache that skyboxInfo.ResourceGroupLayout = ResourceGroupLayout.New(RenderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode); parameters.UpdateLayout(parameterCollectionLayout); if (renderSkybox.Background == SkyboxBackground.Irradiance) { skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters, ".skyboxColor"); } else { skyboxInfo.ParameterCollectionCopier = new ParameterCollection.Copier(parameters, sourceParameters); } } skyboxInfo.ParameterCollectionCopier.Copy(); // Setup the intensity parameters.Set(SkyboxKeys.Intensity, renderSkybox.Intensity); // Update SkyMatrix Matrix skyMatrix; Matrix.RotationQuaternion(ref renderSkybox.Rotation, out skyMatrix); parameters.Set(SkyboxKeys.SkyMatrix, ref skyMatrix); // Update MatrixTransform // TODO: Use default values? var matrixTransformOffset = renderNode.RenderEffect.Reflection.PerDrawLayout.GetConstantBufferOffset(this.matrixTransform); if (matrixTransformOffset != -1) { var mappedCB = renderNode.Resources.ConstantBuffer.Data + matrixTransformOffset; Matrix.Translation(0.0f, 0.0f, 1.0f, out *(Matrix *)(byte *)mappedCB); } var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); context.ResourceGroupAllocator.PrepareResourceGroup(skyboxInfo.ResourceGroupLayout, BufferPoolAllocationType.UsedMultipleTime, skyboxInfo.Resources); ResourceGroupPool[descriptorSetPoolOffset + perLightingDescriptorSetSlot.Index] = skyboxInfo.Resources; var descriptorSet = skyboxInfo.Resources.DescriptorSet; // Set resource bindings in PerLighting resource set for (int resourceSlot = 0; resourceSlot < parameters.Layout.ResourceCount; ++resourceSlot) { descriptorSet.SetValue(resourceSlot, parameters.ObjectValues[resourceSlot]); } // Process PerLighting cbuffer if (skyboxInfo.Resources.ConstantBuffer.Size > 0) { var mappedCB = skyboxInfo.Resources.ConstantBuffer.Data; fixed(byte *dataValues = parameters.DataValues) Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, skyboxInfo.Resources.ConstantBuffer.Size); } } transformRenderFeature.Prepare(context); }
public RenderNode GetRenderNode(RenderNodeReference reference) { return RenderNodes[reference.Index]; }
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Inspect each RenderObject (= ParticleEmitter) to determine if its required vertex buffer size has changed foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; renderParticleEmitter.ParticleEmitter.PrepareForDraw(out renderParticleEmitter.HasVertexBufferChanged, out renderParticleEmitter.VertexSize, out renderParticleEmitter.VertexCount); // TODO: ParticleMaterial should set this up var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo; materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent.Color); } // Calculate the total vertex buffer size required int totalVertexBufferSize = 0; int highestIndexCount = 0; var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); // Reset pipeline states if necessary for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.HasVertexBufferChanged) { // Reset pipeline state, so input layout is regenerated if (renderNode.RenderEffect != null) renderNode.RenderEffect.PipelineState = null; } // Write some attributes back which we will need for rendering later var vertexBuilder = renderParticleEmitter.ParticleEmitter.VertexBuilder; var newNodeData = new RenderAttributesPerNode { VertexBufferOffset = totalVertexBufferSize, VertexBufferSize = renderParticleEmitter.VertexSize * renderParticleEmitter.VertexCount, VertexBufferStride = renderParticleEmitter.VertexSize, IndexCount = vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, }; renderParticleNodeData[new RenderNodeReference(renderNodeIndex)] = newNodeData; totalVertexBufferSize += newNodeData.VertexBufferSize; if (newNodeData.IndexCount > highestIndexCount) highestIndexCount = newNodeData.IndexCount; } base.Prepare(context); // Assign descriptor sets to each render node var resourceGroupPool = ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) continue; // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderParticleEmitter.ParticleEmitter.Material; var materialInfo = renderParticleEmitter.ParticleMaterialInfo; var materialParameters = material.Parameters; if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) continue; var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } particleBufferContext.AllocateBuffers(context, totalVertexBufferSize, highestIndexCount); BuildParticleBuffers(context); }
protected override void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { var renderMesh = (RenderMesh)renderObject; var drawData = renderMesh.ActiveMeshDraw; pipelineState.InputElements = drawData.VertexBuffers.CreateInputElements(); pipelineState.PrimitiveType = drawData.PrimitiveType; }
/// <summary> /// Compute the index of first descriptor set stored in <see cref="ResourceGroupPool"/>. /// </summary> protected internal int ComputeResourceGroupOffset(RenderNodeReference renderNode) { return renderNode.Index * effectDescriptorSetSlots.Count; }
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Reset pipeline states if necessary for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty) { // Reset pipeline state, so input layout is regenerated if (renderNode.RenderEffect != null) renderNode.RenderEffect.PipelineState = null; } } foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; renderParticleEmitter.ParticleEmitter.PrepareForDraw(); var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo; // Handle vertex element changes if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty) { // Create new buffers renderParticleEmitter.ParticleEmitter.VertexBuilder.RecreateBuffers(RenderSystem.GraphicsDevice); } // TODO: ParticleMaterial should set this up materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent.Color); } base.Prepare(context); // Assign descriptor sets to each render node var resourceGroupPool = ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) continue; // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderParticleEmitter.ParticleEmitter.Material; var materialInfo = renderParticleEmitter.ParticleMaterialInfo; var materialParameters = material.Parameters; if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) continue; var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } // Per view // TODO: Transform sub render feature? for (int index = 0; index < RenderSystem.Views.Count; index++) { var view = RenderSystem.Views[index]; var viewFeature = view.Features[Index]; // TODO GRAPHICS REFACTOR: Happens in several places Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection); // Copy ViewProjection to PerFrame cbuffer foreach (var viewLayout in viewFeature.Layouts) { var resourceGroup = viewLayout.Entries[view.Index].Resources; var mappedCB = resourceGroup.ConstantBuffer.Data; // PerView constant buffer var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset); if (perViewOffset != -1) { var perView = (ParticleUtilitiesPerView*)((byte*)mappedCB + perViewOffset); perView->ViewMatrix = view.View; perView->ProjectionMatrix = view.Projection; perView->ViewProjectionMatrix = view.ViewProjection; perView->ViewFrustum = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane); } } } }
protected virtual void ProcessPipelineState(RenderContext context, RenderNodeReference renderNodeReference, ref RenderNode renderNode, RenderObject renderObject, PipelineStateDescription pipelineState) { }
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Reset pipeline states if necessary for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty) { // Reset pipeline state, so input layout is regenerated if (renderNode.RenderEffect != null) { renderNode.RenderEffect.PipelineState = null; } } } foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; renderParticleEmitter.ParticleEmitter.PrepareForDraw(); var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo; // Handle vertex element changes if (renderParticleEmitter.ParticleEmitter.VertexBuilder.IsBufferDirty) { // Create new buffers renderParticleEmitter.ParticleEmitter.VertexBuilder.RecreateBuffers(RenderSystem.GraphicsDevice); } // TODO: ParticleMaterial should set this up materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent.Color); } base.Prepare(context); // Assign descriptor sets to each render node var resourceGroupPool = ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) { continue; } // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderParticleEmitter.ParticleEmitter.Material; var materialInfo = renderParticleEmitter.ParticleMaterialInfo; var materialParameters = material.Parameters; if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) { continue; } var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } // Per view // TODO: Transform sub render feature? for (int index = 0; index < RenderSystem.Views.Count; index++) { var view = RenderSystem.Views[index]; var viewFeature = view.Features[Index]; // TODO GRAPHICS REFACTOR: Happens in several places Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection); // Copy ViewProjection to PerFrame cbuffer foreach (var viewLayout in viewFeature.Layouts) { var viewProjectionOffset = viewLayout.GetConstantBufferOffset(this.view); if (viewProjectionOffset == -1) { continue; } var resourceGroup = viewLayout.Entries[view.Index].Resources; var mappedCB = resourceGroup.ConstantBuffer.Data; var perView = (Matrix *)((byte *)mappedCB + viewProjectionOffset); * perView = view.ViewProjection; } } }
public ref T this[RenderNodeReference index] => ref Data[index.Index];
/// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Inspect each RenderObject (= ParticleEmitter) to determine if its required vertex buffer size has changed foreach (var renderObject in RenderObjects) { var renderParticleEmitter = (RenderParticleEmitter)renderObject; renderParticleEmitter.ParticleEmitter.PrepareForDraw(out renderParticleEmitter.HasVertexBufferChanged, out renderParticleEmitter.VertexSize, out renderParticleEmitter.VertexCount); // TODO: ParticleMaterial should set this up var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo; materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent.Color); } // Calculate the total vertex buffer size required int totalVertexBufferSize = 0; int highestIndexCount = 0; var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey); // Reset pipeline states if necessary for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; if (renderParticleEmitter.HasVertexBufferChanged) { // Reset pipeline state, so input layout is regenerated if (renderNode.RenderEffect != null) { renderNode.RenderEffect.PipelineState = null; } } // Write some attributes back which we will need for rendering later var vertexBuilder = renderParticleEmitter.ParticleEmitter.VertexBuilder; var newNodeData = new RenderAttributesPerNode { VertexBufferOffset = totalVertexBufferSize, VertexBufferSize = renderParticleEmitter.VertexSize * renderParticleEmitter.VertexCount, VertexBufferStride = renderParticleEmitter.VertexSize, IndexCount = vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, }; renderParticleNodeData[new RenderNodeReference(renderNodeIndex)] = newNodeData; totalVertexBufferSize += newNodeData.VertexBufferSize; if (newNodeData.IndexCount > highestIndexCount) { highestIndexCount = newNodeData.IndexCount; } } base.Prepare(context); // Assign descriptor sets to each render node var resourceGroupPool = ResourceGroupPool; for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++) { var renderNodeReference = new RenderNodeReference(renderNodeIndex); var renderNode = RenderNodes[renderNodeIndex]; var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject; // Ignore fallback effects if (renderNode.RenderEffect.State != RenderEffectState.Normal) { continue; } // Collect materials and create associated MaterialInfo (includes reflection) first time // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order) // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario) var material = renderParticleEmitter.ParticleEmitter.Material; var materialInfo = renderParticleEmitter.ParticleMaterialInfo; var materialParameters = material.Parameters; if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters)) { continue; } var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference); resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources; } // Per view // TODO: Transform sub render feature? for (int index = 0; index < RenderSystem.Views.Count; index++) { var view = RenderSystem.Views[index]; var viewFeature = view.Features[Index]; // TODO GRAPHICS REFACTOR: Happens in several places Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection); // Copy ViewProjection to PerFrame cbuffer foreach (var viewLayout in viewFeature.Layouts) { var resourceGroup = viewLayout.Entries[view.Index].Resources; var mappedCB = resourceGroup.ConstantBuffer.Data; // PerView constant buffer var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset); if (perViewOffset != -1) { var perView = (ParticleUtilitiesPerView *)((byte *)mappedCB + perViewOffset); perView->ViewMatrix = view.View; perView->ProjectionMatrix = view.Projection; perView->ViewProjectionMatrix = view.ViewProjection; perView->ViewFrustum = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane); } } } particleBufferContext.AllocateBuffers(context, totalVertexBufferSize, highestIndexCount); BuildParticleBuffers(context); }