Beispiel #1
0
        public void Render(
            RenderContext rc,
            SceneContext sc,
            RenderPasses pass,
            BoundingFrustum frustum,
            Comparer <RenderItemIndex> comparer = null)
        {
            _renderQueue.Clear();

            _cullableStage.Clear();
            CollectVisibleObjects(ref frustum, pass, _cullableStage);
            _renderQueue.AddRange(_cullableStage, _camera.Position);

            _renderableStage.Clear();
            CollectFreeObjects(pass, _renderableStage);
            _renderQueue.AddRange(_renderableStage, _camera.Position);

            if (comparer == null)
            {
                _renderQueue.Sort();
            }
            else
            {
                _renderQueue.Sort(comparer);
            }

            foreach (Renderable renderable in _renderQueue)
            {
                renderable.Render(rc, sc, pass);
            }
        }
Beispiel #2
0
        public void Render(
            GraphicsDevice gd,
            CommandList rc,
            SceneContext sc,
            RenderPasses pass,
            BoundingFrustum frustum,
            RenderQueue renderQueue,
            List <CullRenderable> cullRenderableList,
            List <Renderable> renderableList,
            Comparer <RenderItemIndex> comparer,
            bool threaded)
        {
            renderQueue.Clear();

            cullRenderableList.Clear();
            CollectVisibleObjects(ref frustum, pass, cullRenderableList);
            renderQueue.AddRange(cullRenderableList, _camera.Position);

            renderableList.Clear();
            CollectFreeObjects(pass, renderableList);
            renderQueue.AddRange(renderableList, _camera.Position);

            if (comparer == null)
            {
                renderQueue.Sort();
            }
            else
            {
                renderQueue.Sort(comparer);
            }

            foreach (Renderable renderable in renderQueue)
            {
                renderable.Render(gd, rc, sc, pass);
            }

            if (threaded)
            {
                foreach (CullRenderable thing in cullRenderableList)
                {
                    _allPerFrameRenderablesConcurrentBag.Add(thing);
                }
                foreach (Renderable thing in renderableList)
                {
                    _allPerFrameRenderablesConcurrentBag.Add(thing);
                }
            }
            else
            {
                foreach (CullRenderable thing in cullRenderableList)
                {
                    _allPerFrameRenderablesSet.Add(thing);
                }
                foreach (Renderable thing in renderableList)
                {
                    _allPerFrameRenderablesSet.Add(thing);
                }
            }
        }
