diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-05-10 06:16:28 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-05-10 06:16:28 +0200 |
| commit | 19d3a9b6809075b00cb2309f77e5e213e498892f (patch) | |
| tree | 7155e272c59c02edb47aa7a880dd8b4c1810b53d | |
| parent | 15ddb9f010e54d934544e10ff6dadda2a99b91c3 (diff) | |
debug: correction matrix as row major, embbed shaders after compilation, shaders dir in cvkl
46 files changed, 2062 insertions, 266 deletions
diff --git a/samples/Textured/main.cs b/samples/Textured/main.cs index 7bc2b0d..a1c792f 100644 --- a/samples/Textured/main.cs +++ b/samples/Textured/main.cs @@ -52,9 +52,9 @@ namespace TextureSample { ushort[] indices = { 0, 1, 2, 2, 0, 3 }; int currentImgIndex = 0; string[] imgPathes = { - "../../../samples/data/textures/texture.jpg", - "../../../samples/data/textures/rgba-reference.ktx", - "../../../samples/data/textures/texturearray_rocks_bc3_unorm.ktx", + "data/textures/texture.jpg", + "data/textures/rgba-reference.ktx", + "data/textures/texturearray_rocks_bc3_unorm.ktx", }; Program () : base () { @@ -76,7 +76,7 @@ namespace TextureSample { cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples); cfg.AddVertexBinding (0, 5 * sizeof(float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/main.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/main.frag.spv"); diff --git a/samples/TexturedCube/main.cs b/samples/TexturedCube/main.cs index df3114c..7a8c7b6 100644 --- a/samples/TexturedCube/main.cs +++ b/samples/TexturedCube/main.cs @@ -80,11 +80,11 @@ namespace TextureCube { }; int currentImgIndex = 0; string[] imgPathes = { - "../../../samples/data/textures/papermill.ktx", - "../../../data/textures/cubemap_yokohama_bc3_unorm.ktx", - "../../../data/textures/gcanyon_cube.ktx", - "../../../data/textures/pisa_cube.ktx", - "../../../data/textures/uffizi_cube.ktx", + "data/textures/papermill.ktx", + "data/textures/cubemap_yokohama_bc3_unorm.ktx", + "data/textures/gcanyon_cube.ktx", + "data/textures/pisa_cube.ktx", + "data/textures/uffizi_cube.ktx", }; @@ -106,7 +106,7 @@ namespace TextureCube { cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples); cfg.AddVertexBinding (0, 5 * sizeof(float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/skybox.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/skybox.frag.spv"); diff --git a/samples/Triangle/main.cs b/samples/Triangle/main.cs index 347f83a..e37d861 100644 --- a/samples/Triangle/main.cs +++ b/samples/Triangle/main.cs @@ -4,66 +4,69 @@ using CVKL; using VK; namespace Triangle { - class Program : VkWindow { + class Program : VkWindow { static void Main (string[] args) { + Instance.RenderDocCapture = true; + Instance.Validation = true; + using (Program vke = new Program ()) { vke.Run (); } } - float rotSpeed = 0.01f, zoomSpeed = 0.01f; + float rotSpeed = 0.01f, zoomSpeed = 0.01f; float rotX, rotY, rotZ = 0f, zoom = 1f; struct Matrices { - public Matrix4x4 projection; - public Matrix4x4 view; - public Matrix4x4 model; - } - struct Vertex { - Vector3 position; - Vector3 color; + public Matrix4x4 projection; + public Matrix4x4 view; + public Matrix4x4 model; + } + struct Vertex { + Vector3 position; + Vector3 color; + + public Vertex (float x, float y, float z, float r, float g, float b) { + position = new Vector3 (x, y, z); + color = new Vector3 (r, g, b); + } + } - public Vertex (float x, float y, float z, float r, float g, float b) { - position = new Vector3 (x, y, z); - color = new Vector3 (r, g, b); - } - } + Matrices matrices; - Matrices matrices; + HostBuffer ibo; + HostBuffer vbo; + HostBuffer uboMats; - HostBuffer ibo; - HostBuffer vbo; - HostBuffer uboMats; + DescriptorPool descriptorPool; + DescriptorSetLayout dsLayout; + DescriptorSet descriptorSet; - DescriptorPool descriptorPool; - DescriptorSetLayout dsLayout; - DescriptorSet descriptorSet; - - Framebuffer[] frameBuffers; - GraphicPipeline pipeline; + Framebuffer[] frameBuffers; + GraphicPipeline pipeline; - Vertex[] vertices = { - new Vertex ( 1.0f, 1.0f, 0.0f , 1.0f, 0.0f, 0.0f), - new Vertex (-1.0f, 1.0f, 0.0f , 0.0f, 1.0f, 0.0f), - new Vertex ( 0.0f, -1.0f, 0.0f , 0.0f, 0.0f, 1.0f), - }; - ushort[] indices = new ushort[] { 0, 1, 2 }; + Vertex[] vertices = { + new Vertex (-1.0f, -1.0f, 0.0f , 1.0f, 0.0f, 0.0f), + new Vertex ( 1.0f, -1.0f, 0.0f , 0.0f, 1.0f, 0.0f), + new Vertex ( 0.0f, 1.0f, 0.0f , 0.0f, 0.0f, 1.0f), + }; + ushort[] indices = new ushort[] { 0, 1, 2 }; - Program () : base (false) { + Program () : base (false) { vbo = new HostBuffer<Vertex> (dev, VkBufferUsageFlags.VertexBuffer, vertices); ibo = new HostBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, indices); uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices); descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer)); dsLayout = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex|VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)); + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1); cfg.Layout = new PipelineLayout (dev, dsLayout); cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples); cfg.AddVertexBinding<Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/triangle.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/triangle.frag.spv"); @@ -75,43 +78,67 @@ namespace Triangle { uboUpdate.Write (dev, uboMats.Descriptor); uboMats.Map (); - } + } - public override void UpdateView () { - matrices.projection = Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (60f), (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f); - matrices.view = Matrix4x4.CreateTranslation (0, 0, -2.5f * zoom); - matrices.model = - Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotZ) * - Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotY) * - Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotX); + public override void UpdateView () { + matrices.projection = Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (45f), + (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f) * Camera.VKProjectionCorrection; + matrices.view = + Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotZ) * + Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotY) * + Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotX) * + Matrix4x4.CreateTranslation (0, 0, -3f * zoom); + matrices.model = Matrix4x4.Identity; + uboMats.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); + updateViewRequested = false; + } - uboMats.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); - updateViewRequested = false; - } - - protected override void onMouseMove (double xPos, double yPos) { - double diffX = lastMouseX - xPos; - double diffY = lastMouseY - yPos; + protected override void onMouseMove (double xPos, double yPos) { + double diffX = lastMouseX - xPos; + double diffY = lastMouseY - yPos; if (MouseButton[0]) { rotY -= rotSpeed * (float)diffX; rotX += rotSpeed * (float)diffY; } else if (MouseButton[1]) { zoom += zoomSpeed * (float)diffY; } - updateViewRequested = true; - } + updateViewRequested = true; + } + void buildCommandBuffers() { + cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); + cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); + + for (int i = 0; i < swapChain.ImageCount; ++i) { + Framebuffer fb = frameBuffers[i]; + cmds[i].Start (); + + pipeline.RenderPass.Begin (cmds[i], fb); + + cmds[i].SetViewport (swapChain.Width, swapChain.Height); + cmds[i].SetScissor (swapChain.Width, swapChain.Height); + + cmds[i].BindDescriptorSet (pipeline.Layout, descriptorSet); + + cmds[i].BindPipeline (pipeline); + + cmds[i].BindVertexBuffer (vbo); + cmds[i].BindIndexBuffer (ibo, VkIndexType.Uint16); + cmds[i].DrawIndexed ((uint)indices.Length); + + pipeline.RenderPass.End (cmds[i]); + + cmds[i].End (); + } + } - protected override void OnResize () { + protected override void OnResize () { - if (frameBuffers!=null) + if (frameBuffers != null) for (int i = 0; i < swapChain.ImageCount; ++i) frameBuffers[i]?.Dispose (); frameBuffers = new Framebuffer[swapChain.ImageCount]; - cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources); - cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount); - - for (int i = 0; i < swapChain.ImageCount; ++i) { + for (int i = 0; i < swapChain.ImageCount; ++i) frameBuffers[i] = new Framebuffer (pipeline.RenderPass, swapChain.Width, swapChain.Height, (pipeline.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] { swapChain.images[i], @@ -120,28 +147,10 @@ namespace Triangle { null, null, swapChain.images[i] - }); - - cmds[i].Start (); + }); - pipeline.RenderPass.Begin (cmds[i], frameBuffers[i]); - - cmds[i].SetViewport (swapChain.Width, swapChain.Height); - cmds[i].SetScissor (swapChain.Width, swapChain.Height); - - cmds[i].BindDescriptorSet (pipeline.Layout, descriptorSet); - - cmds[i].BindPipeline (pipeline); - - cmds[i].BindVertexBuffer (vbo); - cmds[i].BindIndexBuffer (ibo, VkIndexType.Uint16); - cmds[i].DrawIndexed ((uint)indices.Length); - - pipeline.RenderPass.End (cmds[i]); - - cmds[i].End (); - } - } + buildCommandBuffers (); + } protected override void Dispose (bool disposing) { if (disposing) { @@ -160,5 +169,5 @@ namespace Triangle { base.Dispose (disposing); } - } + } } diff --git a/samples/Triangle/shaders/triangle.vert b/samples/Triangle/shaders/triangle.vert index 3b395bf..542d015 100644 --- a/samples/Triangle/shaders/triangle.vert +++ b/samples/Triangle/shaders/triangle.vert @@ -25,4 +25,6 @@ void main() { outColor = inColor; gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0); + //gl_Position.y = -gl_Position.y; + //gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0; } diff --git a/samples/deferred/EnvironmentPipeline.cs b/samples/deferred/EnvironmentPipeline.cs index 7217f75..c8f128a 100644 --- a/samples/deferred/EnvironmentPipeline.cs +++ b/samples/deferred/EnvironmentPipeline.cs @@ -32,7 +32,7 @@ namespace CVKL { cfg.RenderPass = renderPass; cfg.Layout = plLayout; cfg.AddVertexBinding (0, 3 * sizeof (float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/skybox.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/skybox.frag.spv"); cfg.multisampleState.rasterizationSamples = Samples; @@ -191,7 +191,7 @@ namespace CVKL { cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal)); cfg.AddVertexBinding (0, 3 * sizeof (float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/filtercube.vert.spv"); if (target == CBTarget.PREFILTEREDENV) diff --git a/samples/deferred/deferredPbrRenderer.cs b/samples/deferred/deferredPbrRenderer.cs index 971eb64..bf3ab54 100644 --- a/samples/deferred/deferredPbrRenderer.cs +++ b/samples/deferred/deferredPbrRenderer.cs @@ -241,7 +241,7 @@ namespace deferred { //cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); cfg.AddVertexBinding<PbrModel.Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); using (SpecializationInfo constants = new SpecializationInfo ( new SpecializationConstant<float> (0, nearPlane), @@ -310,11 +310,12 @@ namespace deferred { model?.Dispose (); if (EnableTextureArray) { - model = new PbrModelTexArray (transferQ, path); - - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]); - uboUpdate.Write (dev, model.materialUBO.Descriptor, (model as PbrModelTexArray).texArray.Descriptor); - + PbrModelTexArray mod = new PbrModelTexArray (transferQ, path); + if (mod.texArray != null) { + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]); + uboUpdate.Write (dev, mod.materialUBO.Descriptor, mod.texArray.Descriptor); + } + model = mod; } else { model = new PbrModelSeparatedTextures (transferQ, path, descLayoutTextures, diff --git a/samples/deferred/main-crow.cs b/samples/deferred/main-crow.cs index 9ed3de0..85a033c 100644 --- a/samples/deferred/main-crow.cs +++ b/samples/deferred/main-crow.cs @@ -16,7 +16,7 @@ namespace deferred { PbrModelTexArray.TEXTURE_DIM = 512; using (Program vke = new Program ()) { - vke.Run (); + vke.Run (); } } @@ -100,19 +100,19 @@ namespace deferred { } string[] cubemapPathes = { - "../../../samples/data/textures/papermill.ktx", - "../../../samples/data/textures/cubemap_yokohama_bc3_unorm.ktx", - "../../../samples/data/textures/gcanyon_cube.ktx", - "../../../samples/data/textures/pisa_cube.ktx", - "../../../samples/data/textures/uffizi_cube.ktx", + "data/textures/papermill.ktx", + "data/textures/cubemap_yokohama_bc3_unorm.ktx", + "data/textures/gcanyon_cube.ktx", + "data/textures/pisa_cube.ktx", + "data/textures/uffizi_cube.ktx", }; string[] modelPathes = { //"/mnt/devel/gts/vkChess.net/data/models/chess.glb", - "../../../samples/data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", - "../../../samples/data/models/shadow.glb", - "../../../samples/data/models/Hubble.glb", - "../../../samples/data/models/MER_static.glb", - "../../../samples/data/models/ISS_stationary.glb", + "data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", + "data/models/shadow.glb", + "data/models/Hubble.glb", + "data/models/MER_static.glb", + "data/models/ISS_stationary.glb", }; int curModelIndex = 0; diff --git a/samples/deferred/main.cs b/samples/deferred/main.cs index 354dd16..d7c4930 100644 --- a/samples/deferred/main.cs +++ b/samples/deferred/main.cs @@ -8,10 +8,12 @@ namespace deferred { class Deferred : VkWindow { static void Main (string[] args) { - Instance.Validation = true; + //Instance.Validation = true; //Instance.DebugUtils = true; //Instance.RenderDocCapture = true; DeferredPbrRenderer.EnableTextureArray = true; + DeferredPbrRenderer.NUM_SAMPLES = VkSampleCountFlags.SampleCount4; + PbrModelTexArray.TEXTURE_DIM = 512; using (Deferred vke = new Deferred ()) { @@ -34,19 +36,19 @@ namespace deferred { transferQ = new Queue (dev, VkQueueFlags.Transfer); } string[] cubemapPathes = { - "../../../samples/data/textures/papermill.ktx", - "../../../samples/data/textures/cubemap_yokohama_bc3_unorm.ktx", - "../../../samples/data/textures/gcanyon_cube.ktx", - "../../../samples/data/textures/pisa_cube.ktx", - "../../../samples/data/textures/uffizi_cube.ktx", + "data/textures/papermill.ktx", + "data/textures/cubemap_yokohama_bc3_unorm.ktx", + "data/textures/gcanyon_cube.ktx", + "data/textures/pisa_cube.ktx", + "data/textures/uffizi_cube.ktx", }; string[] modelPathes = { //"/mnt/devel/gts/vkChess.net/data/models/chess.glb", - "../../../samples/data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", - "../../../samples/data/models/shadow.glb", - "../../../samples/data/models/Hubble.glb", - "../../../samples/data/models/MER_static.glb", - "../../../samples/data/models/ISS_stationary.glb", + "data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", + "data/models/shadow.glb", + "data/models/Hubble.glb", + "data/models/MER_static.glb", + "data/models/ISS_stationary.glb", }; int curModelIndex = 0; diff --git a/samples/deferred/shaders/GBuffPbr.vert b/samples/deferred/shaders/GBuffPbr.vert index 29069af..7cafe49 100644 --- a/samples/deferred/shaders/GBuffPbr.vert +++ b/samples/deferred/shaders/GBuffPbr.vert @@ -29,9 +29,8 @@ void main() { vec4 locPos = ubo.model * pc.model * vec4(inPos, 1.0); outNormal = normalize(transpose(inverse(mat3(ubo.model * pc.model))) * inNormal); - - //locPos.y = -locPos.y; - outWorldPos = locPos.xyz;// / locPos.w; + + outWorldPos = locPos.xyz; outUV0 = inUV0; outUV1 = inUV1; gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); diff --git a/samples/deferred/shadowMapRenderer.cs b/samples/deferred/shadowMapRenderer.cs index 2f5a24e..e24b872 100644 --- a/samples/deferred/shadowMapRenderer.cs +++ b/samples/deferred/shadowMapRenderer.cs @@ -82,7 +82,7 @@ namespace deferred { ); cfg.AddVertexBinding<PbrModel.Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/shadow.vert.spv"); cfg.AddShader (VkShaderStageFlags.Geometry, "shaders/shadow.geom.spv"); diff --git a/samples/pbrSashaWillem/EnvironmentPipeline.cs b/samples/pbrSashaWillem/EnvironmentPipeline.cs index 69c845c..a03374b 100644 --- a/samples/pbrSashaWillem/EnvironmentPipeline.cs +++ b/samples/pbrSashaWillem/EnvironmentPipeline.cs @@ -36,7 +36,7 @@ namespace CVKL { cfg.RenderPass = renderPass; cfg.Layout = plLayout; cfg.AddVertexBinding (0, 3 * sizeof (float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/skybox.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/skybox.frag.spv"); cfg.multisampleState.rasterizationSamples = Samples; @@ -64,11 +64,11 @@ namespace CVKL { #region skybox public List<string> cubemapPathes = new List<string>() { - "../../../samples/data/textures/papermill.ktx", - "../../../samples/data/textures/cubemap_yokohama_bc3_unorm.ktx", - "../../../samples/data/textures/gcanyon_cube.ktx", - "../../../samples/data/textures/pisa_cube.ktx", - "../../../samples/data/textures/uffizi_cube.ktx", + "data/textures/papermill.ktx", + "data/textures/cubemap_yokohama_bc3_unorm.ktx", + "data/textures/gcanyon_cube.ktx", + "data/textures/pisa_cube.ktx", + "data/textures/uffizi_cube.ktx", }; static float[] box_vertices = { 1.0f, 1.0f,-1.0f, // +X side @@ -207,7 +207,7 @@ namespace CVKL { cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal)); cfg.AddVertexBinding (0, 3 * sizeof (float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/filtercube.vert.spv"); if (target == CBTarget.PREFILTEREDENV) diff --git a/samples/pbrSashaWillem/PbrPipeline.cs b/samples/pbrSashaWillem/PbrPipeline.cs index 15ebb50..4ca7e7a 100644 --- a/samples/pbrSashaWillem/PbrPipeline.cs +++ b/samples/pbrSashaWillem/PbrPipeline.cs @@ -72,7 +72,7 @@ namespace CVKL { ); cfg.RenderPass = renderPass; cfg.AddVertexBinding<PbrModel2.Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/pbr.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/pbr_khr.frag.spv"); @@ -89,7 +89,7 @@ namespace CVKL { uboMats = new HostBuffer (Dev, VkBufferUsageFlags.UniformBuffer, matrices, true); string[] modelPathes = { - "../../../samples/data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", + "data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", "/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", diff --git a/spirv.targets b/spirv.targets index 056eac5..b2df443 100644 --- a/spirv.targets +++ b/spirv.targets @@ -6,15 +6,24 @@ <Targets>DXC</Targets> </AvailableItemName> </ItemGroup> - <Target Name="AfterBuild"> - <Copy SourceFiles="@(Datas)" DestinationFiles="@(Datas->'$(SolutionDir)build\$(Configuration)\samples\data\%(RelativeDir)%(Filename)%(Extension)')"/> - </Target> - <Target Name="CompileShaders" BeforeTargets="Build"> - <Message Importance="High" Text="Compiling shaders to spirv with glslc" /> - <MakeDir Directories="$(OutputPath)%(GLSLShader.RelativeDir)"/> - <Exec Command="glslc %(GLSLShader.Identity) -o $(OutputPath)%(RelativeDir)%(Filename)%(Extension).spv" - ConsoleToMSBuild="true" EchoOff="true"> - <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" /> - </Exec> + + <Target Name="DataCopy" AfterTargets="CoreBuild;Build"> + <Copy SourceFiles="@(Datas)" DestinationFiles="@(Datas->'$(OutputPath)\data\%(RecursiveDir)%(Filename)%(Extension)')"/> </Target> + + <Target Name="CompileShaders" BeforeTargets="BeforeBuild" Outputs="@(CompiledShaders)"> + <Message Importance="High" Text="Compiling shaders to spirv with glslc" /> + <MakeDir Directories="$(OutputPath)%(GLSLShader.RelativeDir)"/> + <Exec Command="glslc %(GLSLShader.Identity) -o $(OutputPath)%(RelativeDir)%(Filename)%(Extension).spv" + ConsoleToMSBuild="true" EchoOff="true" Outputs="$(OutputPath)%(RelativeDir)%(Filename)%(Extension).spv"> + <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" /> + </Exec> + <CreateItem + Include="$(OutputPath)%(GLSLShader.RelativeDir)%(Filename)%(Extension).spv"> + <Output + TaskParameter="Include" + ItemName="EmbeddedResource"/> + </CreateItem> + <Message Importance="High" Text="Embedding $(OutputPath)%(GLSLShader.RelativeDir)%(Filename)%(Extension).spv" /> + </Target> </Project> diff --git a/vke/CVKL.csproj b/vke/CVKL.csproj index 02be0d8..91add1b 100644 --- a/vke/CVKL.csproj +++ b/vke/CVKL.csproj @@ -51,6 +51,10 @@ <PackageReference Include="Vulkan" Version="0.1.2.8-beta" /> </ItemGroup> <ItemGroup> + <None Remove="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" /> + <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" /> <Compile Remove="Properties\AssemblyInfo.cs;src\Renderer.cs;src\QueueFamily.cs" /> - </ItemGroup> + </ItemGroup> + + <Import Project="$(SolutionDir)spirv.targets" /> </Project> diff --git a/vke/shaders/FullScreenQuad.vert b/vke/shaders/FullScreenQuad.vert new file mode 100644 index 0000000..826720b --- /dev/null +++ b/vke/shaders/FullScreenQuad.vert @@ -0,0 +1,10 @@ +#version 450 + +layout (location = 0) out vec2 outUV; + +void main() +{ + outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f); + //gl_Position = vec4(outUV -1.0f, 0.0f, 1.0f); +} diff --git a/vke/shaders/debug.frag b/vke/shaders/debug.frag new file mode 100644 index 0000000..fd419ff --- /dev/null +++ b/vke/shaders/debug.frag @@ -0,0 +1,12 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inColor; +layout (location = 0) out vec4 outFragColor; + +void main() +{ + outFragColor = vec4(inColor, 1.0); +}
\ No newline at end of file diff --git a/vke/shaders/debug.vert b/vke/shaders/debug.vert new file mode 100644 index 0000000..180e58e --- /dev/null +++ b/vke/shaders/debug.vert @@ -0,0 +1,34 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inColor; + +layout (location = 0) out vec3 outColor; + +layout (binding = 0) uniform UBO +{ + mat4 projectionMatrix; + mat4 viewMatrix; + mat4 modelMatrix; + float gamma; + float exposure; +} ubo; + +layout(push_constant) uniform PushConsts { + mat4 projectionMatrix; +} pc; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + outColor = inColor; + + gl_Position = pc.projectionMatrix * vec4 ((ubo.viewMatrix * vec4(inPos.xyz, 0.0)).xyz, 1); +} diff --git a/vke/shaders/deffered/GBuffPbr.frag b/vke/shaders/deffered/GBuffPbr.frag new file mode 100644 index 0000000..ca398e6 --- /dev/null +++ b/vke/shaders/deffered/GBuffPbr.frag @@ -0,0 +1,212 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#define MANUAL_SRGB 0 +#define DEBUG 0 + +layout (constant_id = 0) const float NEAR_PLANE = 0.1f; +layout (constant_id = 1) const float FAR_PLANE = 256.0f; +layout (constant_id = 2) const int MAT_COUNT = 1; + +struct Material { + vec4 baseColorFactor; + vec4 emissiveFactor; + vec4 diffuseFactor; + vec4 specularFactor; + float workflow; + uint tex0; + uint tex1; + float metallicFactor; + float roughnessFactor; + float alphaMask; + float alphaMaskCutoff; + int pad0; +}; +const float M_PI = 3.141592653589793; +const float c_MinRoughness = 0.04; + +const float PBR_WORKFLOW_METALLIC_ROUGHNESS = 1.0; +const float PBR_WORKFLOW_SPECULAR_GLOSINESS = 2.0f; + +const uint MAP_COLOR = 0x1; +const uint MAP_NORMAL = 0x2; +const uint MAP_AO = 0x4; +const uint MAP_METAL = 0x8; +const uint MAP_ROUGHNESS = 0x10; +const uint MAP_METALROUGHNESS = 0x20; +const uint MAP_EMISSIVE = 0x40; + +layout (location = 0) in vec3 inWorldPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV0; +layout (location = 3) in vec2 inUV1; + + +layout (set = 0, binding = 5) uniform UBOMaterials { + Material materials[MAT_COUNT]; +}; + +// Material bindings +layout (set = 2, binding = 0) uniform sampler2D colorMap; +layout (set = 2, binding = 1) uniform sampler2D physicalDescriptorMap; +layout (set = 2, binding = 2) uniform sampler2D normalMap; +layout (set = 2, binding = 3) uniform sampler2D aoMap; +layout (set = 2, binding = 4) uniform sampler2D emissiveMap; + + +layout (push_constant) uniform PushCsts { + layout(offset = 64) + int materialIdx; +}; + + +layout (location = 0) out vec4 outColorRough; +layout (location = 1) out vec4 outEmitMetal; +layout (location = 2) out vec4 outN_AO; +layout (location = 3) out vec4 outPos; + +vec4 SRGBtoLINEAR(vec4 srgbIn) +{ + #ifdef MANUAL_SRGB + #ifdef SRGB_FAST_APPROXIMATION + vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); + #else //SRGB_FAST_APPROXIMATION + vec3 bLess = step(vec3(0.04045),srgbIn.xyz); + vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); + #endif //SRGB_FAST_APPROXIMATION + return vec4(linOut,srgbIn.w);; + #else //MANUAL_SRGB + return srgbIn; + #endif //MANUAL_SRGB +} + +// Find the normal for this fragment, pulling either from a predefined normal map +// or from the interpolated mesh normal and tangent attributes. +vec3 getNormal() +{ + vec3 tangentNormal; + // Perturb normal, see http://www.thetenthplanet.de/archives/1180 + if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(normalMap, inUV0).xyz * 2.0 - 1.0; + else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(normalMap, inUV1).xyz * 2.0 - 1.0; + else + return normalize(inNormal); + + vec3 q1 = dFdx(inWorldPos); + vec3 q2 = dFdy(inWorldPos); + vec2 st1 = dFdx(inUV0); + vec2 st2 = dFdy(inUV0); + + vec3 N = normalize(inNormal); + vec3 T = normalize(q1 * st2.t - q2 * st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +// Gets metallic factor from specular glossiness workflow inputs +float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) { + float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b); + float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b); + if (perceivedSpecular < c_MinRoughness) { + return 0.0; + } + float a = c_MinRoughness; + float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness; + float c = c_MinRoughness - perceivedSpecular; + float D = max(b * b - 4.0 * a * c, 0.0); + return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0); +} + +float linearDepth(float depth) +{ + float z = depth * 2.0f - 1.0f; + return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); +} + +void main() +{ + float perceptualRoughness; + float metallic; + vec4 baseColor; + vec3 emissive = vec3(0); + + baseColor = materials[materialIdx].baseColorFactor; + + if (materials[materialIdx].workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) { + perceptualRoughness = materials[materialIdx].roughnessFactor; + metallic = materials[materialIdx].metallicFactor; + // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. + // This layout intentionally reserves the 'r' channel for (optional) occlusion map data + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){ + perceptualRoughness *= texture(physicalDescriptorMap, inUV0).g; + metallic *= texture(physicalDescriptorMap, inUV0).b; + }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){ + perceptualRoughness *= texture(physicalDescriptorMap, inUV1).g; + metallic *= texture(physicalDescriptorMap, inUV1).b; + } + perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); + metallic = clamp(metallic, 0.0, 1.0); + + // The albedo may be defined from a base texture or a flat color + if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(colorMap, inUV0)); + else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(colorMap, inUV1)); + } + + if (materials[materialIdx].alphaMask == 1.0f) { + if (baseColor.a < materials[materialIdx].alphaMaskCutoff) + discard; + } + + if (materials[materialIdx].workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) { + // Values from specular glossiness workflow are converted to metallic roughness + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + perceptualRoughness = 1.0 - texture(physicalDescriptorMap, inUV0).a; + else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + perceptualRoughness = 1.0 - texture(physicalDescriptorMap, inUV1).a; + else + perceptualRoughness = 0.0; + + const float epsilon = 1e-6; + + vec4 diffuse = SRGBtoLINEAR(texture(colorMap, inUV0)); + vec3 specular = SRGBtoLINEAR(texture(physicalDescriptorMap, inUV0)).rgb; + + float maxSpecular = max(max(specular.r, specular.g), specular.b); + + // Convert metallic value from specular glossiness inputs + metallic = convertMetallic(diffuse.rgb, specular, maxSpecular); + + vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * materials[materialIdx].diffuseFactor.rgb; + vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * materials[materialIdx].specularFactor.rgb; + baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a); + + } + + const float u_OcclusionStrength = 1.0f; + const float u_EmissiveFactor = 1.0f; + float ao = 1.0f; + + if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE) + emissive = SRGBtoLINEAR(texture(emissiveMap, inUV0)).rgb * u_EmissiveFactor; + else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE) + emissive = SRGBtoLINEAR(texture(emissiveMap, inUV1)).rgb * u_EmissiveFactor; + + if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO) + ao = texture(aoMap, inUV0).r; + else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO) + ao = texture(aoMap, inUV1).r; + + vec3 n = getNormal(); + vec3 p = inWorldPos; + + outColorRough = vec4 (baseColor.rgb, perceptualRoughness); + outEmitMetal = vec4 (emissive, metallic); + outN_AO = vec4 (n, ao); + outPos = vec4 (p, linearDepth(gl_FragCoord.z)); +}
\ No newline at end of file diff --git a/vke/shaders/deffered/GBuffPbr.vert b/vke/shaders/deffered/GBuffPbr.vert new file mode 100644 index 0000000..7cafe49 --- /dev/null +++ b/vke/shaders/deffered/GBuffPbr.vert @@ -0,0 +1,37 @@ +#version 450 + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV0; +layout (location = 3) in vec2 inUV1; + +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; +} ubo; + +layout(push_constant) uniform PushConsts { + mat4 model; +} pc; + +layout (location = 0) out vec3 outWorldPos; +layout (location = 1) out vec3 outNormal; +layout (location = 2) out vec2 outUV0; +layout (location = 3) out vec2 outUV1; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + vec4 locPos = ubo.model * pc.model * vec4(inPos, 1.0); + outNormal = normalize(transpose(inverse(mat3(ubo.model * pc.model))) * inNormal); + + outWorldPos = locPos.xyz; + outUV0 = inUV0; + outUV1 = inUV1; + gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); +} diff --git a/vke/shaders/deffered/GBuffPbrTexArray.frag b/vke/shaders/deffered/GBuffPbrTexArray.frag new file mode 100644 index 0000000..dee3471 --- /dev/null +++ b/vke/shaders/deffered/GBuffPbrTexArray.frag @@ -0,0 +1,211 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#define MANUAL_SRGB 0 +#define DEBUG 0 + +layout (constant_id = 0) const float NEAR_PLANE = 0.1f; +layout (constant_id = 1) const float FAR_PLANE = 256.0f; +layout (constant_id = 2) const int MAT_COUNT = 1; + +struct Material { + vec4 baseColorFactor; + vec4 emissiveFactor; + vec4 diffuseFactor; + vec4 specularFactor; + + float workflow; + uint tex0; + uint tex1; + int baseColorTex; + + int physicalDescTex; + int normalTex; + int occlusionTex; + int emissiveTex; + + float metallicFactor; + float roughnessFactor; + float alphaMask; + float alphaMaskCutoff; +}; +const float M_PI = 3.141592653589793; +const float c_MinRoughness = 0.04; + +const float PBR_WORKFLOW_METALLIC_ROUGHNESS = 1.0; +const float PBR_WORKFLOW_SPECULAR_GLOSINESS = 2.0f; + +const uint MAP_COLOR = 0x1; +const uint MAP_NORMAL = 0x2; +const uint MAP_AO = 0x4; +const uint MAP_METAL = 0x8; +const uint MAP_ROUGHNESS = 0x10; +const uint MAP_METALROUGHNESS = 0x20; +const uint MAP_EMISSIVE = 0x40; + +layout (location = 0) in vec3 inWorldPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec2 inUV0; +layout (location = 3) in vec2 inUV1; + +layout (set = 0, binding = 5) uniform UBOMaterials { + Material materials[MAT_COUNT]; +}; +layout (set = 0, binding = 7) uniform sampler2DArray texArray; + +layout (push_constant) uniform PushCsts { + layout(offset = 64) + int materialIdx; +}; + + +layout (location = 0) out vec4 outColorRough; +layout (location = 1) out vec4 outEmitMetal; +layout (location = 2) out vec4 outN_AO; +layout (location = 3) out vec4 outPos; + +vec4 SRGBtoLINEAR(vec4 srgbIn) +{ + #ifdef MANUAL_SRGB + #ifdef SRGB_FAST_APPROXIMATION + vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); + #else //SRGB_FAST_APPROXIMATION + vec3 bLess = step(vec3(0.04045),srgbIn.xyz); + vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); + #endif //SRGB_FAST_APPROXIMATION + return vec4(linOut,srgbIn.w);; + #else //MANUAL_SRGB + return srgbIn; + #endif //MANUAL_SRGB +} + +// Find the normal for this fragment, pulling either from a predefined normal map +// or from the interpolated mesh normal and tangent attributes. +vec3 getNormal() +{ + vec3 tangentNormal; + // Perturb normal, see http://www.thetenthplanet.de/archives/1180 + if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(texArray, vec3(inUV0, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0; + else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(texArray, vec3(inUV1, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0; + else + return normalize(inNormal); + + vec3 q1 = dFdx(inWorldPos); + vec3 q2 = dFdy(inWorldPos); + vec2 st1 = dFdx(inUV0); + vec2 st2 = dFdy(inUV0); + + vec3 N = normalize(inNormal); + vec3 T = normalize(q1 * st2.t - q2 * st1.t); + vec3 B = -normalize(cross(N, T)); + mat3 TBN = mat3(T, B, N); + + return normalize(TBN * tangentNormal); +} + +// Gets metallic factor from specular glossiness workflow inputs +float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) { + float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b); + float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b); + if (perceivedSpecular < c_MinRoughness) { + return 0.0; + } + float a = c_MinRoughness; + float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness; + float c = c_MinRoughness - perceivedSpecular; + float D = max(b * b - 4.0 * a * c, 0.0); + return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0); +} + +float linearDepth(float depth) +{ + float z = depth * 2.0f - 1.0f; + return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE)); +} + +void main() +{ + float perceptualRoughness; + float metallic; + vec4 baseColor; + vec3 emissive = vec3(0); + + baseColor = materials[materialIdx].baseColorFactor; + + if (materials[materialIdx].workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) { + perceptualRoughness = materials[materialIdx].roughnessFactor; + metallic = materials[materialIdx].metallicFactor; + // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. + // This layout intentionally reserves the 'r' channel for (optional) occlusion map data + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){ + perceptualRoughness *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).g; + metallic *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).b; + }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){ + perceptualRoughness *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).g; + metallic *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).b; + } + perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); + metallic = clamp(metallic, 0.0, 1.0); + + // The albedo may be defined from a base texture or a flat color + if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex))); + else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].baseColorTex))); + } + + if (materials[materialIdx].alphaMask == 1.0f) { + if (baseColor.a < materials[materialIdx].alphaMaskCutoff) + discard; + } + + if (materials[materialIdx].workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) { + // Values from specular glossiness workflow are converted to metallic roughness + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + perceptualRoughness = 1.0 - texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).a; + else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + perceptualRoughness = 1.0 - texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).a; + else + perceptualRoughness = 0.0; + + const float epsilon = 1e-6; + + vec4 diffuse = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex))); + vec3 specular = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex))).rgb; + + float maxSpecular = max(max(specular.r, specular.g), specular.b); + + // Convert metallic value from specular glossiness inputs + metallic = convertMetallic(diffuse.rgb, specular, maxSpecular); + + vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * materials[materialIdx].diffuseFactor.rgb; + vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * materials[materialIdx].specularFactor.rgb; + baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a); + + } + + const float u_OcclusionStrength = 1.0f; + const float u_EmissiveFactor = 1.0f; + float ao = 1.0f; + + if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE) + emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor; + else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE) + emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor; + + if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO) + ao = texture(texArray, vec3(inUV0, materials[materialIdx].occlusionTex)).r; + else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO) + ao = texture(texArray, vec3(inUV1, materials[materialIdx].occlusionTex)).r; + + vec3 n = getNormal(); + vec3 p = inWorldPos; + + outColorRough = vec4 (baseColor.rgb, perceptualRoughness); + outEmitMetal = vec4 (emissive, metallic); + outN_AO = vec4 (n, ao); + outPos = vec4 (p, linearDepth(gl_FragCoord.z)); +}
\ No newline at end of file diff --git a/vke/shaders/deffered/compose.frag b/vke/shaders/deffered/compose.frag new file mode 100644 index 0000000..81312bd --- /dev/null +++ b/vke/shaders/deffered/compose.frag @@ -0,0 +1,230 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; + vec4 camPos; + float exposure; + float gamma; + float prefilteredCubeMipLevels; + float scaleIBLAmbient; +} ubo; + +layout (constant_id = 0) const uint NUM_LIGHTS = 1; + +struct Light { + vec4 position; + vec4 color; + mat4 mvp; +}; + +layout (set = 0, binding = 4) uniform UBOLights { + Light lights[NUM_LIGHTS]; +}; + +const float M_PI = 3.141592653589793; +const float c_MinRoughness = 0.04; + +layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough; +layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal; +layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO; +layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos; + +layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance; +layout (set = 0, binding = 2) uniform samplerCube prefilteredMap; +layout (set = 0, binding = 3) uniform sampler2D samplerBRDFLUT; + +layout (location = 0) in vec2 inUV; + +layout (location = 0) out vec4 outColor; + +// Encapsulate the various inputs used by the various functions in the shading equation +// We store values in this struct to simplify the integration of alternative implementations +// of the shading terms, outlined in the Readme.MD Appendix. +struct PBRInfo +{ + float NdotL; // cos angle between normal and light direction + float NdotV; // cos angle between normal and view direction + float NdotH; // cos angle between normal and half vector + float LdotH; // cos angle between light direction and half vector + float VdotH; // cos angle between view direction and half vector + float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) + float metalness; // metallic value at the surface + vec3 reflectance0; // full reflectance color (normal incidence angle) + vec3 reflectance90; // reflectance color at grazing angle + float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) + vec3 diffuseColor; // color contribution from diffuse lighting + vec3 specularColor; // color contribution from specular lighting +}; + +// Calculation of the lighting contribution from an optional Image Based Light source. +// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1]. +// See our README.md on Environment Maps [3] for additional discussion. +vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) +{ + float lod = (pbrInputs.perceptualRoughness * ubo.prefilteredCubeMipLevels); + // retrieve a scale and bias to F0. See [1], Figure 3 + vec3 brdf = (texture(samplerBRDFLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; + vec3 diffuseLight = texture(samplerIrradiance, reflection).rgb; + + vec3 specularLight = textureLod(prefilteredMap, reflection, lod).rgb; + + vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; + vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); + + // For presentation, this allows us to disable IBL terms + // For presentation, this allows us to disable IBL terms + diffuse *= ubo.scaleIBLAmbient; + specular *= ubo.scaleIBLAmbient; + + return diffuse + specular; +} + +// Basic Lambertian diffuse +// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog +// See also [1], Equation 1 +vec3 diffuse(PBRInfo pbrInputs) +{ + return pbrInputs.diffuseColor / M_PI; +} + +// The following equation models the Fresnel reflectance term of the spec equation (aka F()) +// Implementation of fresnel from [4], Equation 15 +vec3 specularReflection(PBRInfo pbrInputs) +{ + return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); +} + +// This calculates the specular geometric attenuation (aka G()), +// where rougher material will reflect less light back to the viewer. +// This implementation is based on [1] Equation 4, and we adopt their modifications to +// alphaRoughness as input as originally proposed in [2]. +float geometricOcclusion(PBRInfo pbrInputs) +{ + float NdotL = pbrInputs.NdotL; + float NdotV = pbrInputs.NdotV; + float r = pbrInputs.alphaRoughness; + + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + return attenuationL * attenuationV; +} + +// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) +// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz +// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. +float microfacetDistribution(PBRInfo pbrInputs) +{ + float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; + float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; + return roughnessSq / (M_PI * f * f); +} + +// Gets metallic factor from specular glossiness workflow inputs +float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) { + float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b); + float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b); + if (perceivedSpecular < c_MinRoughness) { + return 0.0; + } + float a = c_MinRoughness; + float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness; + float c = c_MinRoughness - perceivedSpecular; + float D = max(b * b - 4.0 * a * c, 0.0); + return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0); +} + +void main() +{ + if (subpassLoad(samplerPos, gl_SampleID).a == 1.0f) + discard; + + float perceptualRoughness = subpassLoad(samplerColorRough, gl_SampleID).a; + float metallic = subpassLoad(samplerEmitMetal, gl_SampleID).a; + vec3 diffuseColor; + vec4 baseColor = vec4(subpassLoad(samplerColorRough, gl_SampleID).rgb, 1); + vec3 emissive = subpassLoad (samplerEmitMetal, gl_SampleID).rgb; + + vec3 f0 = vec3(0.04); + + diffuseColor = baseColor.rgb * (vec3(1.0) - f0); + diffuseColor *= 1.0 - metallic; + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + vec3 specularColor = mix(f0, baseColor.rgb, metallic); + + // Compute reflectance. + float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); + + // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. + // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. + float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); + vec3 specularEnvironmentR0 = specularColor.rgb; + vec3 specularEnvironmentR90 = vec3(1.0) * reflectance90; + + vec3 n = subpassLoad(samplerN_AO, gl_SampleID).rgb; + vec3 pos = subpassLoad(samplerPos, gl_SampleID).rgb; + vec3 v = normalize(ubo.camPos.xyz - pos); // Vector from surface point to camera + + vec3 colors = vec3(0); + vec3 lightTarget = vec3(0); + + for (int i=0; i<NUM_LIGHTS; i++) { + + vec3 l = normalize(lights[i].position.xyz-pos); // 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 + ); + + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); + + // 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 + colors = mix(colors, colors * subpassLoad(samplerN_AO, gl_SampleID).a, u_OcclusionStrength); + colors += emissive; + + outColor = vec4(colors, baseColor.a); +}
\ No newline at end of file diff --git a/vke/shaders/deffered/compose_with_shadows.frag b/vke/shaders/deffered/compose_with_shadows.frag new file mode 100644 index 0000000..d8ad270 --- /dev/null +++ b/vke/shaders/deffered/compose_with_shadows.frag @@ -0,0 +1,277 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; + vec4 camPos; + float exposure; + float gamma; + float prefilteredCubeMipLevels; + float scaleIBLAmbient; +} ubo; + +layout (constant_id = 0) const uint NUM_LIGHTS = 1; + +struct Light { + vec4 position; + vec4 color; + mat4 mvp; +}; + +layout (set = 0, binding = 4) uniform UBOLights { + Light lights[NUM_LIGHTS]; +}; + +const float M_PI = 3.141592653589793; +const float c_MinRoughness = 0.04; +#define SHADOW_FACTOR 0.15 + +layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough; +layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal; +layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO; +layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos; + +layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance; +layout (set = 0, binding = 2) uniform samplerCube prefilteredMap; +layout (set = 0, binding = 3) uniform sampler2D samplerBRDFLUT; +layout (set = 0, binding = 6) uniform sampler2DArray samplerShadowMap; + +layout (location = 0) in vec2 inUV; + +layout (location = 0) out vec4 outColor; + +// Encapsulate the various inputs used by the various functions in the shading equation +// We store values in this struct to simplify the integration of alternative implementations +// of the shading terms, outlined in the Readme.MD Appendix. +struct PBRInfo +{ + float NdotL; // cos angle between normal and light direction + float NdotV; // cos angle between normal and view direction + float NdotH; // cos angle between normal and half vector + float LdotH; // cos angle between light direction and half vector + float VdotH; // cos angle between view direction and half vector + float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) + float metalness; // metallic value at the surface + vec3 reflectance0; // full reflectance color (normal incidence angle) + vec3 reflectance90; // reflectance color at grazing angle + float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) + vec3 diffuseColor; // color contribution from diffuse lighting + vec3 specularColor; // color contribution from specular lighting +}; + +// Calculation of the lighting contribution from an optional Image Based Light source. +// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1]. +// See our README.md on Environment Maps [3] for additional discussion. +vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) +{ + float lod = (pbrInputs.perceptualRoughness * ubo.prefilteredCubeMipLevels); + // retrieve a scale and bias to F0. See [1], Figure 3 + vec3 brdf = (texture(samplerBRDFLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; + vec3 diffuseLight = texture(samplerIrradiance, reflection).rgb; + + vec3 specularLight = textureLod(prefilteredMap, reflection, lod).rgb; + + vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; + vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); + + // For presentation, this allows us to disable IBL terms + // For presentation, this allows us to disable IBL terms + diffuse *= ubo.scaleIBLAmbient; + specular *= ubo.scaleIBLAmbient; + + return diffuse + specular; +} + +// Basic Lambertian diffuse +// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog +// See also [1], Equation 1 +vec3 diffuse(PBRInfo pbrInputs) +{ + return pbrInputs.diffuseColor / M_PI; +} + +// The following equation models the Fresnel reflectance term of the spec equation (aka F()) +// Implementation of fresnel from [4], Equation 15 +vec3 specularReflection(PBRInfo pbrInputs) +{ + return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); +} + +// This calculates the specular geometric attenuation (aka G()), +// where rougher material will reflect less light back to the viewer. +// This implementation is based on [1] Equation 4, and we adopt their modifications to +// alphaRoughness as input as originally proposed in [2]. +float geometricOcclusion(PBRInfo pbrInputs) +{ + float NdotL = pbrInputs.NdotL; + float NdotV = pbrInputs.NdotV; + float r = pbrInputs.alphaRoughness; + + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + return attenuationL * attenuationV; +} + +// The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) +// Implementation from "Average Irregularity Representation of a Roughened Surface for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz +// Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. +float microfacetDistribution(PBRInfo pbrInputs) +{ + float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; + float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; + return roughnessSq / (M_PI * f * f); +} + +// Gets metallic factor from specular glossiness workflow inputs +float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) { + float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b); + float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b); + if (perceivedSpecular < c_MinRoughness) { + return 0.0; + } + float a = c_MinRoughness; + float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness; + float c = c_MinRoughness - perceivedSpecular; + float D = max(b * b - 4.0 * a * c, 0.0); + return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0); +} + +float textureProj(vec4 P, float layer, vec2 offset) +{ + float shadow = 1.0; + vec4 shadowCoord = P / P.w; + shadowCoord.st = shadowCoord.st * 0.5 + 0.5; + + if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0) + { + float dist = texture(samplerShadowMap, vec3(shadowCoord.st + offset, layer)).r; + if (shadowCoord.w > 0.0 && dist < shadowCoord.z) + shadow = SHADOW_FACTOR; + }else + shadow = 0.05f;//for debug view out of light proj + + return shadow; +} + +float filterPCF(vec4 sc, float layer) +{ + ivec2 texDim = textureSize(samplerShadowMap, 0).xy; + float scale = 1.5; + float dx = scale * 1.0 / float(texDim.x); + float dy = scale * 1.0 / float(texDim.y); + + float shadowFactor = 0.0; + int count = 0; + int range = 1; + + for (int x = -range; x <= range; x++) + { + for (int y = -range; y <= range; y++) + { + shadowFactor += textureProj(sc, layer, vec2(dx*x, dy*y)); + count++; + } + + } + return shadowFactor / count; +} + +void main() +{ + if (subpassLoad(samplerPos, gl_SampleID).a == 1.0f) + discard; + + float perceptualRoughness = subpassLoad(samplerColorRough, gl_SampleID).a; + float metallic = subpassLoad(samplerEmitMetal, gl_SampleID).a; + vec3 diffuseColor; + vec4 baseColor = vec4(subpassLoad(samplerColorRough, gl_SampleID).rgb, 1); + vec3 emissive = subpassLoad (samplerEmitMetal, gl_SampleID).rgb; + + vec3 f0 = vec3(0.04); + + diffuseColor = baseColor.rgb * (vec3(1.0) - f0); + diffuseColor *= 1.0 - metallic; + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + vec3 specularColor = mix(f0, baseColor.rgb, metallic); + + // Compute reflectance. + float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); + + // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. + // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. + float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); + vec3 specularEnvironmentR0 = specularColor.rgb; + vec3 specularEnvironmentR90 = vec3(1.0) * reflectance90; + + vec3 n = subpassLoad(samplerN_AO, gl_SampleID).rgb; + vec3 pos = subpassLoad(samplerPos, gl_SampleID).rgb; + vec3 v = normalize(ubo.camPos.xyz - pos); // Vector from surface point to camera + + vec3 colors = vec3(0); + vec3 lightTarget = vec3(0); + + for (int i=0; i<NUM_LIGHTS; i++) { + + vec3 l = normalize(lights[i].position.xyz-pos); // 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 + ); + + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); + + // 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) + vec4 shadowClip = lights[i].mvp * vec4(pos, 1); + float shadowFactor = filterPCF(shadowClip, i); + + + vec3 color = NdotL * lights[i].color.rgb * (diffuseContrib + specContrib); + + // Calculate lighting contribution from image based lighting source (IBL) + colors += shadowFactor * (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 + colors = mix(colors, colors * subpassLoad(samplerN_AO, gl_SampleID).a, u_OcclusionStrength); + colors += emissive; + + outColor = vec4(colors, baseColor.a); +}
\ No newline at end of file diff --git a/vke/shaders/deffered/show_gbuff.frag b/vke/shaders/deffered/show_gbuff.frag new file mode 100644 index 0000000..7859e36 --- /dev/null +++ b/vke/shaders/deffered/show_gbuff.frag @@ -0,0 +1,92 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough; +layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal; +layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO; +layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos; + +layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance; +layout (set = 0, binding = 2) uniform samplerCube prefilteredMap; +layout (set = 0, binding = 3) uniform sampler2D samplerBRDFLUT; +layout (set = 0, binding = 6) uniform sampler2DArray samplerShadowMap; + +layout (push_constant) uniform PushCsts { + layout(offset = 64) + int imgIdx; +}; + +layout (location = 0) in vec2 inUV; +layout (location = 0) out vec4 outColor; + +const uint color = 0; +const uint normal = 1; +const uint pos = 2; +const uint occlusion = 3; +const uint emissive = 4; +const uint metallic = 5; +const uint roughness = 6; +const uint depth = 7; +const uint prefill = 8; +const uint irradiance = 9; +const uint shadowMap = 10; + +vec4 sampleCubeMap (samplerCube sc, uint face, uint lod) { + vec2 uv = 2.0 * inUV - vec2(1.0); + switch (face) { + case 0: + return vec4 (textureLod (sc, vec3(1, uv.t, uv.s), lod).rgb, 1); + case 1: + return vec4 (textureLod (sc, vec3(-1, uv.t, uv.s), lod).rgb, 1); + case 2: + return vec4 (textureLod (sc, vec3(uv.s, 1, -uv.t), lod).rgb, 1); + case 3: + return vec4 (textureLod (sc, vec3(uv.s, -1, uv.t), lod).rgb, 1); + case 4: + return vec4 (textureLod (sc, vec3(uv, 1), lod).rgb, 1); + case 5: + return vec4 (textureLod (sc, vec3(-uv.s, uv.t, -1), lod).rgb, 1); + } +} + +void main() +{ + uint imgNum = bitfieldExtract (imgIdx, 0, 8); + switch (imgNum) { + case color: + outColor = vec4(subpassLoad(samplerColorRough, gl_SampleID).rgb, 1); + break; + case normal: + outColor = vec4(subpassLoad(samplerN_AO, gl_SampleID).rgb, 1); + break; + case pos: + outColor = vec4(subpassLoad(samplerPos, gl_SampleID).rgb, 1); + break; + case occlusion: + outColor = vec4(subpassLoad(samplerN_AO, gl_SampleID).aaa, 1); + break; + case emissive: + outColor = vec4(subpassLoad(samplerEmitMetal, gl_SampleID).rgb, 1); + break; + case metallic: + outColor = vec4(subpassLoad(samplerEmitMetal, gl_SampleID).aaa, 1); + break; + case roughness: + outColor = vec4(subpassLoad(samplerColorRough, gl_SampleID).aaa, 1); + break; + case depth: + outColor = vec4(subpassLoad(samplerPos, gl_SampleID).aaa, 1); + break; + case shadowMap: + vec3 d = texture(samplerShadowMap, vec3(inUV, bitfieldExtract (imgIdx, 8, 8))).rrr; + outColor = vec4(d*d*d, 1); + break; + default: + if (imgNum == prefill) + outColor = sampleCubeMap (prefilteredMap, bitfieldExtract (imgIdx, 8, 8), bitfieldExtract (imgIdx, 16, 8)); + else if (imgNum == irradiance) + outColor = sampleCubeMap (samplerIrradiance, bitfieldExtract (imgIdx, 8, 8), bitfieldExtract (imgIdx, 16, 8)); + break; + } +}
\ No newline at end of file diff --git a/vke/shaders/deffered/tone_mapping.frag b/vke/shaders/deffered/tone_mapping.frag new file mode 100644 index 0000000..187d672 --- /dev/null +++ b/vke/shaders/deffered/tone_mapping.frag @@ -0,0 +1,60 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; + vec4 camPos; + float exposure; + float gamma; +} ubo; + +layout (input_attachment_index = 0, set = 1, binding = 4) uniform subpassInputMS samplerHDR; + +layout (location = 0) in vec2 inUV; +layout (location = 0) out vec4 outColor; + +vec3 Uncharted2Tonemap(vec3 color) +{ + const float A = 0.15; + const float B = 0.50; + const float C = 0.10; + const float D = 0.20; + const float E = 0.02; + const float F = 0.30; + const float W = 11.2; + return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; +} + +vec3 tonemap(vec3 color) +{ + vec3 outcol = Uncharted2Tonemap(color.rgb * ubo.exposure); + outcol = outcol * (1.0f / Uncharted2Tonemap(vec3(11.2f))); + return pow(outcol, vec3(1.0f / ubo.gamma)); +} + +vec3 SRGBtoLINEAR(vec3 srgbIn) +{ + #ifdef MANUAL_SRGB + #ifdef SRGB_FAST_APPROXIMATION + return pow(srgbIn.xyz,vec3(2.2)); + #else //SRGB_FAST_APPROXIMATION + vec3 bLess = step(vec3(0.04045),srgbIn.xyz); + return linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); + #endif //SRGB_FAST_APPROXIMATION + #else //MANUAL_SRGB + return srgbIn; + #endif //MANUAL_SRGB +} + +void main() +{ + vec4 hdrColor = subpassLoad(samplerHDR, gl_SampleID); + outColor = vec4(SRGBtoLINEAR(tonemap(hdrColor.rgb)), hdrColor.a); + /* + vec3 mapped = vec3(1.0) - exp(-hdrColor.rgb * ubo.exposure); + mapped = pow(mapped, vec3(1.0 / ubo.gamma)); + outColor = vec4(mapped, hdrColor.a);*/ +}
\ No newline at end of file diff --git a/vke/shaders/emissive.frag b/vke/shaders/emissive.frag new file mode 100644 index 0000000..2efe331 --- /dev/null +++ b/vke/shaders/emissive.frag @@ -0,0 +1,25 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInputMS samplerColorRough; +layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInputMS samplerEmitMetal; +layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInputMS samplerN_AO; +layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInputMS samplerPos; + +layout (location = 0) in vec2 inUV; + +layout (location = 0) out vec4 outColor; + +const float offset[5] = float[](0.0, 1.0, 2.0, 3.0, 4.0); +const float weight[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, + 0.0540540541, 0.0162162162); + +void main() +{ + if (subpassLoad(samplerPos, gl_SampleID).a == 1.0f) + discard; + vec3 emissive = subpassLoad (samplerEmitMetal, gl_SampleID).rgb; + + outColor = vec4(emissive, 1); +}
\ No newline at end of file diff --git a/vke/shaders/filtercube.vert b/vke/shaders/filtercube.vert new file mode 100644 index 0000000..1226e28 --- /dev/null +++ b/vke/shaders/filtercube.vert @@ -0,0 +1,19 @@ +#version 450 + +layout (location = 0) in vec3 inPos; + +layout(push_constant) uniform PushConsts { + layout (offset = 0) mat4 mvp; +} pushConsts; + +layout (location = 0) out vec3 outUVW; + +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() +{ + outUVW = inPos; + gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); +} diff --git a/vke/shaders/genbrdflut.frag b/vke/shaders/genbrdflut.frag new file mode 100644 index 0000000..b6290dd --- /dev/null +++ b/vke/shaders/genbrdflut.frag @@ -0,0 +1,90 @@ +#version 450 + +layout (location = 0) in vec2 inUV; +layout (location = 0) out vec4 outColor; +layout (constant_id = 0) const uint NUM_SAMPLES = 1024u; + +const float PI = 3.1415926536; + +// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +float random(vec2 co) +{ + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); +} + +vec2 hammersley2d(uint i, uint N) +{ + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); +} + +// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf +vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) +{ + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); +} + +// Geometric Shadowing function +float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) +{ + float k = (roughness * roughness) / 2.0; + float GL = dotNL / (dotNL * (1.0 - k) + k); + float GV = dotNV / (dotNV * (1.0 - k) + k); + return GL * GV; +} + +vec2 BRDF(float NoV, float roughness) +{ + // Normal always points along z-axis for the 2D lookup + const vec3 N = vec3(0.0, 0.0, 1.0); + vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV); + + vec2 LUT = vec2(0.0); + for(uint i = 0u; i < NUM_SAMPLES; i++) { + vec2 Xi = hammersley2d(i, NUM_SAMPLES); + vec3 H = importanceSample_GGX(Xi, roughness, N); + vec3 L = 2.0 * dot(V, H) * H - V; + + float dotNL = max(dot(N, L), 0.0); + float dotNV = max(dot(N, V), 0.0); + float dotVH = max(dot(V, H), 0.0); + float dotNH = max(dot(H, N), 0.0); + + if (dotNL > 0.0) { + float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); + float G_Vis = (G * dotVH) / (dotNH * dotNV); + float Fc = pow(1.0 - dotVH, 5.0); + LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis); + } + } + return LUT / float(NUM_SAMPLES); +} + +void main() +{ + outColor = vec4(BRDF(inUV.s, 1.0-inUV.t), 0.0, 1.0); +}
\ No newline at end of file diff --git a/vke/shaders/genbrdflut.vert b/vke/shaders/genbrdflut.vert new file mode 100644 index 0000000..f3dd233 --- /dev/null +++ b/vke/shaders/genbrdflut.vert @@ -0,0 +1,9 @@ +#version 450 + +layout (location = 0) out vec2 outUV; + +void main() +{ + outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f); +}
\ No newline at end of file diff --git a/vke/shaders/irradiancecube.frag b/vke/shaders/irradiancecube.frag new file mode 100644 index 0000000..340d679 --- /dev/null +++ b/vke/shaders/irradiancecube.frag @@ -0,0 +1,37 @@ +// Generates an irradiance cube from an environment map using convolution + +#version 450 + +layout (location = 0) in vec3 inPos; +layout (location = 0) out vec4 outColor; +layout (binding = 0) uniform samplerCube samplerEnv; + +layout(push_constant) uniform PushConsts { + layout (offset = 64) float deltaPhi; + layout (offset = 68) float deltaTheta; +} consts; + +#define PI 3.1415926535897932384626433832795 + +void main() +{ + vec3 N = normalize(inPos); + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = cross(N, right); + + const float TWO_PI = PI * 2.0; + const float HALF_PI = PI * 0.5; + + vec3 color = vec3(0.0); + uint sampleCount = 0u; + for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) { + for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) { + vec3 tempVec = cos(phi) * right + sin(phi) * up; + vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; + color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta); + sampleCount++; + } + } + outColor = vec4(PI * color / float(sampleCount), 1.0);//texture(samplerEnv, inPos).rgba; +} diff --git a/vke/shaders/prefilterenvmap.frag b/vke/shaders/prefilterenvmap.frag new file mode 100644 index 0000000..ae1212e --- /dev/null +++ b/vke/shaders/prefilterenvmap.frag @@ -0,0 +1,105 @@ +#version 450 + +layout (location = 0) in vec3 inPos; +layout (location = 0) out vec4 outColor; + +layout (binding = 0) uniform samplerCube samplerEnv; + +layout(push_constant) uniform PushConsts { + layout (offset = 64) float roughness; + layout (offset = 68) uint numSamples; +} consts; + +const float PI = 3.1415926536; + +// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +float random(vec2 co) +{ + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); +} + +vec2 hammersley2d(uint i, uint N) +{ + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); +} + +// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf +vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) +{ + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); +} + +// Normal Distribution function +float D_GGX(float dotNH, float roughness) +{ + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); +} + +vec3 prefilterEnvMap(vec3 R, float roughness) +{ + vec3 N = R; + vec3 V = R; + vec3 color = vec3(0.0); + float totalWeight = 0.0; + float envMapDim = float(textureSize(samplerEnv, 0).s); + for(uint i = 0u; i < consts.numSamples; i++) { + vec2 Xi = hammersley2d(i, consts.numSamples); + vec3 H = importanceSample_GGX(Xi, roughness, N); + vec3 L = 2.0 * dot(V, H) * H - V; + float dotNL = clamp(dot(N, L), 0.0, 1.0); + if(dotNL > 0.0) { + // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ + + float dotNH = clamp(dot(N, H), 0.0, 1.0); + float dotVH = clamp(dot(V, H), 0.0, 1.0); + + // Probability Distribution Function + float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; + // Slid angle of current smple + float omegaS = 1.0 / (float(consts.numSamples) * pdf); + // Solid angle of 1 pixel across all cube faces + float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); + // Biased (+1.0) mip level for better result + float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); + color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL; + totalWeight += dotNL; + + } + } + return (color / totalWeight); +} + + +void main() +{ + vec3 N = normalize(inPos); + outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0); +} diff --git a/vke/shaders/shadow.geom b/vke/shaders/shadow.geom new file mode 100644 index 0000000..283586d --- /dev/null +++ b/vke/shaders/shadow.geom @@ -0,0 +1,37 @@ +#version 420 + +#define NUM_LIGHTS 2 + +layout (triangles, invocations = NUM_LIGHTS) in; +layout (triangle_strip, max_vertices = 3) out; + +struct Light { + vec4 position; + vec4 color; + mat4 mvp; +}; +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; +}; +layout (set = 0, binding = 1) uniform UBOLights { + Light lights[NUM_LIGHTS]; +}; + +//layout (location = 0) in int inInstanceIndex[]; + +layout(push_constant) uniform PushConsts { + mat4 model; +} pc; + +void main() +{ + for (int i = 0; i < gl_in.length(); i++) + { + gl_Layer = gl_InvocationID; + gl_Position = lights[gl_InvocationID].mvp * model * pc.model * gl_in[i].gl_Position; + EmitVertex(); + } + EndPrimitive(); +}
\ No newline at end of file diff --git a/vke/shaders/shadow.vert b/vke/shaders/shadow.vert new file mode 100644 index 0000000..548f093 --- /dev/null +++ b/vke/shaders/shadow.vert @@ -0,0 +1,8 @@ +#version 450 + +layout (location = 0) in vec4 inPos; + +void main() +{ + gl_Position = inPos; +}
\ No newline at end of file diff --git a/vke/shaders/simpletexture.frag b/vke/shaders/simpletexture.frag new file mode 100644 index 0000000..a081876 --- /dev/null +++ b/vke/shaders/simpletexture.frag @@ -0,0 +1,15 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (set = 0, binding = 0) uniform sampler2D samplerColor; + +layout (location = 0) in vec2 inUV; + +layout (location = 0) out vec4 outFragColor; + +void main() +{ + outFragColor = texture(samplerColor, inUV); +} diff --git a/vke/shaders/skybox.frag b/vke/shaders/skybox.frag new file mode 100644 index 0000000..e505ef1 --- /dev/null +++ b/vke/shaders/skybox.frag @@ -0,0 +1,12 @@ +#version 450 + +layout (binding = 2) uniform samplerCube samplerEnv; + +layout (set = 0, location = 0) in vec3 inUVW; + +layout (set = 0, location = 0) out vec4 outColor; + +void main() +{ + outColor = vec4(textureLod(samplerEnv, inUVW, 1.5).rgb, 1.0); +}
\ No newline at end of file diff --git a/vke/shaders/skybox.vert b/vke/shaders/skybox.vert new file mode 100644 index 0000000..22e285e --- /dev/null +++ b/vke/shaders/skybox.vert @@ -0,0 +1,27 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + mat4 view; +} ubo; + +layout (location = 0) out vec3 outUVW; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + outUVW = inPos; + outUVW.y = -outUVW.y; + gl_Position = ubo.projection * mat4(mat3(ubo.view)) * vec4(inPos, 1.0); +} diff --git a/vke/src/Buffer.cs b/vke/src/Buffer.cs index f361f5b..6072d0d 100644 --- a/vke/src/Buffer.cs +++ b/vke/src/Buffer.cs @@ -24,101 +24,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; using VK; using static VK.Vk; namespace CVKL { - #region GPUBuffer - /// <summary> - /// Device local Buffer - /// </summary> - public class GPUBuffer : Buffer { - public GPUBuffer (Device device, VkBufferUsageFlags usage, UInt64 size) - : base (device, usage, VkMemoryPropertyFlags.DeviceLocal, size){ - } - } - /// <summary> - /// Device local Buffer - /// </summary> - public class GPUBuffer<T> : GPUBuffer { - public GPUBuffer (Device device, VkBufferUsageFlags usage, int elementCount) - : base (device, usage, (ulong)(Marshal.SizeOf<T> () * elementCount)) { - } - public GPUBuffer (Queue staggingQ, CommandPool staggingCmdPool, VkBufferUsageFlags usage, T[] elements) - : base (staggingQ.Dev, usage | VkBufferUsageFlags.TransferDst, (ulong)(Marshal.SizeOf<T> () * elements.Length)) { - using (HostBuffer<T> stagging = new HostBuffer<T> (Dev, VkBufferUsageFlags.TransferSrc, elements)) { - CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer (); - cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit); - - stagging.CopyTo (cmd, this); - - cmd.End (); - - staggingQ.Submit (cmd); - staggingQ.WaitIdle (); - - cmd.Free (); - } - } - } - #endregion - - #region HostBuffer - public class HostBuffer<T> : HostBuffer { - public HostBuffer (Device device, VkBufferUsageFlags usage, uint arrayElementCount) - : base (device, usage, (ulong)(Marshal.SizeOf<T> () * arrayElementCount)) { - } - public HostBuffer (Device device, VkBufferUsageFlags usage, IList<T> data, bool keepMapped = false) - : base (device, usage, (ulong)(Marshal.SizeOf<T> () * data.Count)) { - Map (); - Update (data, createInfo.size); - if (!keepMapped) - Unmap (); - } - public HostBuffer (Device device, VkBufferUsageFlags usage, T[] data, bool keepMapped = false) - : base (device, usage, (ulong)(Marshal.SizeOf<T> () * data.Length)) { - Map (); - Update (data, createInfo.size); - if (!keepMapped) - Unmap (); - } - public void Update (T[] data) { - Update (data, (ulong)(Marshal.SizeOf<T> () * data.Length)); - } - } - /// <summary> - /// Mappable Buffer with HostVisble and HostCoherent memory flags - /// </summary> - public class HostBuffer : Buffer { - public HostBuffer (Device device, VkBufferUsageFlags usage, UInt64 size) - : base (device, usage, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, size) { - } - public HostBuffer (Device device, VkBufferUsageFlags usage, object data, bool keepMapped = false) - : base (device, usage, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, (ulong)Marshal.SizeOf(data)) { - Map (); - Update (data, createInfo.size); - if (!keepMapped) - Unmap (); - } - public HostBuffer (Device device, VkBufferUsageFlags usage, UInt64 size, IntPtr data, bool keepMapped = false) - : base (device, usage, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, size) { - Map (); - unsafe { - System.Buffer.MemoryCopy (data.ToPointer (), mappedData.ToPointer (), size, size); - } - if (!keepMapped) - Unmap (); - } - } - #endregion - - /// <summary> - /// Base class for HostBuffer and GPUBuffer - /// </summary> - public class Buffer : Resource { + /// <summary> + /// Base class for HostBuffer and GPUBuffer + /// </summary> + public class Buffer : Resource { internal VkBuffer handle; protected VkBufferCreateInfo createInfo = VkBufferCreateInfo.New (); diff --git a/vke/src/Camera.cs b/vke/src/Camera.cs index c2d2586..acd9262 100644 --- a/vke/src/Camera.cs +++ b/vke/src/Camera.cs @@ -10,8 +10,8 @@ namespace CVKL { new Matrix4x4 ( 1, 0, 0, 0, 0, -1, 0, 0, - 0, 0, 1f/2, 1f/2, - 0, 0, 0, 1 + 0, 0, 1f/2, 0, + 0, 0, 1f/2, 1 ); public enum CamType {LookAt, FirstPerson}; diff --git a/vke/src/DebuDrawPipeline.cs b/vke/src/DebuDrawPipeline.cs new file mode 100644 index 0000000..acc6d5c --- /dev/null +++ b/vke/src/DebuDrawPipeline.cs @@ -0,0 +1,83 @@ +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using VK; + +namespace CVKL { + public class DebugDrawPipeline : GraphicPipeline { + public HostBuffer Vertices; + uint vertexCount; + uint vboLength; + + public DebugDrawPipeline (RenderPass renderPass, uint maxVertices = 100, + VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, PipelineCache pipelineCache = null) : + base (renderPass, pipelineCache, "Debug draw pipeline") { + + vboLength = 100 * 6 * sizeof(float); + + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.LineList, samples); + cfg.rasterizationState.lineWidth = 1.0f; + cfg.RenderPass = RenderPass; + cfg.Layout = new PipelineLayout(Dev, new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4>() * 2)); + cfg.AddVertexBinding (0, 6 * sizeof(float)); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); + cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState (true); + + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/debug.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/debug.frag.spv"); + + layout = cfg.Layout; + + init (cfg); + + Vertices = new HostBuffer (Dev, VkBufferUsageFlags.VertexBuffer, vboLength); + Vertices.Map (); + } + + public void AddLine (Vector3 start, Vector3 end, float r, float g, float b) { + float[] data = { + start.X, start.Y, start.Z, + r, g, b, + end.X, end.Y, end.Z, + r, g, b + }; + Vertices.Update (data, 12 * sizeof (float), vertexCount * 6 * sizeof (float)); + vertexCount+=2; + } + public void UpdateLine (uint lineNum, Vector3 start, Vector3 end, float r, float g, float b) { + float[] data = { + start.X, start.Y, start.Z, + r, g, b, + end.X, end.Y, end.Z, + r, g, b + }; + Vertices.Update (data, 12 * sizeof (float), (lineNum-1) * 2 * 6 * sizeof (float)); + } + + public void RecordDraw (CommandBuffer cmd, Framebuffer fb, Matrix4x4 projection, Matrix4x4 view) { + + //cmd.SetViewport (fb.Width/ratio, fb.Height/ratio, (ratio-1) * (int)fb.Width / ratio, (ratio-1) * (int)fb.Height / ratio); + //cmd.SetViewport (200, 200,100,100,-10,10);//, 4 * (int)fb.Width / 5, 4 * (int)fb.Height / 5); + //cmd.SetScissor (fb.Width / ratio, fb.Height / ratio, (ratio-1) * (int)fb.Width / ratio, (ratio-1) * (int)fb.Height / ratio); + //cmd.SetScissor (200, 200,100,100); + + Bind(cmd); + + cmd.PushConstant (layout, VkShaderStageFlags.Vertex, projection); + cmd.PushConstant (layout, VkShaderStageFlags.Vertex, view, (uint)Marshal.SizeOf<Matrix4x4>()); + + cmd.BindVertexBuffer (Vertices); + cmd.Draw (vertexCount); + } + + protected override void Dispose (bool disposing) { + if (disposing) { + Vertices.Unmap (); + Vertices.Dispose (); + } + + base.Dispose (disposing); + } + } + +} diff --git a/vke/src/Device.cs b/vke/src/Device.cs index af9d241..3c29f2c 100644 --- a/vke/src/Device.cs +++ b/vke/src/Device.cs @@ -28,6 +28,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using VK; using static VK.Vk; @@ -247,8 +248,37 @@ namespace CVKL { } } - #region IDisposable Support - private bool disposedValue = false; // Pour détecter les appels redondants + public static Stream StaticGetStreamFromPath (string path) { + Stream stream = null; + + if (path.StartsWith ("#", StringComparison.Ordinal)) { + string resId = path.Substring (1); + //first search entry assembly + stream = Assembly.GetEntryAssembly ().GetManifestResourceStream (resId); + if (stream != null) + return stream; + //second search CVKL assemlby + stream = Assembly.GetExecutingAssembly ().GetManifestResourceStream (resId); + if (stream != null) + return stream; + //if still not found, search assembly named with the 1st element of the resId + string assemblyName = resId.Split ('.')[0]; + Assembly a = AppDomain.CurrentDomain.GetAssemblies ().FirstOrDefault (aa => aa.GetName ().Name == assemblyName); + if (a == null) + throw new Exception ($"Assembly '{assemblyName}' not found for ressource '{path}'."); + stream = a.GetManifestResourceStream (resId); + if (stream == null) + throw new Exception ("Resource not found: " + path); + } else { + if (!File.Exists (path)) + throw new FileNotFoundException ("File not found: ", path); + stream = new FileStream (path, FileMode.Open, FileAccess.Read); + } + return stream; + } + + #region IDisposable Support + private bool disposedValue = false; // Pour détecter les appels redondants protected virtual void Dispose (bool disposing) { if (!disposedValue) { diff --git a/vke/src/GPUBuffer.cs b/vke/src/GPUBuffer.cs new file mode 100644 index 0000000..061dd65 --- /dev/null +++ b/vke/src/GPUBuffer.cs @@ -0,0 +1,64 @@ +// +// GPUBuffer.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2019 jp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using VK; + +namespace CVKL { + + /// <summary> + /// Device local Buffer + /// </summary> + public class GPUBuffer : Buffer { + public GPUBuffer (Device device, VkBufferUsageFlags usage, UInt64 size) + : base (device, usage, VkMemoryPropertyFlags.DeviceLocal, size){ + } + } + /// <summary> + /// Device local Buffer + /// </summary> + public class GPUBuffer<T> : GPUBuffer { + public GPUBuffer (Device device, VkBufferUsageFlags usage, int elementCount) + : base (device, usage, (ulong)(Marshal.SizeOf<T> () * elementCount)) { + } + public GPUBuffer (Queue staggingQ, CommandPool staggingCmdPool, VkBufferUsageFlags usage, T[] elements) + : base (staggingQ.Dev, usage | VkBufferUsageFlags.TransferDst, (ulong)(Marshal.SizeOf<T> () * elements.Length)) { + using (HostBuffer<T> stagging = new HostBuffer<T> (Dev, VkBufferUsageFlags.TransferSrc, elements)) { + CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer (); + cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit); + + stagging.CopyTo (cmd, this); + + cmd.End (); + + staggingQ.Submit (cmd); + staggingQ.WaitIdle (); + + cmd.Free (); + } + } + } +} diff --git a/vke/src/GraphicPipelineConfig.cs b/vke/src/GraphicPipelineConfig.cs index 000da1a..4a21a78 100644 --- a/vke/src/GraphicPipelineConfig.cs +++ b/vke/src/GraphicPipelineConfig.cs @@ -94,15 +94,16 @@ namespace CVKL { return cfg; } - public void SetVertexAttributes (uint binding, params VkFormat[] attribsDesc) { - uint offset = 0; - - for (uint i = 0; i < attribsDesc.Length; i++) { - vertexAttributes.Add (new VkVertexInputAttributeDescription (binding, i, attribsDesc[i], offset)); + uint currentAttributeIndex = 0; + public void AddVertexAttributes (uint binding, params VkFormat[] attribsDesc) { + uint currentAttributeoffset = 0; + for (uint i = 0; i < attribsDesc.Length; i++) { + vertexAttributes.Add (new VkVertexInputAttributeDescription (binding, i + currentAttributeIndex, attribsDesc[i], currentAttributeoffset)); VkFormatSize fs; Utils.vkGetFormatSize (attribsDesc[i], out fs); - offset += fs.blockSizeInBits/8; + currentAttributeoffset += fs.blockSizeInBits/8; } + currentAttributeIndex += (uint)attribsDesc.Length; } public void AddVertexBinding (uint binding, uint stride, VkVertexInputRate inputRate = VkVertexInputRate.Vertex) { vertexBindings.Add (new VkVertexInputBindingDescription (binding, stride, inputRate)); @@ -117,7 +118,8 @@ namespace CVKL { public void ResetShadersAndVerticesInfos () { foreach (ShaderInfo shader in shaders) shader.Dispose (); - vertexBindings.Clear (); + currentAttributeIndex = 0; + vertexBindings.Clear (); vertexAttributes.Clear (); shaders.Clear (); } diff --git a/vke/src/HostBuffer.cs b/vke/src/HostBuffer.cs new file mode 100644 index 0000000..a12cfd0 --- /dev/null +++ b/vke/src/HostBuffer.cs @@ -0,0 +1,104 @@ +// +// HostBuffer.cs +// +// Author: +// Jean-Philippe Bruyère <jp_bruyere@hotmail.com> +// +// Copyright (c) 2019 jp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using VK; +using static VK.Vk; + +namespace CVKL { + + public class HostBuffer<T> : HostBuffer { + int TSize; + + public HostBuffer (Device device, VkBufferUsageFlags usage, uint arrayElementCount, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, (ulong)(Marshal.SizeOf<T> () * arrayElementCount), keepMapped, coherentMem) { + TSize = Marshal.SizeOf<T>(); + } + public HostBuffer (Device device, VkBufferUsageFlags usage, IList<T> data, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, (ulong)(Marshal.SizeOf<T> () * data.Count), keepMapped, coherentMem) { + TSize = Marshal.SizeOf<T>(); + Map(); + Update (data, createInfo.size); + if (!keepMapped) + Unmap (); + } + public HostBuffer (Device device, VkBufferUsageFlags usage, T[] data, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, (ulong)(Marshal.SizeOf<T> () * data.Length), keepMapped, coherentMem) { + TSize = Marshal.SizeOf<T>(); + Map(); + Update (data, createInfo.size); + if (!keepMapped) + Unmap (); + } + public void Update (T[] data) { + Update (data, (ulong)(TSize * data.Length)); + } + public void Update (uint index, T data) { + GCHandle ptr = GCHandle.Alloc(data, GCHandleType.Pinned); + unsafe { + System.Buffer.MemoryCopy(ptr.AddrOfPinnedObject().ToPointer(), (mappedData + (int)(TSize*index)).ToPointer(), TSize, TSize); + } + ptr.Free(); + } + public void Flush (uint startIndex, uint endIndex) { + VkMappedMemoryRange mr = new VkMappedMemoryRange + { + sType = VkStructureType.MappedMemoryRange, + memory = memoryPool.vkMemory, + offset = poolOffset + (ulong)(startIndex * TSize), + size = (ulong)((endIndex - startIndex) * TSize) + }; + vkFlushMappedMemoryRanges(Dev.VkDev, 1, ref mr); + } + } + /// <summary> + /// Mappable Buffer with HostVisble and HostCoherent memory flags + /// </summary> + public class HostBuffer : Buffer { + public HostBuffer (Device device, VkBufferUsageFlags usage, UInt64 size, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, coherentMem ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent : VkMemoryPropertyFlags.HostVisible, size) { + if (keepMapped) + Map(); + } + public HostBuffer (Device device, VkBufferUsageFlags usage, object data, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, coherentMem ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent : VkMemoryPropertyFlags.HostVisible, (ulong)Marshal.SizeOf(data)) { + Map (); + Update (data, createInfo.size); + if (!keepMapped) + Unmap (); + } + public HostBuffer (Device device, VkBufferUsageFlags usage, UInt64 size, IntPtr data, bool keepMapped = false, bool coherentMem = true) + : base (device, usage, coherentMem ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent : VkMemoryPropertyFlags.HostVisible, size) { + Map (); + unsafe { + System.Buffer.MemoryCopy (data.ToPointer (), mappedData.ToPointer (), size, size); + } + if (!keepMapped) + Unmap (); + } + } +} diff --git a/vke/src/Model.cs b/vke/src/Model.cs index cc3a3dc..03cae49 100644 --- a/vke/src/Model.cs +++ b/vke/src/Model.cs @@ -97,8 +97,12 @@ namespace CVKL { max = _max; } } - - public class Primitive { + public class InstancedCmd + { + public int meshIdx; + public uint count; + } + public class Primitive { public string name; public UInt32 indexBase; public Int32 vertexBase; @@ -108,12 +112,6 @@ namespace CVKL { public BoundingBox bb; } - public struct InstanceData { - public UInt32 materialIndex; - public Matrix4x4 modelMat; - public Vector4 color; - }; - public class Mesh { public string Name; public List<Primitive> Primitives = new List<Primitive> (); diff --git a/vke/src/PbrModel.cs b/vke/src/PbrModel.cs index 761001a..d4b96ec 100644 --- a/vke/src/PbrModel.cs +++ b/vke/src/PbrModel.cs @@ -35,8 +35,8 @@ namespace CVKL { using static VK.Utils; //TODO:stride in buffer views? - public abstract class PbrModel : Model { - public struct Vertex { + public abstract class PbrModel : Model { + public new struct Vertex { [VertexAttribute (VertexAttributeType.Position, VkFormat.R32g32b32Sfloat)] public Vector3 pos; [VertexAttribute (VertexAttributeType.Normal, VkFormat.R32g32b32Sfloat)] @@ -55,7 +55,7 @@ namespace CVKL { public GPUBuffer ibo; public HostBuffer materialUBO; - public PbrModel (Queue transferQ, string path) { + public PbrModel (Queue transferQ, string path) { dev = transferQ.Dev; using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) { using (glTFLoader ctx = new glTFLoader (path, transferQ, cmdPool)) { @@ -104,8 +104,23 @@ namespace CVKL { RenderNode(cmd, pipelineLayout, scene.Root, Matrix4x4.Identity, shadowPass); } - #region IDisposable Support - protected bool isDisposed; + public void Draw (CommandBuffer cmd, PipelineLayout pipelineLayout, Buffer instanceBuf, bool shadowPass = false, params InstancedCmd[] instances) { + cmd.BindVertexBuffer(instanceBuf, 1); + uint firstInstance = 0; + for (int i = 0; i < instances.Length; i++) + { + foreach (Primitive p in Meshes[instances[i].meshIdx].Primitives) + { + if (!shadowPass) + cmd.PushConstant(pipelineLayout, VkShaderStageFlags.Fragment, (int)p.material, (uint)Marshal.SizeOf<Matrix4x4>()); + cmd.DrawIndexed(p.indexCount, instances[i].count, p.indexBase, p.vertexBase, firstInstance); + } + firstInstance += instances[i].count; + } + } + + #region IDisposable Support + protected bool isDisposed; protected virtual void Dispose (bool disposing) { if (!isDisposed) { diff --git a/vke/src/PbrModelTexArray.cs b/vke/src/PbrModelTexArray.cs index 47b6b74..b7b09e4 100644 --- a/vke/src/PbrModelTexArray.cs +++ b/vke/src/PbrModelTexArray.cs @@ -87,16 +87,18 @@ namespace CVKL { Meshes = new List<Mesh> (ctx.LoadMeshes<Vertex> (IndexBufferType, vbo, 0, ibo, 0)); - texArray = new Image (dev, Image.DefaultTextureFormat, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc, - VkMemoryPropertyFlags.DeviceLocal, TEXTURE_DIM, TEXTURE_DIM, VkImageType.Image2D, - VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, Image.ComputeMipLevels(TEXTURE_DIM), ctx.ImageCount); - - ctx.BuildTexArray (ref texArray, 0); + if (ctx.ImageCount > 0) { + texArray = new Image (dev, Image.DefaultTextureFormat, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc, + VkMemoryPropertyFlags.DeviceLocal, TEXTURE_DIM, TEXTURE_DIM, VkImageType.Image2D, + VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, Image.ComputeMipLevels (TEXTURE_DIM), ctx.ImageCount); - texArray.CreateView (VkImageViewType.ImageView2DArray, VkImageAspectFlags.Color, texArray.CreateInfo.arrayLayers); - texArray.CreateSampler (); - texArray.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - texArray.SetName ("model texArray"); + ctx.BuildTexArray (ref texArray, 0); + + texArray.CreateView (VkImageViewType.ImageView2DArray, VkImageAspectFlags.Color, texArray.CreateInfo.arrayLayers); + texArray.CreateSampler (); + texArray.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + texArray.SetName ("model texArray"); + } loadMaterials (ctx); diff --git a/vke/src/Resource.cs b/vke/src/Resource.cs index c44f893..50deb39 100644 --- a/vke/src/Resource.cs +++ b/vke/src/Resource.cs @@ -50,7 +50,6 @@ namespace CVKL { GCHandle ptr = GCHandle.Alloc (data, GCHandleType.Pinned); unsafe { System.Buffer.MemoryCopy (ptr.AddrOfPinnedObject ().ToPointer (), (mappedData + (int)offset).ToPointer (), size, size); - Flush ();//TODO:flush only if not coherent } ptr.Free (); } |