private void RenderAllSingleThread(GraphicsDevice gd, CommandList cl, SceneContext sc) { float depthClear = gd.IsDepthRangeZeroToOne ? 0f : 1f; Matrix4x4 cameraProj = Camera.ProjectionMatrix; Vector4 nearLimitCS = Vector4.Transform(new Vector3(0, 0, -_nearCascadeLimit), cameraProj); Vector4 midLimitCS = Vector4.Transform(new Vector3(0, 0, -_midCascadeLimit), cameraProj); Vector4 farLimitCS = Vector4.Transform(new Vector3(0, 0, -_farCascadeLimit), cameraProj); cl.UpdateBuffer(sc.DepthLimitsBuffer, 0, new DepthCascadeLimits { NearLimit = nearLimitCS.Z, MidLimit = midLimitCS.Z, FarLimit = farLimitCS.Z }); cl.UpdateBuffer(sc.LightInfoBuffer, 0, sc.DirectionalLight.GetInfo()); Vector3 lightPos = sc.DirectionalLight.Transform.Position - sc.DirectionalLight.Direction * 1000f; // Near cl.PushDebugGroup("Shadow Map - Near Cascade"); Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices( gd, sc, Camera.NearDistance, _nearCascadeLimit, sc.ShadowMapTexture.Width, out BoundingFrustum lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer0, 0, ref viewProj0); cl.SetFramebuffer(sc.NearShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapNear, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); // Mid cl.PushDebugGroup("Shadow Map - Mid Cascade"); Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices( gd, sc, _nearCascadeLimit, _midCascadeLimit, sc.ShadowMapTexture.Width, out lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer1, 0, ref viewProj1); cl.SetFramebuffer(sc.MidShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapMid, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); // Far cl.PushDebugGroup("Shadow Map - Far Cascade"); Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices( gd, sc, _midCascadeLimit, _farCascadeLimit, sc.ShadowMapTexture.Width, out lightFrustum); cl.UpdateBuffer(sc.LightViewProjectionBuffer2, 0, ref viewProj2); cl.SetFramebuffer(sc.FarShadowMapFramebuffer); cl.SetFullViewports(); cl.ClearDepthStencil(depthClear); Render(gd, cl, sc, RenderPasses.ShadowMapFar, lightFrustum, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); // Reflections cl.PushDebugGroup("Planar Reflection Map"); cl.SetFramebuffer(sc.ReflectionFramebuffer); float fbWidth = sc.ReflectionFramebuffer.Width; float fbHeight = sc.ReflectionFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearColorTarget(0, RgbaFloat.Black); cl.ClearDepthStencil(depthClear); // Render reflected scene. Matrix4x4 planeReflectionMatrix = Matrix4x4.CreateReflection(MirrorMesh.Plane); CameraInfo camInfo = new CameraInfo(); camInfo.CameraLookDirection = Vector3.Normalize(Vector3.Reflect(_camera.LookDirection, MirrorMesh.Plane.Normal)); camInfo.CameraPosition_WorldSpace = Vector3.Transform(_camera.Position, planeReflectionMatrix); cl.UpdateBuffer(sc.CameraInfoBuffer, 0, ref camInfo); Matrix4x4 view = sc.Camera.ViewMatrix; view = planeReflectionMatrix * view; cl.UpdateBuffer(sc.ViewMatrixBuffer, 0, view); Matrix4x4 projection = _camera.ProjectionMatrix; cl.UpdateBuffer(sc.ReflectionViewProjBuffer, 0, view * projection); BoundingFrustum cameraFrustum = new BoundingFrustum(view * projection); Render(gd, cl, sc, RenderPasses.ReflectionMap, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.GenerateMipmaps(sc.ReflectionColorTexture); cl.PopDebugGroup(); // Main scene cl.PushDebugGroup("Main Scene Pass"); cl.SetFramebuffer(sc.MainSceneFramebuffer); fbWidth = sc.MainSceneFramebuffer.Width; fbHeight = sc.MainSceneFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetFullViewports(); cl.SetFullScissorRects(); cl.ClearDepthStencil(depthClear); sc.UpdateCameraBuffers(cl); // Re-set because reflection step changed it. cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix); Render(gd, cl, sc, RenderPasses.Standard, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); cl.PushDebugGroup("Transparent Pass"); Render(gd, cl, sc, RenderPasses.AlphaBlend, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); cl.PushDebugGroup("Overlay"); Render(gd, cl, sc, RenderPasses.Overlay, cameraFrustum, _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); if (sc.MainSceneColorTexture.SampleCount != TextureSampleCount.Count1) { cl.ResolveTexture(sc.MainSceneColorTexture, sc.MainSceneResolvedColorTexture); } cl.PushDebugGroup("Duplicator"); cl.SetFramebuffer(sc.DuplicatorFramebuffer); fbWidth = sc.DuplicatorFramebuffer.Width; fbHeight = sc.DuplicatorFramebuffer.Height; cl.SetFullViewports(); Render(gd, cl, sc, RenderPasses.Duplicator, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); cl.PushDebugGroup("Swapchain Pass"); cl.SetFramebuffer(gd.SwapchainFramebuffer); fbWidth = gd.SwapchainFramebuffer.Width; fbHeight = gd.SwapchainFramebuffer.Height; cl.SetFullViewports(); Render(gd, cl, sc, RenderPasses.SwapchainOutput, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.PopDebugGroup(); cl.End(); _resourceUpdateCL.Begin(); foreach (Renderable renderable in _allPerFrameRenderablesSet) { renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc); } _resourceUpdateCL.End(); gd.SubmitCommands(_resourceUpdateCL); gd.SubmitCommands(cl); }
private void RenderAllMultiThreaded(GraphicsDevice gd, CommandList cl, SceneContext sc) { float depthClear = gd.IsDepthRangeZeroToOne ? 0f : 1f; Matrix4x4 cameraProj = Camera.ProjectionMatrix; Vector4 nearLimitCS = Vector4.Transform(new Vector3(0, 0, -_nearCascadeLimit), cameraProj); Vector4 midLimitCS = Vector4.Transform(new Vector3(0, 0, -_midCascadeLimit), cameraProj); Vector4 farLimitCS = Vector4.Transform(new Vector3(0, 0, -_farCascadeLimit), cameraProj); Vector3 lightPos = sc.DirectionalLight.Transform.Position - sc.DirectionalLight.Direction * 1000f; _resourceUpdateCL.Begin(); CommandList[] cls = new CommandList[5]; for (int i = 0; i < cls.Length; i++) { cls[i] = gd.ResourceFactory.CreateCommandList(); cls[i].Begin(); } _resourceUpdateCL.UpdateBuffer(sc.DepthLimitsBuffer, 0, new DepthCascadeLimits { NearLimit = nearLimitCS.Z, MidLimit = midLimitCS.Z, FarLimit = farLimitCS.Z }); _resourceUpdateCL.UpdateBuffer(sc.LightInfoBuffer, 0, sc.DirectionalLight.GetInfo()); _allPerFrameRenderablesSet.Clear(); _tasks[0] = Task.Run(() => { // Near Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices( gd, sc, Camera.NearDistance, _nearCascadeLimit, sc.ShadowMapTexture.Width, out BoundingFrustum lightFrustum0); cls[1].UpdateBuffer(sc.LightViewProjectionBuffer0, 0, ref viewProj0); cls[1].SetFramebuffer(sc.NearShadowMapFramebuffer); cls[1].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[1].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[1].ClearDepthStencil(depthClear); Render(gd, cls[1], sc, RenderPasses.ShadowMapNear, lightFrustum0, lightPos, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, true); }); _tasks[1] = Task.Run(() => { // Mid Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices( gd, sc, _nearCascadeLimit, _midCascadeLimit, sc.ShadowMapTexture.Width, out var lightFrustum1); cls[2].UpdateBuffer(sc.LightViewProjectionBuffer1, 0, ref viewProj1); cls[2].SetFramebuffer(sc.MidShadowMapFramebuffer); cls[2].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[2].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[2].ClearDepthStencil(depthClear); Render(gd, cls[2], sc, RenderPasses.ShadowMapMid, lightFrustum1, lightPos, _renderQueues[1], _cullableStage[1], _renderableStage[1], null, true); }); _tasks[2] = Task.Run(() => { // Far Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices( gd, sc, _midCascadeLimit, _farCascadeLimit, sc.ShadowMapTexture.Width, out var lightFrustum2); cls[3].UpdateBuffer(sc.LightViewProjectionBuffer2, 0, ref viewProj2); cls[3].SetFramebuffer(sc.FarShadowMapFramebuffer); cls[3].SetViewport(0, new Viewport(0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height, 0, 1)); cls[3].SetScissorRect(0, 0, 0, sc.ShadowMapTexture.Width, sc.ShadowMapTexture.Height); cls[3].ClearDepthStencil(depthClear); Render(gd, cls[3], sc, RenderPasses.ShadowMapFar, lightFrustum2, lightPos, _renderQueues[2], _cullableStage[2], _renderableStage[2], null, true); }); _tasks[3] = Task.Run(() => { // Reflections cls[4].SetFramebuffer(sc.ReflectionFramebuffer); float scWidth = sc.ReflectionFramebuffer.Width; float scHeight = sc.ReflectionFramebuffer.Height; cls[4].SetViewport(0, new Viewport(0, 0, scWidth, scHeight, 0, 1)); cls[4].SetFullViewports(); cls[4].SetFullScissorRects(); cls[4].ClearColorTarget(0, RgbaFloat.Black); cls[4].ClearDepthStencil(depthClear); // Render reflected scene. Matrix4x4 planeReflectionMatrix = Matrix4x4.CreateReflection(MirrorMesh.Plane); CameraInfo camInfo = new CameraInfo(); camInfo.CameraLookDirection = Vector3.Normalize(Vector3.Reflect(_camera.LookDirection, MirrorMesh.Plane.Normal)); camInfo.CameraPosition_WorldSpace = Vector3.Transform(_camera.Position, planeReflectionMatrix); cls[4].UpdateBuffer(sc.CameraInfoBuffer, 0, ref camInfo); Matrix4x4 view = sc.Camera.ViewMatrix; view = planeReflectionMatrix * view; cls[4].UpdateBuffer(sc.ViewMatrixBuffer, 0, view); Matrix4x4 projection = _camera.ProjectionMatrix; cls[4].UpdateBuffer(sc.ReflectionViewProjBuffer, 0, view * projection); BoundingFrustum cameraFrustum = new BoundingFrustum(view * projection); Render(gd, cls[4], sc, RenderPasses.ReflectionMap, cameraFrustum, _camera.Position, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); cl.GenerateMipmaps(sc.ReflectionColorTexture); // Main scene cls[4].SetFramebuffer(sc.MainSceneFramebuffer); scWidth = sc.MainSceneFramebuffer.Width; scHeight = sc.MainSceneFramebuffer.Height; cls[4].SetViewport(0, new Viewport(0, 0, scWidth, scHeight, 0, 1)); cls[4].SetScissorRect(0, 0, 0, (uint)scWidth, (uint)scHeight); cls[4].ClearColorTarget(0, RgbaFloat.Black); cls[4].ClearDepthStencil(depthClear); sc.UpdateCameraBuffers(cls[4]); cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix); Render(gd, cls[4], sc, RenderPasses.Standard, cameraFrustum, _camera.Position, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); Render(gd, cls[4], sc, RenderPasses.AlphaBlend, cameraFrustum, _camera.Position, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); Render(gd, cls[4], sc, RenderPasses.Overlay, cameraFrustum, _camera.Position, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true); }); Task.WaitAll(_tasks); foreach (Renderable renderable in _allPerFrameRenderablesSet) { renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc); } _resourceUpdateCL.End(); gd.SubmitCommands(_resourceUpdateCL); for (int i = 0; i < cls.Length; i++) { cls[i].End(); gd.SubmitCommands(cls[i]); cls[i].Dispose(); } if (sc.MainSceneColorTexture.SampleCount != TextureSampleCount.Count1) { cl.ResolveTexture(sc.MainSceneColorTexture, sc.MainSceneResolvedColorTexture); } cl.SetFramebuffer(sc.DuplicatorFramebuffer); uint fbWidth = sc.DuplicatorFramebuffer.Width; uint fbHeight = sc.DuplicatorFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetViewport(1, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetScissorRect(0, 0, 0, fbWidth, fbHeight); cl.SetScissorRect(1, 0, 0, fbWidth, fbHeight); Render(gd, cl, sc, RenderPasses.Duplicator, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.SetFramebuffer(gd.SwapchainFramebuffer); fbWidth = gd.SwapchainFramebuffer.Width; fbHeight = gd.SwapchainFramebuffer.Height; cl.SetViewport(0, new Viewport(0, 0, fbWidth, fbHeight, 0, 1)); cl.SetScissorRect(0, 0, 0, fbWidth, fbHeight); Render(gd, cl, sc, RenderPasses.SwapchainOutput, new BoundingFrustum(), _camera.Position, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false); cl.End(); gd.SubmitCommands(cl); }