Beispiel #3
0
        public virtual void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc)
        {
            ResourceFactory factory = gd.ResourceFactory;

            ProjectionMatrixBuffer     = factory.CreateUniformBuffer(new BufferDescription(64));
            ViewMatrixBuffer           = factory.CreateUniformBuffer(new BufferDescription(64));
            LightViewProjectionBuffer0 = factory.CreateUniformBuffer(new BufferDescription(64, true));
            gd.SetResourceName(LightViewProjectionBuffer0, "LightViewProjectionBuffer0");
            LightViewProjectionBuffer1 = factory.CreateUniformBuffer(new BufferDescription(64, true));
            gd.SetResourceName(LightViewProjectionBuffer1, "LightViewProjectionBuffer1");
            LightViewProjectionBuffer2 = factory.CreateUniformBuffer(new BufferDescription(64, true));
            gd.SetResourceName(LightViewProjectionBuffer2, "LightViewProjectionBuffer2");
            DepthLimitsBuffer = factory.CreateUniformBuffer(new BufferDescription((uint)Unsafe.SizeOf <DepthCascadeLimits>()));
            LightInfoBuffer   = factory.CreateUniformBuffer(new BufferDescription((uint)Unsafe.SizeOf <DirectionalLightInfo>()));
            CameraInfoBuffer  = factory.CreateUniformBuffer(new BufferDescription((uint)Unsafe.SizeOf <CameraInfo>()));
            if (Camera != null)
            {
                UpdateCameraBuffers(cl);
            }

            PointLightsBuffer = factory.CreateUniformBuffer(new BufferDescription((uint)Unsafe.SizeOf <PointLightsInfo.Blittable>()));

            PointLightsInfo pli = new PointLightsInfo();

            pli.NumActiveLights = 4;
            pli.PointLights     = new PointLightInfo[4]
            {
                new PointLightInfo {
                    Color = new Vector3(1f, 1f, 1f), Position = new Vector3(-50, 5, 0), Range = 75f
                },
                new PointLightInfo {
                    Color = new Vector3(1f, .75f, .9f), Position = new Vector3(0, 5, 0), Range = 100f
                },
                new PointLightInfo {
                    Color = new Vector3(1f, 1f, 0.6f), Position = new Vector3(50, 5, 0), Range = 40f
                },
                new PointLightInfo {
                    Color = new Vector3(0.75f, 0.75f, 1f), Position = new Vector3(25, 5, 45), Range = 150f
                },
            };

            cl.UpdateBuffer(PointLightsBuffer, 0, pli.GetBlittable());

            NearShadowMapTexture = factory.CreateTexture(new TextureDescription(2048, 2048, 1, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil | TextureUsage.Sampled));
            gd.SetResourceName(NearShadowMapTexture, "Near Shadow Map");
            NearShadowMapView        = factory.CreateTextureView(new TextureViewDescription(NearShadowMapTexture));
            NearShadowMapFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(NearShadowMapTexture));

            MidShadowMapTexture     = factory.CreateTexture(new TextureDescription(2048, 2048, 1, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil | TextureUsage.Sampled));
            MidShadowMapView        = factory.CreateTextureView(new TextureViewDescription(MidShadowMapTexture));
            MidShadowMapFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(MidShadowMapTexture));

            FarShadowMapTexture     = factory.CreateTexture(new TextureDescription(4096, 4096, 1, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil | TextureUsage.Sampled));
            FarShadowMapView        = factory.CreateTextureView(new TextureViewDescription(FarShadowMapTexture));
            FarShadowMapFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(FarShadowMapTexture));
        }
Beispiel #4
0
 public void RenderAllStages(GraphicsDevice gd, CommandList cl, SceneContext sc)
 {
     if (ThreadedRendering)
     {
         RenderAllMultiThreaded(gd, cl, sc);
     }
     else
     {
         RenderAllSingleThread(gd, cl, sc);
     }
 }
Beispiel #5
0
 public override void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc)
 {
     if (_imguiRenderer == null)
     {
         _imguiRenderer = new ImGuiRenderer(gd, cl, gd.SwapchainFramebuffer.OutputDescription, _width, _height);
     }
     else
     {
         _imguiRenderer.CreateDeviceResources(gd, cl, gd.SwapchainFramebuffer.OutputDescription);
     }
 }
Beispiel #6
0
 public override void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc)
 {
     if (_imguiRenderer == null)
     {
         _imguiRenderer = new ImGuiRenderer(gd, sc.MainSceneFramebuffer.OutputDescription, _width, _height, ColorSpaceHandling.Linear);
     }
     else
     {
         _imguiRenderer.CreateDeviceResources(gd, sc.MainSceneFramebuffer.OutputDescription, ColorSpaceHandling.Linear);
     }
 }
Beispiel #7
0
        internal void CreateAllDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc)
        {
            _cullableStage[0].Clear();
            _octree.GetAllContainedObjects(_cullableStage[0]);
            foreach (CullRenderable cr in _cullableStage[0])
            {
                cr.CreateDeviceObjects(gd, cl, sc);
            }
            foreach (Renderable r in _freeRenderables)
            {
                r.CreateDeviceObjects(gd, cl, sc);
            }

            _resourceUpdateCL      = gd.ResourceFactory.CreateCommandList();
            _resourceUpdateCL.Name = "Scene Resource Update Command List";
        }
