/// <param name="context"></param> /// <inheritdoc/> public override unsafe void Prepare(RenderDrawContext context) { // Compute WorldView, WorldViewProj var renderModelObjectInfoData = RootRenderFeature.RenderData.GetData(RenderModelObjectInfoKey); var renderModelViewInfoData = RootRenderFeature.RenderData.GetData(RenderModelViewInfoKey); // Update PerFrame (time) // TODO Move that to RootEffectRenderFeature? float timeStep = (float)Context.Time.Elapsed.TotalSeconds * GlobalKeys.TimeScale; scaledTimeAccumulator += timeStep; foreach (var frameLayout in ((RootEffectRenderFeature)RootRenderFeature).FrameLayouts) { var timeOffset = frameLayout.GetConstantBufferOffset(time); if (timeOffset == -1) { continue; } var resourceGroup = frameLayout.Entry.Resources; var mappedCB = resourceGroup.ConstantBuffer.Data; var perFrameTime = (PerFrameTime *)((byte *)mappedCB + timeOffset); perFrameTime->TimeStep = timeStep; perFrameTime->Time = scaledTimeAccumulator; } // Update PerView (View, Proj, etc...) for (int index = 0; index < RenderSystem.Views.Count; index++) { var view = RenderSystem.Views[index]; var viewFeature = view.Features[RootRenderFeature.Index]; // Compute WorldView and WorldViewProjection Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference => { var renderPerViewNode = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference); ref var renderModelFrameInfo = ref renderModelObjectInfoData[renderPerViewNode.ObjectNode]; ref var renderModelViewInfo = ref renderModelViewInfoData[renderPerViewNodeReference]; Matrix.Multiply(ref renderModelFrameInfo.World, ref view.View, out renderModelViewInfo.WorldView); Matrix.Multiply(ref renderModelFrameInfo.World, ref view.ViewProjection, out renderModelViewInfo.WorldViewProjection); });
public override unsafe void Prepare(RenderDrawContext context) { var previousTransformationInfoData = RootRenderFeature.RenderData.GetData(previousTransformationInfoKey); var previousTransformationViewInfoData = RootRenderFeature.RenderData.GetData(previousTransformationViewInfoKey); var renderModelObjectInfoData = RootRenderFeature.RenderData.GetData(renderModelObjectInfoKey); // Calculate previous WVP matrix per view and object usageCounter++; for (int index = 0; index < RenderSystem.Views.Count; index++) { var view = RenderSystem.Views[index]; var viewFeature = view.Features[RootRenderFeature.Index]; bool useView = false; foreach (var stage in RenderSystem.RenderStages) { foreach (var renderViewStage in view.RenderStages) { if (renderViewStage.Index == stage.Index && stage.OutputValidator?.Find <VelocityTargetSemantic>() >= 0) { useView = true; break; } } } if (!useView) { continue; } // Cache per-view data locally RenderViewData viewData; if (!renderViewDatas.TryGetValue(view, out viewData)) { viewData = new RenderViewData(); renderViewDatas.Add(view, viewData); } Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference => { var renderPerViewNode = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference); var renderModelFrameInfo = renderModelObjectInfoData[renderPerViewNode.ObjectNode]; Matrix previousViewProjection = viewData.PreviousViewProjection; Matrix previousWorldViewProjection; Matrix.Multiply(ref renderModelFrameInfo.World, ref previousViewProjection, out previousWorldViewProjection); previousTransformationViewInfoData[renderPerViewNodeReference] = new PreviousObjectViewInfo { WorldViewProjection = previousWorldViewProjection, }; }); // Shift current view projection transform into previous viewData.PreviousViewProjection = view.ViewProjection; viewData.UsageCounter = usageCounter; updatedViews.Add(view); } foreach (var view in renderViewDatas.Keys.ToArray()) { if (!updatedViews.Contains(view)) { renderViewDatas.Remove(view); } } updatedViews.Clear(); // Update cbuffer for previous WVP matrix Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).RenderNodes, (ref RenderNode renderNode) => { var perDrawLayout = renderNode.RenderEffect?.Reflection?.PerDrawLayout; if (perDrawLayout == null) { return; } var previousWvpOffset = perDrawLayout.GetConstantBufferOffset(previousWorldViewProjection); if (previousWvpOffset == -1) { return; } var mappedCB = renderNode.Resources.ConstantBuffer.Data; var previousPerDraw = (PreviousPerDraw *)((byte *)mappedCB + previousWvpOffset); var renderModelFrameInfo = renderModelObjectInfoData[renderNode.RenderObject.ObjectNode]; var renderModelPreviousFrameInfo = previousTransformationViewInfoData[renderNode.ViewObjectNode]; // Shift current world transform into previous transform previousTransformationInfoData[renderNode.RenderObject.StaticObjectNode] = new StaticObjectInfo { World = renderModelFrameInfo.World, }; previousPerDraw->PreviousWorldViewProjection = renderModelPreviousFrameInfo.WorldViewProjection; }); }