diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-04-27 16:43:56 +0200 |
|---|---|---|
| committer | j-p <jp_bruyere@hotmail.com> | 2019-05-02 03:07:11 +0200 |
| commit | 58eddf11cc951caca5aca1e7f33610fc1e58e5ff (patch) | |
| tree | 3ff0e390e498be1894900cbc8bf543200139f894 | |
| parent | 04160ef015304a7f28308ea43aa1a959b84a78fc (diff) | |
Renderer class, lights ubo for multiple light handling
| -rw-r--r-- | samples/deferred/deferred.csproj | 2 | ||||
| -rw-r--r-- | samples/deferred/deferredPbrRenderer.cs | 452 | ||||
| -rw-r--r-- | samples/deferred/main.cs | 477 | ||||
| -rw-r--r-- | samples/deferred/shaders/GBuffPbr.frag | 9 | ||||
| -rw-r--r-- | samples/deferred/shaders/GBuffPbr.vert | 3 | ||||
| -rw-r--r-- | samples/deferred/shaders/compose.frag | 102 | ||||
| -rw-r--r-- | samples/deferred/shaders/debug.vert | 3 | ||||
| -rw-r--r-- | samples/deferred/shaders/tone_mapping.frag | 3 | ||||
| -rw-r--r-- | vke/src/CommandPool.cs | 13 | ||||
| -rw-r--r-- | vke/src/Device.cs | 11 | ||||
| -rw-r--r-- | vke/src/Model.cs | 5 |
11 files changed, 564 insertions, 516 deletions
diff --git a/samples/deferred/deferred.csproj b/samples/deferred/deferred.csproj index 7fca916..0b3a0ad 100644 --- a/samples/deferred/deferred.csproj +++ b/samples/deferred/deferred.csproj @@ -29,7 +29,7 @@ <Datas Include="..\data\**\*.*"> <Link>data\%(RecursiveDir)%(Filename)%(Extension)</Link> </Datas> - <Compile Include="main.cs;EnvironmentPipeline.cs" /> + <Compile Include="main.cs;EnvironmentPipeline.cs;deferredPbrRenderer.cs" /> </ItemGroup> <ItemGroup> <Reference Include="System.Numerics" /> diff --git a/samples/deferred/deferredPbrRenderer.cs b/samples/deferred/deferredPbrRenderer.cs new file mode 100644 index 0000000..2099670 --- /dev/null +++ b/samples/deferred/deferredPbrRenderer.cs @@ -0,0 +1,452 @@ +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using Glfw; +using VK; +using CVKL; + +namespace deferred { + class DeferredPbrRenderer : IDisposable { + Device dev; + SwapChain swapChain; + PresentQueue presentQueue; + + VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4; + VkFormat hdrFormat = VkFormat.R32g32b32a32Sfloat; + + public enum DebugView { + none, + color, + normal, + pos, + occlusion, + emissive, + metallic, + roughness, + depth, + prefill, + irradiance + } + + public DebugView currentDebugView = DebugView.none; + + public struct Matrices { + public Matrix4x4 projection; + public Matrix4x4 model; + public Matrix4x4 view; + public Vector4 camPos; + public float exposure; + public float gamma; + public float prefilteredCubeMipLevels; + public float scaleIBLAmbient; + } + + public struct Light { + public Vector4 position; + public Vector4 color; + } + + public Matrices matrices = new Matrices { + gamma = 1.2f, + exposure = 2.0f, + scaleIBLAmbient = 1.0f, + }; + + Light[] lights = { + new Light { + position = new Vector4(1), + color = new Vector4(1) + } + }; + public Vector4 lightPos = new Vector4 (1, 0, 0, 0); + + Framebuffer[] frameBuffers; + Image gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg; + + DescriptorPool descriptorPool; + DescriptorSetLayout descLayoutMain, descLayoutTextures, descLayoutGBuff; + DescriptorSet dsMain, dsGBuff; + + public PipelineCache pipelineCache; + Pipeline gBuffPipeline, composePipeline, toneMappingPipeline, debugPipeline; + + HostBuffer uboMatrices, uboLights; + + RenderPass renderPass; + + PbrModel model; + public EnvironmentCube envCube; + + public BoundingBox modelAABB; + + const int SP_SKYBOX = 0; + const int SP_MODELS = 1; + const int SP_COMPOSE = 2; + const int SP_TONE_MAPPING = 3; + + public DeferredPbrRenderer (Device dev, SwapChain swapChain, PresentQueue presentQueue, float nearPlane, float farPlane) { + this.dev = dev; + this.swapChain = swapChain; + this.presentQueue = presentQueue; + + pipelineCache = new PipelineCache (dev); + + init (nearPlane, farPlane); + } + + void init (float nearPlane, float farPlane) { + + renderPass = new RenderPass (dev, samples); + + renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1);//swapchain image + renderPass.AddAttachment (dev.GetSuitableDepthFormat(), VkImageLayout.DepthStencilAttachmentOptimal, samples); + renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff0 (color + roughness) and final color before resolve + renderPass.AddAttachment (VkFormat.R8g8b8a8Unorm, VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff1 (emit + metal) + renderPass.AddAttachment (VkFormat.R16g16b16a16Sfloat, VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff2 (normals + AO) + renderPass.AddAttachment (VkFormat.R16g16b16a16Sfloat, VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff3 (Pos + depth) + renderPass.AddAttachment (hdrFormat, VkImageLayout.ColorAttachmentOptimal, samples);//hdr color + + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + + SubPass[] subpass = { new SubPass (), new SubPass (), new SubPass(), new SubPass() }; + //skybox + subpass[SP_SKYBOX].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); + //models + subpass[SP_MODELS].AddColorReference (new VkAttachmentReference (2, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (3, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (4, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (5, VkImageLayout.ColorAttachmentOptimal)); + subpass[SP_MODELS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); + subpass[SP_MODELS].AddPreservedReference (0); + + //compose + subpass[SP_COMPOSE].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); + subpass[SP_COMPOSE].AddInputReference (new VkAttachmentReference (2, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (3, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (4, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (5, VkImageLayout.ShaderReadOnlyOptimal)); + //tone mapping + subpass[SP_TONE_MAPPING].AddColorReference ((samples == VkSampleCountFlags.SampleCount1) ? 0u : 2u, VkImageLayout.ColorAttachmentOptimal); + subpass[SP_TONE_MAPPING].AddInputReference (new VkAttachmentReference (6, VkImageLayout.ShaderReadOnlyOptimal)); + if (samples != VkSampleCountFlags.SampleCount1) + subpass[SP_TONE_MAPPING].AddResolveReference (0, VkImageLayout.ColorAttachmentOptimal); + + renderPass.AddSubpass (subpass); + + renderPass.AddDependency (Vk.SubpassExternal, SP_SKYBOX, + VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, + VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); + renderPass.AddDependency (SP_SKYBOX, SP_MODELS, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_MODELS, SP_COMPOSE, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_COMPOSE, SP_TONE_MAPPING, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_TONE_MAPPING, Vk.SubpassExternal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, + VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead); + + + descriptorPool = new DescriptorPool (dev, 3, + new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 3), + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 3), + new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 6) + ); + + descLayoutMain = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//matrices and params + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//lights + new VkDescriptorSetLayoutBinding (5, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer));//materials + + descLayoutTextures = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) + ); + + descLayoutGBuff = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//color + roughness + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//emit + metal + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//normals + AO + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//Pos + depth + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment));//hdr + + dsMain = descriptorPool.Allocate (descLayoutMain); + dsGBuff = descriptorPool.Allocate (descLayoutGBuff); + + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples); + + if (samples != VkSampleCountFlags.SampleCount1) { + cfg.multisampleState.sampleShadingEnable = true; + cfg.multisampleState.minSampleShading = 0.5f; + } + cfg.Cache = pipelineCache; + cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutTextures, descLayoutGBuff); + cfg.Layout.AddPushConstants ( + new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), + new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64) + ); + cfg.RenderPass = renderPass; + cfg.SubpassIndex = SP_MODELS; + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + //cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + + cfg.AddVertexBinding<PbrModel.Vertex> (0); + cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); + + using (SpecializationInfo constants = new SpecializationInfo ( + new SpecializationConstant<float> (0, nearPlane), + new SpecializationConstant<float> (1, farPlane))) { + + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/GBuffPbr.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/GBuffPbr.frag.spv", constants); + + gBuffPipeline = new GraphicPipeline (cfg); + } + + //COMPOSE PIPELINE + cfg.blendAttachments.Clear (); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + cfg.ResetShadersAndVerticesInfos (); + cfg.SubpassIndex = SP_COMPOSE; + cfg.Layout = gBuffPipeline.Layout; + cfg.depthStencilState.depthTestEnable = false; + cfg.depthStencilState.depthWriteEnable = false; + using (SpecializationInfo constants = new SpecializationInfo ( + new SpecializationConstant<uint> (0, (uint)lights.Length))) { + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/compose.frag.spv", constants); + composePipeline = new GraphicPipeline (cfg); + } + //DEBUG DRAW use subpass of compose + cfg.shaders[1] = new ShaderInfo (VkShaderStageFlags.Fragment, "shaders/show_gbuff.frag.spv"); + cfg.SubpassIndex = SP_COMPOSE; + debugPipeline = new GraphicPipeline (cfg); + //TONE MAPPING + cfg.shaders[1] = new ShaderInfo (VkShaderStageFlags.Fragment, "shaders/tone_mapping.frag.spv"); + cfg.SubpassIndex = SP_TONE_MAPPING; + toneMappingPipeline = new GraphicPipeline (cfg); + + envCube = new EnvironmentCube (dsMain, gBuffPipeline.Layout, presentQueue, renderPass); + + matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; + uboMatrices = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true); + uboLights = new HostBuffer<Light> (dev, VkBufferUsageFlags.UniformBuffer, lights, true); + + string[] modelPathes = { + "../data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", + "/home/jp/gltf/chessold/scene.gltf", + "../data/models/Hubble.glb", + "../data/models/MER_static.glb", + "../data/models/ISS_stationary.glb", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Avocado/glTF/Avocado.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BarramundiFish/glTF/BarramundiFish.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BoomBoxWithAxes/glTF/BoomBoxWithAxes.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Box/glTF/Box.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/EnvironmentTest/glTF/EnvironmentTest.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/OrientationTest/glTF/OrientationTest.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Buggy/glTF/Buggy.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/2CylinderEngine/glTF-Embedded/2CylinderEngine.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/FlightHelmet/glTF/FlightHelmet.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/GearboxAssy/glTF/GearboxAssy.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Lantern/glTF/Lantern.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/SciFiHelmet/glTF/SciFiHelmet.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Sponza/glTF/Sponza.gltf", + "/mnt/devel/vkChess/data/chess.gltf", + "/home/jp/gltf/camaro/scene.gltf" + }; + + model = new PbrModel (presentQueue, modelPathes[0], + descLayoutTextures, + AttachmentType.Color, + AttachmentType.PhysicalProps, + AttachmentType.Normal, + AttachmentType.AmbientOcclusion, + AttachmentType.Emissive); + //model = new Model (presentQueue, "../data/models/chess.gltf"); + //model = new Model (presentQueue, "../data/models/Sponza/glTF/Sponza.gltf"); + //model = new Model (dev, presentQueue, "../data/models/icosphere.gltf"); + //model = new Model (dev, presentQueue, cmdPool, "../data/models/cube.gltf"); + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutMain); + uboUpdate.Write (dev, dsMain, + uboMatrices.Descriptor, + envCube.irradianceCube.Descriptor, + envCube.prefilterCube.Descriptor, + envCube.lutBrdf.Descriptor, + uboLights.Descriptor, + model.materialUBO.Descriptor); + + modelAABB = model.DefaultScene.AABB; + } + + public void buildCommandBuffers (CommandBuffer[] cmds) { + for (int i = 0; i < swapChain.ImageCount; ++i) { + cmds[i].Start (); + recordDraw (cmds[i], frameBuffers[i]); + cmds[i].End (); + } + } + + void recordDraw (CommandBuffer cmd, Framebuffer fb) { + renderPass.Begin (cmd, fb); + + cmd.SetViewport (fb.Width, fb.Height); + cmd.SetScissor (fb.Width, fb.Height); + + cmd.BindDescriptorSet (gBuffPipeline.Layout, dsMain); + + envCube.RecordDraw (cmd); + renderPass.BeginSubPass (cmd); + + gBuffPipeline.Bind (cmd); + model.Bind (cmd); + model.DrawAll (cmd, gBuffPipeline.Layout); + + renderPass.BeginSubPass (cmd); + + cmd.BindDescriptorSet (composePipeline.Layout, dsGBuff, 2); + + if (currentDebugView == DebugView.none) + composePipeline.Bind (cmd); + else { + debugPipeline.Bind (cmd); + uint debugValue = (uint)currentDebugView - 1; + debugValue += (uint)((envCube.debugFace << 8) + (envCube.debugMip << 16)); + cmd.PushConstant (debugPipeline.Layout, VkShaderStageFlags.Fragment, debugValue, (uint)Marshal.SizeOf<Matrix4x4> ()); + } + + cmd.Draw (3, 1, 0, 0); + + renderPass.BeginSubPass (cmd); + toneMappingPipeline.Bind (cmd); + cmd.Draw (3, 1, 0, 0); + + renderPass.End (cmd); + } + + #region update + public void UpdateView (Camera camera) { + camera.AspectRatio = (float)swapChain.Width / swapChain.Height; + + lights[0].position = lightPos; + + matrices.projection = camera.Projection; + matrices.view = camera.View; + matrices.model = camera.Model; + + + matrices.camPos = new Vector4 ( + -camera.Position.Z * (float)Math.Sin (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + camera.Position.Z * (float)Math.Sin (camera.Rotation.X), + camera.Position.Z * (float)Math.Cos (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + 0 + ); + + uboMatrices.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); + } + + #endregion + + void createGBuff () { + gbColorRough?.Dispose (); + gbEmitMetal?.Dispose (); + gbN_AO?.Dispose (); + gbPos?.Dispose (); + hdrImg?.Dispose (); + + gbColorRough = new Image (dev, swapChain.ColorFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); + gbEmitMetal = new Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); + gbN_AO = new Image (dev, VkFormat.R16g16b16a16Sfloat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); + gbPos = new Image (dev, VkFormat.R16g16b16a16Sfloat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); + hdrImg = new Image (dev, hdrFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal | VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); + + gbColorRough.CreateView (); + gbColorRough.CreateSampler (); + gbColorRough.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbEmitMetal.CreateView (); + gbEmitMetal.CreateSampler (); + gbEmitMetal.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbN_AO.CreateView (); + gbN_AO.CreateSampler (); + gbN_AO.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbPos.CreateView (); + gbPos.CreateSampler (); + gbPos.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + hdrImg.CreateView (); + hdrImg.CreateSampler (); + hdrImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutGBuff); + uboUpdate.Write (dev, dsGBuff, gbColorRough.Descriptor, + gbEmitMetal.Descriptor, + gbN_AO.Descriptor, + gbPos.Descriptor, + hdrImg.Descriptor); + gbColorRough.SetName ("GBuffColorRough"); + gbEmitMetal.SetName ("GBuffEmitMetal"); + gbN_AO.SetName ("GBuffN"); + gbPos.SetName ("GBuffPos"); + hdrImg.SetName ("HDRimg"); + } + + public void Resize () { + if (frameBuffers != null) + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i]?.Dispose (); + + createGBuff (); + + frameBuffers = new Framebuffer[swapChain.ImageCount]; + + for (int i = 0; i < swapChain.ImageCount; ++i) { + frameBuffers[i] = new Framebuffer (renderPass, swapChain.Width, swapChain.Height, new Image[] { + swapChain.images[i], null, gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg}); + } + } + + public void Dispose () { + dev.WaitIdle (); + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i]?.Dispose (); + + gbColorRough.Dispose (); + gbEmitMetal.Dispose (); + gbN_AO.Dispose (); + gbPos.Dispose (); + hdrImg.Dispose (); + + gBuffPipeline.Dispose (); + composePipeline.Dispose (); + toneMappingPipeline.Dispose (); + debugPipeline.Dispose (); + + descLayoutMain.Dispose (); + descLayoutTextures.Dispose (); + descLayoutGBuff.Dispose (); + + uboMatrices.Dispose (); + uboLights.Dispose (); + model.Dispose (); + envCube.Dispose (); + + descriptorPool.Dispose (); + } + } +} diff --git a/samples/deferred/main.cs b/samples/deferred/main.cs index def9ee0..c20be6e 100644 --- a/samples/deferred/main.cs +++ b/samples/deferred/main.cs @@ -21,422 +21,38 @@ namespace deferred { VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4; VkFormat hdrFormat = VkFormat.R32g32b32a32Sfloat; - enum DebugView { - none, - color, - normal, - pos, - occlusion, - emissive, - metallic, - roughness, - depth, - prefill, - irradiance - } - - DebugView currentDebugView = DebugView.none; - - public struct Matrices { - public Matrix4x4 projection; - public Matrix4x4 model; - public Matrix4x4 view; - public Vector4 camPos; - public Vector4 lightPos; - public float exposure; - public float gamma; - public float prefilteredCubeMipLevels; - public float scaleIBLAmbient; - public uint lightsCount; - public float debugViewEquation; - } - - public struct Light { - public Vector4 position; - public Vector4 color; - } - - public Matrices matrices = new Matrices { - lightPos = Vector4.Normalize (new Vector4 (0.7f, 0.6f, 0.2f, 0.0f)), - gamma = 1.2f, - exposure = 2.0f, - scaleIBLAmbient = 1.0f, - lightsCount = 1, - debugViewEquation = 0 - }; - - Light[] lights = { - new Light { - position = new Vector4(1,1,1,0), - color = new Vector4(1) - } - }; - - Framebuffer[] frameBuffers; - Image gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg; - - DescriptorPool descriptorPool; - DescriptorSetLayout descLayoutMain, descLayoutTextures, descLayoutGBuff; - DescriptorSet dsMain, dsGBuff; - - PipelineCache pipelineCache; - Pipeline gBuffPipeline, composePipeline, toneMappingPipeline, debugPipeline; - - HostBuffer uboMats; - - RenderPass renderPass; - - PbrModel model; - EnvironmentCube envCube; - - Vector4 lightPos = new Vector4 (1, 0, 0, 0); - BoundingBox modelAABB; - - const int SP_SKYBOX = 0; - const int SP_MODELS = 1; - const int SP_COMPOSE = 2; - const int SP_TONE_MAPPING = 3; + DeferredPbrRenderer renderer; Program () { - pipelineCache = new PipelineCache (dev); - camera = new Camera (Utils.DegreesToRadians (45f), 1f, 0.1f, 16f); - - init (); - camera.SetPosition (0, 0, 3); - camera.Model = Matrix4x4.CreateScale (1f / Math.Max (Math.Max (modelAABB.max.X, modelAABB.max.Y), modelAABB.max.Z)); - //camera.Model = Matrix4x4.CreateScale (0.02f); - } - - void init () { - - renderPass = new RenderPass (dev, samples); - - renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1);//swapchain image - renderPass.AddAttachment (dev.GetSuitableDepthFormat(), VkImageLayout.DepthStencilAttachmentOptimal, samples); - renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.ColorAttachmentOptimal, samples);//GBuff0 (color + roughness) and final color before resolve - renderPass.AddAttachment (VkFormat.R8g8b8a8Unorm, VkImageLayout.ColorAttachmentOptimal, samples);//GBuff1 (emit + metal) - renderPass.AddAttachment (VkFormat.R16g16b16a16Sfloat, VkImageLayout.ColorAttachmentOptimal, samples);//GBuff2 (normals + AO) - renderPass.AddAttachment (VkFormat.R16g16b16a16Sfloat, VkImageLayout.ColorAttachmentOptimal, samples);//GBuff3 (Pos + depth) - renderPass.AddAttachment (hdrFormat, VkImageLayout.ColorAttachmentOptimal, samples);//hdr color - - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - - SubPass[] subpass = { new SubPass (), new SubPass (), new SubPass(), new SubPass() }; - //skybox - subpass[SP_SKYBOX].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); - //models - subpass[SP_MODELS].AddColorReference (new VkAttachmentReference (2, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (3, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (4, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (5, VkImageLayout.ColorAttachmentOptimal)); - subpass[SP_MODELS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); - subpass[SP_MODELS].AddPreservedReference (0); - - //compose - subpass[SP_COMPOSE].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); - subpass[SP_COMPOSE].AddInputReference (new VkAttachmentReference (2, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (3, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (4, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (5, VkImageLayout.ShaderReadOnlyOptimal)); - //tone mapping - subpass[SP_TONE_MAPPING].AddColorReference ((samples == VkSampleCountFlags.SampleCount1) ? 0u : 2u, VkImageLayout.ColorAttachmentOptimal); - subpass[SP_TONE_MAPPING].AddInputReference (new VkAttachmentReference (6, VkImageLayout.ShaderReadOnlyOptimal)); - if (samples != VkSampleCountFlags.SampleCount1) - subpass[SP_TONE_MAPPING].AddResolveReference (0, VkImageLayout.ColorAttachmentOptimal); - - renderPass.AddSubpass (subpass); - - renderPass.AddDependency (Vk.SubpassExternal, SP_SKYBOX, - VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, - VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); - renderPass.AddDependency (SP_SKYBOX, SP_MODELS, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_MODELS, SP_COMPOSE, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_COMPOSE, SP_TONE_MAPPING, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_TONE_MAPPING, Vk.SubpassExternal, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, - VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead); - - - descriptorPool = new DescriptorPool (dev, 3, - new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 2), - new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 3), - new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 6) - ); - - descLayoutMain = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)); - - descLayoutTextures = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) - ); - - descLayoutGBuff = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//color + roughness - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//emit + metal - new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//normals + AO - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//Pos + depth - new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment));//hdr - - dsMain = descriptorPool.Allocate (descLayoutMain); - dsGBuff = descriptorPool.Allocate (descLayoutGBuff); - - GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples); - - if (samples != VkSampleCountFlags.SampleCount1) { - cfg.multisampleState.sampleShadingEnable = true; - cfg.multisampleState.minSampleShading = 0.5f; - } - cfg.Cache = pipelineCache; - cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutTextures, descLayoutGBuff); - cfg.Layout.AddPushConstants ( - new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), - new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64) - ); - cfg.RenderPass = renderPass; - cfg.SubpassIndex = SP_MODELS; - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - //cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - - cfg.AddVertexBinding<PbrModel.Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); - - using (SpecializationInfo constants = new SpecializationInfo ( - new SpecializationConstant<float> (0, camera.NearPlane), - new SpecializationConstant<float> (1, camera.FarPlane))) { - - cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/GBuffPbr.vert.spv"); - cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/GBuffPbr.frag.spv", constants); - - gBuffPipeline = new GraphicPipeline (cfg); - } - - //COMPOSE PIPELINE - cfg.blendAttachments.Clear (); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - cfg.ResetShadersAndVerticesInfos (); - cfg.SubpassIndex = SP_COMPOSE; - cfg.Layout = gBuffPipeline.Layout; - cfg.depthStencilState.depthTestEnable = false; - cfg.depthStencilState.depthWriteEnable = false; - cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); - cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/compose.frag.spv"); - composePipeline = new GraphicPipeline (cfg); - //DEBUG DRAW use subpass of compose - cfg.shaders[1] = new ShaderInfo (VkShaderStageFlags.Fragment, "shaders/show_gbuff.frag.spv"); - cfg.SubpassIndex = SP_COMPOSE; - debugPipeline = new GraphicPipeline (cfg); - //TONE MAPPING - cfg.shaders[1] = new ShaderInfo (VkShaderStageFlags.Fragment, "shaders/tone_mapping.frag.spv"); - cfg.SubpassIndex = SP_TONE_MAPPING; - //cfg.multisampleState.sampleShadingEnable = false; - //cfg.multisampleState.rasterizationSamples = VkSampleCountFlags.SampleCount1; + renderer = new DeferredPbrRenderer (dev, swapChain, presentQueue, camera.NearPlane, camera.FarPlane); - toneMappingPipeline = new GraphicPipeline (cfg); - - envCube = new EnvironmentCube (dsMain, gBuffPipeline.Layout, presentQueue, renderPass); - - matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; - uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true); - - string[] modelPathes = { - "../data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", - "../data/models/Hubble.glb", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Avocado/glTF/Avocado.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BarramundiFish/glTF/BarramundiFish.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BoomBoxWithAxes/glTF/BoomBoxWithAxes.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Box/glTF/Box.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/EnvironmentTest/glTF/EnvironmentTest.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/OrientationTest/glTF/OrientationTest.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Buggy/glTF/Buggy.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/2CylinderEngine/glTF-Embedded/2CylinderEngine.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/FlightHelmet/glTF/FlightHelmet.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/GearboxAssy/glTF/GearboxAssy.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Lantern/glTF/Lantern.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/SciFiHelmet/glTF/SciFiHelmet.gltf", - "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Sponza/glTF/Sponza.gltf", - "/mnt/devel/vkChess/data/chess.gltf", - "/home/jp/gltf/camaro/scene.gltf" - }; - - model = new PbrModel (presentQueue, modelPathes[1], - descLayoutTextures, - AttachmentType.Color, - AttachmentType.PhysicalProps, - AttachmentType.Normal, - AttachmentType.AmbientOcclusion, - AttachmentType.Emissive); - //model = new Model (presentQueue, "../data/models/chess.gltf"); - //model = new Model (presentQueue, "../data/models/Sponza/glTF/Sponza.gltf"); - //model = new Model (dev, presentQueue, "../data/models/icosphere.gltf"); - //model = new Model (dev, presentQueue, cmdPool, "../data/models/cube.gltf"); - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutMain); - uboUpdate.Write (dev, dsMain, - uboMats.Descriptor, - envCube.irradianceCube.Descriptor, - envCube.prefilterCube.Descriptor, - envCube.lutBrdf.Descriptor, - model.materialUBO.Descriptor); - - modelAABB = model.DefaultScene.AABB; + camera.Model = Matrix4x4.CreateScale (1f / Math.Max (Math.Max (renderer.modelAABB.Width, renderer.modelAABB.Height), renderer.modelAABB.Depth)); } - void buildCommandBuffers () { - for (int i = 0; i < swapChain.ImageCount; ++i) { - cmds[i]?.Free (); - cmds[i] = cmdPool.AllocateAndStart (); - recordDraw (cmds[i], frameBuffers[i]); - cmds[i].End (); - } + void buildCommandBuffers () { + cmdPool.FreeCommandBuffers (cmds); + cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); + renderer.buildCommandBuffers (cmds); } - void recordDraw (CommandBuffer cmd, Framebuffer fb) { - renderPass.Begin (cmd, fb); - - cmd.SetViewport (fb.Width, fb.Height); - cmd.SetScissor (fb.Width, fb.Height); - - cmd.BindDescriptorSet (gBuffPipeline.Layout, dsMain); - - envCube.RecordDraw (cmd); - renderPass.BeginSubPass (cmd); - gBuffPipeline.Bind (cmd); - model.Bind (cmd); - model.DrawAll (cmd, gBuffPipeline.Layout); - - renderPass.BeginSubPass (cmd); - - cmd.BindDescriptorSet (composePipeline.Layout, dsGBuff, 2); - - if (currentDebugView == DebugView.none) - composePipeline.Bind (cmd); - else { - debugPipeline.Bind (cmd); - uint debugValue = (uint)currentDebugView - 1; - debugValue += (uint)((envCube.debugFace << 8) + (envCube.debugMip << 16)); - cmd.PushConstant (debugPipeline.Layout, VkShaderStageFlags.Fragment, debugValue, (uint)Marshal.SizeOf<Matrix4x4> ()); - } - - cmd.Draw (3, 1, 0, 0); - - renderPass.BeginSubPass (cmd); - toneMappingPipeline.Bind (cmd); - cmd.Draw (3, 1, 0, 0); - - renderPass.End (cmd); - } #region update public override void UpdateView () { - camera.AspectRatio = (float)swapChain.Width / swapChain.Height; - - matrices.lightPos = lightPos; - - matrices.projection = camera.Projection; - matrices.view = camera.View; - matrices.model = camera.Model; - - - matrices.camPos = new Vector4 ( - -camera.Position.Z * (float)Math.Sin (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), - camera.Position.Z * (float)Math.Sin (camera.Rotation.X), - camera.Position.Z * (float)Math.Cos (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), - 0 - ); - - uboMats.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); - + renderer.UpdateView (camera); updateViewRequested = false; } #endregion - void createGBuff () { - gbColorRough?.Dispose (); - gbEmitMetal?.Dispose (); - gbN_AO?.Dispose (); - gbPos?.Dispose (); - hdrImg?.Dispose (); - - gbColorRough = new Image (dev, swapChain.ColorFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); - gbEmitMetal = new Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); - gbN_AO = new Image (dev, VkFormat.R16g16b16a16Sfloat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); - gbPos = new Image (dev, VkFormat.R16g16b16a16Sfloat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); - hdrImg = new Image (dev, hdrFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, samples); - - gbColorRough.CreateView (); - gbColorRough.CreateSampler (); - gbColorRough.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbEmitMetal.CreateView (); - gbEmitMetal.CreateSampler (); - gbEmitMetal.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbN_AO.CreateView (); - gbN_AO.CreateSampler (); - gbN_AO.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbPos.CreateView (); - gbPos.CreateSampler (); - gbPos.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - hdrImg.CreateView (); - hdrImg.CreateSampler (); - hdrImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutGBuff); - uboUpdate.Write (dev, dsGBuff, gbColorRough.Descriptor, - gbEmitMetal.Descriptor, - gbN_AO.Descriptor, - gbPos.Descriptor, - hdrImg.Descriptor); - gbColorRough.SetName ("GBuffColorRough"); - gbEmitMetal.SetName ("GBuffEmitMetal"); - gbN_AO.SetName ("GBuffN"); - gbPos.SetName ("GBuffPos"); - hdrImg.SetName ("HDRimg"); - } - protected override void OnResize () { UpdateView (); - - if (frameBuffers != null) - for (int i = 0; i < swapChain.ImageCount; ++i) - frameBuffers[i]?.Dispose (); - - createGBuff (); - - frameBuffers = new Framebuffer[swapChain.ImageCount]; - - for (int i = 0; i < swapChain.ImageCount; ++i) { - frameBuffers[i] = new Framebuffer (renderPass, swapChain.Width, swapChain.Height, new Image[] { - swapChain.images[i], null, gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg}); - } - + renderer.Resize (); buildCommandBuffers (); } @@ -454,25 +70,25 @@ namespace deferred { switch (key) { case Key.F: if (modifiers.HasFlag (Modifier.Shift)) { - envCube.debugFace--; - if (envCube.debugFace < 0) - envCube.debugFace = 5; + renderer.envCube.debugFace--; + if (renderer.envCube.debugFace < 0) + renderer.envCube.debugFace = 5; } else { - envCube.debugFace++; - if (envCube.debugFace > 5) - envCube.debugFace = 0; + renderer.envCube.debugFace++; + if (renderer.envCube.debugFace > 5) + renderer.envCube.debugFace = 0; } rebuildBuffers = true; break; case Key.M: if (modifiers.HasFlag (Modifier.Shift)) { - envCube.debugMip--; - if (envCube.debugMip < 0) - envCube.debugMip = (int)envCube.prefilterCube.CreateInfo.mipLevels - 1; + renderer.envCube.debugMip--; + if (renderer.envCube.debugMip < 0) + renderer.envCube.debugMip = (int)renderer.envCube.prefilterCube.CreateInfo.mipLevels - 1; } else { - envCube.debugMip++; - if (envCube.debugMip > envCube.prefilterCube.CreateInfo.mipLevels) - envCube.debugMip = 0; + renderer.envCube.debugMip++; + if (renderer.envCube.debugMip > renderer.envCube.prefilterCube.CreateInfo.mipLevels) + renderer.envCube.debugMip = 0; } rebuildBuffers = true; break; @@ -486,60 +102,60 @@ namespace deferred { case Key.Keypad7: case Key.Keypad8: case Key.Keypad9: - currentDebugView = (DebugView)(int)key-320; + renderer.currentDebugView = (DeferredPbrRenderer.DebugView)(int)key-320; rebuildBuffers = true; break; case Key.KeypadDivide: - currentDebugView = DebugView.irradiance; + renderer.currentDebugView = DeferredPbrRenderer.DebugView.irradiance; rebuildBuffers = true; break; case Key.Up: if (modifiers.HasFlag (Modifier.Shift)) - lightPos -= Vector4.UnitZ; + renderer.lightPos -= Vector4.UnitZ; else camera.Move (0, 0, 1); break; case Key.Down: if (modifiers.HasFlag (Modifier.Shift)) - lightPos += Vector4.UnitZ; + renderer.lightPos += Vector4.UnitZ; else camera.Move (0, 0, -1); break; case Key.Left: if (modifiers.HasFlag (Modifier.Shift)) - lightPos -= Vector4.UnitX; + renderer.lightPos -= Vector4.UnitX; else camera.Move (1, 0, 0); break; case Key.Right: if (modifiers.HasFlag (Modifier.Shift)) - lightPos += Vector4.UnitX; + renderer.lightPos += Vector4.UnitX; else camera.Move (-1, 0, 0); break; case Key.PageUp: if (modifiers.HasFlag (Modifier.Shift)) - lightPos += Vector4.UnitY; + renderer.lightPos += Vector4.UnitY; else camera.Move (0, 1, 0); break; case Key.PageDown: if (modifiers.HasFlag (Modifier.Shift)) - lightPos -= Vector4.UnitY; + renderer.lightPos -= Vector4.UnitY; else camera.Move (0, -1, 0); break; case Key.F2: if (modifiers.HasFlag (Modifier.Shift)) - matrices.exposure -= 0.3f; + renderer.matrices.exposure -= 0.3f; else - matrices.exposure += 0.3f; + renderer.matrices.exposure += 0.3f; break; case Key.F3: if (modifiers.HasFlag (Modifier.Shift)) - matrices.gamma -= 0.1f; + renderer.matrices.gamma -= 0.1f; else - matrices.gamma += 0.1f; + renderer.matrices.gamma += 0.1f; break; case Key.F4: if (camera.Type == Camera.CamType.FirstPerson) @@ -549,7 +165,7 @@ namespace deferred { Console.WriteLine ($"camera type = {camera.Type}"); break; case Key.S: - pipelineCache.Save (); + renderer.pipelineCache.Save (); Console.WriteLine ($"Pipeline Cache saved."); break; default: @@ -563,30 +179,7 @@ namespace deferred { protected override void Dispose (bool disposing) { if (disposing) { if (!isDisposed) { - dev.WaitIdle (); - for (int i = 0; i < swapChain.ImageCount; ++i) - frameBuffers[i]?.Dispose (); - - gbColorRough.Dispose (); - gbEmitMetal.Dispose (); - gbN_AO.Dispose (); - gbPos.Dispose (); - hdrImg.Dispose (); - - gBuffPipeline.Dispose (); - composePipeline.Dispose (); - toneMappingPipeline.Dispose (); - debugPipeline.Dispose (); - - descLayoutMain.Dispose (); - descLayoutTextures.Dispose (); - descLayoutGBuff.Dispose (); - - uboMats.Dispose (); - model.Dispose (); - envCube.Dispose (); - - descriptorPool.Dispose (); + renderer.Dispose (); } } diff --git a/samples/deferred/shaders/GBuffPbr.frag b/samples/deferred/shaders/GBuffPbr.frag index 0a98717..c5708a0 100644 --- a/samples/deferred/shaders/GBuffPbr.frag +++ b/samples/deferred/shaders/GBuffPbr.frag @@ -45,19 +45,14 @@ layout (set = 0, binding = 0) uniform UBO { mat4 projection; mat4 model; mat4 view; - vec4 camPos; - vec4 lightDir; + vec4 camPos; float exposure; float gamma; float prefilteredCubeMipLevels; float scaleIBLAmbient; -#if DEBUG - float debugViewInputs; - float debugViewEquation; -#endif } ubo; -layout (set = 0, binding = 4) uniform UBOMaterials { +layout (set = 0, binding = 5) uniform UBOMaterials { Material materials[16]; }; diff --git a/samples/deferred/shaders/GBuffPbr.vert b/samples/deferred/shaders/GBuffPbr.vert index 76ee24b..aa526a0 100644 --- a/samples/deferred/shaders/GBuffPbr.vert +++ b/samples/deferred/shaders/GBuffPbr.vert @@ -9,8 +9,7 @@ layout (set = 0, binding = 0) uniform UBO { mat4 projection; mat4 model; mat4 view; - vec4 camPos; - vec4 lightDir; + vec4 camPos; float exposure; float gamma; float prefilteredCubeMipLevels; diff --git a/samples/deferred/shaders/compose.frag b/samples/deferred/shaders/compose.frag index 8dbf013..fc185a3 100644 --- a/samples/deferred/shaders/compose.frag +++ b/samples/deferred/shaders/compose.frag @@ -6,27 +6,22 @@ layout (set = 0, binding = 0) uniform UBO { mat4 projection; mat4 model; mat4 view; - vec4 camPos; - vec4 lightPos; + vec4 camPos; float exposure; float gamma; float prefilteredCubeMipLevels; float scaleIBLAmbient; -#if DEBUG - float debugViewInputs; - float debugViewEquation; -#endif } ubo; -#define MAX_LIGHT 4 +layout (constant_id = 0) const uint NUM_LIGHTS = 1; struct Light { vec4 position; vec4 color; }; -layout (set = 0, binding = 5) uniform UBOLights { - Light lights[MAX_LIGHT]; +layout (set = 0, binding = 4) uniform UBOLights { + Light lights[NUM_LIGHTS]; }; const float M_PI = 3.141592653589793; @@ -171,56 +166,63 @@ void main() vec3 specularEnvironmentR90 = vec3(1.0) * reflectance90; vec3 n = subpassLoad(samplerN_AO, gl_SampleID).rgb; - vec3 v = subpassLoad(samplerPos, gl_SampleID).rgb; // Vector from surface point to camera - vec3 l = normalize(ubo.lightPos.xyz); // Vector from surface point to light - vec3 h = normalize(l+v); // Half vector between both l and v - vec3 reflection = -normalize(reflect(v, n)); - reflection.y *= -1.0f; - - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float LdotH = clamp(dot(l, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - PBRInfo pbrInputs = PBRInfo( - NdotL, - NdotV, - NdotH, - LdotH, - VdotH, - perceptualRoughness, - metallic, - specularEnvironmentR0, - specularEnvironmentR90, - alphaRoughness, - diffuseColor, - specularColor - ); + vec3 v = subpassLoad(samplerPos, gl_SampleID).rgb; // Vector from surface point to camera + + vec3 colors = vec3(0); + + for (int i=0; i<NUM_LIGHTS; i++) { + + vec3 l = normalize(lights[i].position.xyz); // Vector from surface point to light + vec3 h = normalize(l+v); // Half vector between both l and v + vec3 reflection = -normalize(reflect(v, n)); + reflection.y *= -1.0f; - // Calculate the shading terms for the microfacet specular shading model - vec3 F = specularReflection(pbrInputs); - float G = geometricOcclusion(pbrInputs); - float D = microfacetDistribution(pbrInputs); + float NdotL = clamp(dot(n, l), 0.001, 1.0); + float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); + float NdotH = clamp(dot(n, h), 0.0, 1.0); + float LdotH = clamp(dot(l, h), 0.0, 1.0); + float VdotH = clamp(dot(v, h), 0.0, 1.0); - const vec3 u_LightColor = vec3(1.0); + PBRInfo pbrInputs = PBRInfo( + NdotL, + NdotV, + NdotH, + LdotH, + VdotH, + perceptualRoughness, + metallic, + specularEnvironmentR0, + specularEnvironmentR90, + alphaRoughness, + diffuseColor, + specularColor + ); - // Calculation of analytical lighting contribution - vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); - vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); - // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) - vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib); + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); - // Calculate lighting contribution from image based lighting source (IBL) - color += getIBLContribution(pbrInputs, n, reflection); + // Calculation of analytical lighting contribution + vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); + vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); + // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) + vec3 color = NdotL * lights[i].color.rgb * (diffuseContrib + specContrib); + // Calculate lighting contribution from image based lighting source (IBL) + colors += color + getIBLContribution(pbrInputs, n, reflection); + + } + colors /= NUM_LIGHTS; + + const float u_OcclusionStrength = 1.0f; const float u_EmissiveFactor = 1.0f; //AO is in the alpha channel of the normalAttachment - color = mix(color, color * subpassLoad(samplerN_AO, gl_SampleID).a, u_OcclusionStrength); - color += emissive; + colors = mix(colors, colors * subpassLoad(samplerN_AO, gl_SampleID).a, u_OcclusionStrength); + colors += emissive; - outColor = vec4(color, baseColor.a); + outColor = vec4(colors, baseColor.a); }
\ No newline at end of file diff --git a/samples/deferred/shaders/debug.vert b/samples/deferred/shaders/debug.vert index 34a2df2..180e58e 100644 --- a/samples/deferred/shaders/debug.vert +++ b/samples/deferred/shaders/debug.vert @@ -12,8 +12,7 @@ layout (binding = 0) uniform UBO { mat4 projectionMatrix; mat4 viewMatrix; - mat4 modelMatrix; - vec4 lightPos; + mat4 modelMatrix; float gamma; float exposure; } ubo; diff --git a/samples/deferred/shaders/tone_mapping.frag b/samples/deferred/shaders/tone_mapping.frag index 9b8c94c..66f435d 100644 --- a/samples/deferred/shaders/tone_mapping.frag +++ b/samples/deferred/shaders/tone_mapping.frag @@ -6,8 +6,7 @@ layout (set = 0, binding = 0) uniform UBO { mat4 projection; mat4 model; mat4 view; - vec4 camPos; - vec4 lightDir; + vec4 camPos; float exposure; float gamma; } ubo; diff --git a/vke/src/CommandPool.cs b/vke/src/CommandPool.cs index 2099a51..4d21d4e 100644 --- a/vke/src/CommandPool.cs +++ b/vke/src/CommandPool.cs @@ -95,9 +95,16 @@ namespace CVKL { return; } using (NativeList<VkCommandBuffer> nlCmds = new NativeList<VkCommandBuffer> ((uint)cmds.Length, (uint)cmds.Length)) { - for (int i = 0; i < cmds.Length; i++) - nlCmds[i] = cmds[i].Handle; - vkFreeCommandBuffers (Dev.VkDev, handle, (uint)cmds.Length, nlCmds.Data); + int count = 0; + for (int i = 0; i < cmds.Length; i++) { + if (cmds[i] == null) + continue; + nlCmds[count] = cmds[i].Handle; + count++; + } + if (count == 0) + return; + vkFreeCommandBuffers (Dev.VkDev, handle, (uint)count, nlCmds.Data); } } diff --git a/vke/src/Device.cs b/vke/src/Device.cs index e66c28d..9c8700c 100644 --- a/vke/src/Device.cs +++ b/vke/src/Device.cs @@ -250,9 +250,10 @@ namespace CVKL { protected virtual void Dispose (bool disposing) { if (!disposedValue) { - if (disposing) { - // TODO: supprimer l'état managé (objets managés). - } + if (disposing) { + resourceManager.Dispose (); + } else + System.Diagnostics.Debug.WriteLine ("Device disposed by Finalizer."); vkDestroyDevice (dev, IntPtr.Zero); @@ -260,17 +261,13 @@ namespace CVKL { } } - // TODO: remplacer un finaliseur seulement si la fonction Dispose(bool disposing) ci-dessus a du code pour libérer les ressources non managées. ~Device() { - // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. Dispose(false); } // Ce code est ajouté pour implémenter correctement le modèle supprimable. public void Dispose () { - // Ne modifiez pas ce code. Placez le code de nettoyage dans Dispose(bool disposing) ci-dessus. Dispose (true); - // TODO: supprimer les marques de commentaire pour la ligne suivante si le finaliseur est remplacé ci-dessus. GC.SuppressFinalize(this); } #endregion diff --git a/vke/src/Model.cs b/vke/src/Model.cs index 0614108..280dc2a 100644 --- a/vke/src/Model.cs +++ b/vke/src/Model.cs @@ -75,6 +75,11 @@ namespace CVKL { return new BoundingBox (mini, maxi, true); } + public float Width => max.X - min.X; + public float Height => max.Y - min.Y; + public float Depth => max.Z - min.Z; + + public Vector3 Center => new Vector3 (Width / 2f + min.X, Height / 2f + min.Y, Depth / 2f + min.Z); public static BoundingBox operator +(BoundingBox bb1, BoundingBox bb2) { return bb1.isValid ? bb2.isValid ? new BoundingBox (Vector3.Min (bb1.min, bb2.min), Vector3.Min (bb1.max, bb2.max),true) : bb1 : bb2.isValid ? bb2 : default(BoundingBox); |