Beispiel #8
0
        private Matrix4x4 UpdateDirectionalLightMatrices(
            SceneContext sc,
            float near,
            float far,
            int shadowMapWidth,
            out BoundingFrustum lightFrustum)
        {
            Vector3 lightDir = sc.DirectionalLight.Direction;
            Vector3 viewDir  = sc.Camera.LookDirection;
            Vector3 viewPos  = sc.Camera.Position;
            Vector3 unitY    = Vector3.UnitY;

            FrustumHelpers.ComputePerspectiveFrustumCorners(
                ref viewPos,
                ref viewDir,
                ref unitY,
                sc.Camera.FieldOfView,
                near,
                far,
                sc.Camera.AspectRatio,
                out FrustumCorners cameraCorners);

            // Approach used: http://alextardif.com/ShadowMapping.html

            Vector3 frustumCenter = Vector3.Zero;

            frustumCenter += cameraCorners.NearTopLeft;
            frustumCenter += cameraCorners.NearTopRight;
            frustumCenter += cameraCorners.NearBottomLeft;
            frustumCenter += cameraCorners.NearBottomRight;
            frustumCenter += cameraCorners.FarTopLeft;
            frustumCenter += cameraCorners.FarTopRight;
            frustumCenter += cameraCorners.FarBottomLeft;
            frustumCenter += cameraCorners.FarBottomRight;
            frustumCenter /= 8f;

            float radius        = (cameraCorners.NearTopLeft - cameraCorners.FarBottomRight).Length() / 2.0f;
            float texelsPerUnit = shadowMapWidth / (radius * 2.0f);

            Matrix4x4 scalar = Matrix4x4.CreateScale(texelsPerUnit, texelsPerUnit, texelsPerUnit);

            Vector3 baseLookAt = -lightDir;

            Matrix4x4 lookat = Matrix4x4.CreateLookAt(Vector3.Zero, baseLookAt, Vector3.UnitY);

            lookat = scalar * lookat;
            Matrix4x4.Invert(lookat, out Matrix4x4 lookatInv);

            frustumCenter   = Vector3.Transform(frustumCenter, lookat);
            frustumCenter.X = (int)frustumCenter.X;
            frustumCenter.Y = (int)frustumCenter.Y;
            frustumCenter   = Vector3.Transform(frustumCenter, lookatInv);

            Vector3 lightPos = frustumCenter - (lightDir * radius * 2f);

            Matrix4x4 lightView = Matrix4x4.CreateLookAt(lightPos, frustumCenter, Vector3.UnitY);

            Matrix4x4 lightProjection = Matrix4x4.CreateOrthographicOffCenter(
                -radius * _lScale,
                radius * _rScale,
                -radius * _bScale,
                radius * _tScale,
                -radius * _nScale,
                radius * _fScale);
            Matrix4x4 viewProjectionMatrix = lightView * lightProjection;

            lightFrustum = new BoundingFrustum(lightProjection);
            return(viewProjectionMatrix);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
 public override void UpdatePerFrameResources(GraphicsDevice gd, CommandList cl, SceneContext sc)
 {
 }
Beispiel #11
0
 public override void Render(RenderContext rc, SceneContext sc, RenderPasses renderPass)
 {
     Debug.Assert(renderPass == RenderPasses.Overlay);
     _imguiRenderer.Render(rc);
 }
Beispiel #12
0
 public abstract void Render(GraphicsDevice gd, CommandList cl, SceneContext sc, RenderPasses renderPass);
Beispiel #13
0
 public abstract void UpdatePerFrameResources(GraphicsDevice gd, CommandList cl, SceneContext sc);
Beispiel #14
0
 public abstract void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc);
