/// <inheritdoc/> public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage) { foreach (var renderFeature in RenderFeatures) { renderFeature.Draw(context, renderView, renderViewStage); } }
public override unsafe void GenerateSortKey(RenderView renderView, RenderViewStage renderViewStage, SortKey *sortKeys) { Matrix.Invert(ref renderView.View, out var viewInverse); var plane = new Plane(viewInverse.Forward, Vector3.Dot(viewInverse.TranslationVector, viewInverse.Forward)); // TODO: Point-normal-constructor seems wrong. Check. var renderNodes = renderViewStage.RenderNodes; int distanceShift = 32 - distancePrecision; int stateShift = 32 - statePrecision; for (int i = 0; i < renderNodes.Count; ++i) { var renderNode = renderNodes[i]; var renderObject = renderNode.RenderObject; var distance = CollisionHelper.DistancePlanePoint(ref plane, ref renderObject.BoundingBox.Center); var distanceI = ComputeDistance(distance); if (reverseDistance) { distanceI = ~distanceI; } // Compute sort key sortKeys[i] = new SortKey { Value = ((ulong)renderNode.RootRenderFeature.SortKey << 56) | ((ulong)(distanceI >> distanceShift) << distancePosition) | ((ulong)(renderObject.StateSortKey >> stateShift) << statePosition), Index = i, StableIndex = renderObject.Index }; } }
public abstract bool IsVisible(RenderObject renderObject, RenderView renderView, RenderViewStage renderViewStage);
public abstract unsafe void GenerateSortKey(RenderView renderView, RenderViewStage renderViewStage, SortKey *sortKeys);
/// <inheritdoc/> public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { var commandList = context.CommandList; foreach (var renderFeature in RenderFeatures) { renderFeature.Draw(context, renderView, renderViewStage, startIndex, endIndex); } // TODO: stackalloc? var descriptorSetsLocal = descriptorSets.Value; if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount) { descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount]; } MeshDraw currentDrawData = null; int emptyBufferSlot = -1; for (int index = startIndex; index < endIndex; index++) { var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode; var renderNode = GetRenderNode(renderNodeReference); var renderMesh = (RenderMesh)renderNode.RenderObject; var drawData = renderMesh.ActiveMeshDraw; // Get effect // TODO: Use real effect slot var renderEffect = renderNode.RenderEffect; if (renderEffect.Effect == null) { continue; } // Bind VB if (currentDrawData != drawData) { for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++) { var vertexBuffer = drawData.VertexBuffers[slot]; commandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride); } // If the mesh's vertex buffers miss any input streams, an additional input binding will have been added to the pipeline state. // We bind an additional empty vertex buffer to that slot handle those streams gracefully. if (emptyBufferSlot != drawData.VertexBuffers.Length) { commandList.SetVertexBuffer(drawData.VertexBuffers.Length, emptyBuffer, 0, 0); emptyBufferSlot = drawData.VertexBuffers.Length; } if (drawData.IndexBuffer != null) { commandList.SetIndexBuffer(drawData.IndexBuffer.Buffer, drawData.IndexBuffer.Offset, drawData.IndexBuffer.Is32Bit); } currentDrawData = drawData; } var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference); // Update cbuffer renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset); // Bind descriptor sets for (int i = 0; i < descriptorSetsLocal.Length; ++i) { var resourceGroup = ResourceGroupPool[resourceGroupOffset++]; if (resourceGroup != null) { descriptorSetsLocal[i] = resourceGroup.DescriptorSet; } } commandList.SetPipelineState(renderEffect.PipelineState); commandList.SetDescriptorSets(0, descriptorSetsLocal); // Draw if (drawData.IndexBuffer == null) { if (renderMesh.InstanceCount > 0) { commandList.DrawInstanced(drawData.DrawCount, renderMesh.InstanceCount, drawData.StartLocation); } else { commandList.Draw(drawData.DrawCount, drawData.StartLocation); } } else { if (renderMesh.InstanceCount > 0) { commandList.DrawIndexedInstanced(drawData.DrawCount, renderMesh.InstanceCount, drawData.StartLocation); } else { commandList.DrawIndexed(drawData.DrawCount, drawData.StartLocation); } } } }