Beispiel #15
0
        private void RenderAllSingleThread(GraphicsDevice gd, CommandList cl, SceneContext sc)
        {
            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());

            // Near
            Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices(
                sc,
                Camera.NearDistance,
                _nearCascadeLimit,
                sc.NearShadowMapTexture.Width,
                out BoundingFrustum lightFrustum);

            cl.UpdateBuffer(sc.LightViewProjectionBuffer0, 0, ref viewProj0);
            cl.SetFramebuffer(sc.NearShadowMapFramebuffer);
            cl.SetViewport(0, new Viewport(0, 0, sc.NearShadowMapTexture.Width, sc.NearShadowMapTexture.Height, 0, 1));
            cl.SetScissorRect(0, 0, 0, sc.NearShadowMapTexture.Width, sc.NearShadowMapTexture.Height);
            cl.ClearDepthTarget(01f);
            Render(gd, cl, sc, RenderPasses.ShadowMapNear, lightFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);

            // Mid
            Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices(
                sc,
                _nearCascadeLimit,
                _midCascadeLimit,
                sc.MidShadowMapTexture.Width,
                out lightFrustum);

            cl.UpdateBuffer(sc.LightViewProjectionBuffer1, 0, ref viewProj1);
            cl.SetFramebuffer(sc.MidShadowMapFramebuffer);
            cl.SetViewport(0, new Viewport(0, 0, sc.MidShadowMapTexture.Width, sc.MidShadowMapTexture.Height, 0, 1));
            cl.SetScissorRect(0, 0, 0, sc.MidShadowMapTexture.Width, sc.MidShadowMapTexture.Height);
            cl.ClearDepthTarget(1f);
            Render(gd, cl, sc, RenderPasses.ShadowMapMid, lightFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);

            // Far
            Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices(
                sc,
                _midCascadeLimit,
                _farCascadeLimit,
                sc.FarShadowMapTexture.Width,
                out lightFrustum);

            cl.UpdateBuffer(sc.LightViewProjectionBuffer2, 0, ref viewProj2);
            cl.SetFramebuffer(sc.FarShadowMapFramebuffer);
            cl.SetViewport(0, new Viewport(0, 0, sc.FarShadowMapTexture.Width, sc.FarShadowMapTexture.Height, 0, 1));
            cl.SetScissorRect(0, 0, 0, sc.FarShadowMapTexture.Width, sc.FarShadowMapTexture.Height);
            cl.ClearDepthTarget(1f);
            Render(gd, cl, sc, RenderPasses.ShadowMapFar, lightFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);

            cl.SetFramebuffer(gd.SwapchainFramebuffer);
            float scWidth  = gd.SwapchainFramebuffer.Width;
            float scHeight = gd.SwapchainFramebuffer.Height;

            cl.SetViewport(0, new Viewport(0, 0, scWidth, scHeight, 0, 1));
            cl.SetScissorRect(0, 0, 0, (uint)scWidth, (uint)scHeight);
            cl.ClearColorTarget(0, RgbaFloat.CornflowerBlue);
            cl.ClearDepthTarget(1f);
            BoundingFrustum cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix);

            Render(gd, cl, sc, RenderPasses.Standard, cameraFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);
            Render(gd, cl, sc, RenderPasses.AlphaBlend, cameraFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);
            Render(gd, cl, sc, RenderPasses.Overlay, cameraFrustum, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, false);

            _resourceUpdateCL.Begin();
            foreach (Renderable renderable in _allPerFrameRenderablesSet)
            {
                renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc);
            }
            _resourceUpdateCL.End();
            gd.ExecuteCommands(_resourceUpdateCL);
        }
Beispiel #16
0
        public void RenderAllStages(RenderContext rc, SceneContext sc)
        {
            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);

            sc.DepthLimitsBuffer.SetData(new DepthCascadeLimits
            {
                NearLimit = nearLimitCS.Z,
                MidLimit  = midLimitCS.Z,
                FarLimit  = farLimitCS.Z
            });

            sc.LightInfoBuffer.SetData(sc.DirectionalLight.GetInfo());

            // Near
            Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices(
                sc,
                Camera.NearDistance,
                _nearCascadeLimit,
                sc.NearShadowMapTexture.Width,
                out BoundingFrustum lightFrustum);

            sc.LightViewProjectionBuffer0.SetData(ref viewProj0);
            sc.CurrentLightViewProjectionBuffer = sc.LightViewProjectionBuffer0;
            rc.SetFramebuffer(sc.NearShadowMapFramebuffer);
            rc.SetViewport(0, 0, sc.NearShadowMapTexture.Width, sc.NearShadowMapTexture.Height);
            rc.ClearBuffer();
            Render(rc, sc, RenderPasses.ShadowMap, lightFrustum, null);

            // Mid
            Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices(
                sc,
                _nearCascadeLimit,
                _midCascadeLimit,
                sc.MidShadowMapTexture.Width,
                out lightFrustum);

            sc.LightViewProjectionBuffer1.SetData(ref viewProj1);
            sc.CurrentLightViewProjectionBuffer = sc.LightViewProjectionBuffer1;
            rc.SetFramebuffer(sc.MidShadowMapFramebuffer);
            rc.SetViewport(0, 0, sc.MidShadowMapTexture.Width, sc.MidShadowMapTexture.Height);
            rc.ClearBuffer();
            Render(rc, sc, RenderPasses.ShadowMap, lightFrustum, null);

            // Far
            Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices(
                sc,
                _midCascadeLimit,
                _farCascadeLimit,
                sc.FarShadowMapTexture.Width,
                out lightFrustum);

            sc.LightViewProjectionBuffer2.SetData(ref viewProj2);
            sc.CurrentLightViewProjectionBuffer = sc.LightViewProjectionBuffer2;
            rc.SetFramebuffer(sc.FarShadowMapFramebuffer);
            rc.SetViewport(0, 0, sc.FarShadowMapTexture.Width, sc.FarShadowMapTexture.Height);
            rc.ClearBuffer();
            Render(rc, sc, RenderPasses.ShadowMap, lightFrustum, null);

            rc.SetDefaultFramebuffer();
            rc.SetViewport(0, 0, rc.CurrentFramebuffer.Width, rc.CurrentFramebuffer.Height);
            BoundingFrustum cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix);

            Render(rc, sc, RenderPasses.Standard, cameraFrustum, null);
            Render(rc, sc, RenderPasses.AlphaBlend, cameraFrustum, null);
            Render(rc, sc, RenderPasses.Overlay, cameraFrustum, null);
        }
Beispiel #17
0
 public abstract void Render(RenderContext rc, SceneContext sc, RenderPasses renderPass);
Beispiel #18
0
 public override void Render(GraphicsDevice gd, CommandList cl, SceneContext sc, RenderPasses renderPass)
 {
     Debug.Assert(renderPass == RenderPasses.Overlay);
     _imguiRenderer.Render(gd, cl);
 }
Beispiel #19
0
        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);
        }
        public virtual void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc)
        {
            ResourceFactory factory = gd.ResourceFactory;

            ProjectionMatrixBuffer          = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            ViewMatrixBuffer                = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            LightViewProjectionBuffer0      = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            LightViewProjectionBuffer0.Name = "LightViewProjectionBuffer0";
            LightViewProjectionBuffer1      = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            LightViewProjectionBuffer1.Name = "LightViewProjectionBuffer1";
            LightViewProjectionBuffer2      = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            LightViewProjectionBuffer2.Name = "LightViewProjectionBuffer2";
            DepthLimitsBuffer               = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DepthCascadeLimits>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            LightInfoBuffer  = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DirectionalLightInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            CameraInfoBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <CameraInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic));
            if (Camera != null)
            {
                UpdateCameraBuffers(cl);
            }

            PointLightsBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <PointLightsInfo.Blittable>(), BufferUsage.UniformBuffer));

            PointLightsInfo pli = new PointLightsInfo();

            pli.NumActiveLights = 4;
            pli.PointLights     = new PointLightInfo[4]
            {
                new PointLightInfo {
                    Color = new Vector3(1f, 1f, 1f), Position = new Vector3(-50, 5, 0), Range = 75f
                },
                new PointLightInfo {
                    Color = new Vector3(1f, .75f, .9f), Position = new Vector3(0, 5, 0), Range = 100f
                },
                new PointLightInfo {
                    Color = new Vector3(1f, 1f, 0.6f), Position = new Vector3(50, 5, 0), Range = 40f
                },
                new PointLightInfo {
                    Color = new Vector3(0.75f, 0.75f, 1f), Position = new Vector3(25, 5, 45), Range = 150f
                },
            };

            cl.UpdateBuffer(PointLightsBuffer, 0, pli.GetBlittable());

            TextureSamplerResourceLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                            new ResourceLayoutElementDescription("SourceTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                            new ResourceLayoutElementDescription("SourceSampler", ResourceKind.Sampler, ShaderStages.Fragment)));

            uint ReflectionMapSize = 2048;

            ReflectionColorTexture   = factory.CreateTexture(TextureDescription.Texture2D(ReflectionMapSize, ReflectionMapSize, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled));
            ReflectionDepthTexture   = factory.CreateTexture(TextureDescription.Texture2D(ReflectionMapSize, ReflectionMapSize, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil));
            ReflectionColorView      = factory.CreateTextureView(ReflectionColorTexture);
            ReflectionFramebuffer    = factory.CreateFramebuffer(new FramebufferDescription(ReflectionDepthTexture, ReflectionColorTexture));
            ReflectionViewProjBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            MirrorClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer));
            gd.UpdateBuffer(MirrorClipPlaneBuffer, 0, new ClipPlaneInfo(MirrorMesh.Plane, true));
            NoClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer));
            gd.UpdateBuffer(NoClipPlaneBuffer, 0, new ClipPlaneInfo());

            RecreateWindowSizedResources(gd, cl);

            ShadowMaps.CreateDeviceResources(gd);
        }
Beispiel #21
0
        private void RenderAllMultiThreaded(GraphicsDevice gd, SceneContext sc)
        {
            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);

            _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());

            _allPerFrameRenderablesConcurrentBag.Clear();
            _tasks[0] = Task.Run(() =>
            {
                // Near
                Matrix4x4 viewProj0 = UpdateDirectionalLightMatrices(
                    sc,
                    Camera.NearDistance,
                    _nearCascadeLimit,
                    sc.NearShadowMapTexture.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.NearShadowMapTexture.Width, sc.NearShadowMapTexture.Height, 0, 1));
                cls[1].SetScissorRect(0, 0, 0, sc.NearShadowMapTexture.Width, sc.NearShadowMapTexture.Height);
                cls[1].ClearDepthTarget(1f);
                Render(gd, cls[1], sc, RenderPasses.ShadowMapNear, lightFrustum0, _renderQueues[0], _cullableStage[0], _renderableStage[0], null, true);
            });

            _tasks[1] = Task.Run(() =>
            {
                // Mid
                Matrix4x4 viewProj1 = UpdateDirectionalLightMatrices(
                    sc,
                    _nearCascadeLimit,
                    _midCascadeLimit,
                    sc.MidShadowMapTexture.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.MidShadowMapTexture.Width, sc.MidShadowMapTexture.Height, 0, 1));
                cls[2].SetScissorRect(0, 0, 0, sc.MidShadowMapTexture.Width, sc.MidShadowMapTexture.Height);
                cls[2].ClearDepthTarget(1f);
                Render(gd, cls[2], sc, RenderPasses.ShadowMapMid, lightFrustum1, _renderQueues[1], _cullableStage[1], _renderableStage[1], null, true);
            });

            _tasks[2] = Task.Run(() =>
            {
                // Far
                Matrix4x4 viewProj2 = UpdateDirectionalLightMatrices(
                    sc,
                    _midCascadeLimit,
                    _farCascadeLimit,
                    sc.FarShadowMapTexture.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.FarShadowMapTexture.Width, sc.FarShadowMapTexture.Height, 0, 1));
                cls[3].SetScissorRect(0, 0, 0, sc.FarShadowMapTexture.Width, sc.FarShadowMapTexture.Height);
                cls[3].ClearDepthTarget(1f);
                Render(gd, cls[3], sc, RenderPasses.ShadowMapFar, lightFrustum2, _renderQueues[2], _cullableStage[2], _renderableStage[2], null, true);
            });

            _tasks[3] = Task.Run(() =>
            {
                cls[4].SetFramebuffer(gd.SwapchainFramebuffer);
                float scWidth  = gd.SwapchainFramebuffer.Width;
                float scHeight = gd.SwapchainFramebuffer.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].ClearDepthTarget(1f);
                BoundingFrustum cameraFrustum = new BoundingFrustum(_camera.ViewMatrix * _camera.ProjectionMatrix);
                Render(gd, cls[4], sc, RenderPasses.Standard, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true);
                Render(gd, cls[4], sc, RenderPasses.AlphaBlend, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true);
                Render(gd, cls[4], sc, RenderPasses.Overlay, cameraFrustum, _renderQueues[3], _cullableStage[3], _renderableStage[3], null, true);
            });

            Task.WaitAll(_tasks);

            foreach (Renderable renderable in _allPerFrameRenderablesConcurrentBag.ToHashSet())
            {
                renderable.UpdatePerFrameResources(gd, _resourceUpdateCL, sc);
            }
            _resourceUpdateCL.End();
            gd.ExecuteCommands(_resourceUpdateCL);

            for (int i = 0; i < cls.Length; i++)
            {
                cls[i].End(); gd.ExecuteCommands(cls[i]); cls[i].Dispose();
            }
        }