aboutsummaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-05-10 06:16:28 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-05-10 06:16:28 +0200
commita0330071543a504f765f5c438bec7e4363398fa7 (patch)
tree895be71e15a41f4f701c69b347b749d23f5f976a
parent36967cdfa2268a4303c0805fa0aa0b35f006ecde (diff)
debug: correction matrix as row major, embbed shaders after compilation, shaders dir in cvkl
-rw-r--r--samples/Textured/main.cs8
-rw-r--r--samples/TexturedCube/main.cs12
-rw-r--r--samples/Triangle/main.cs165
-rw-r--r--samples/Triangle/shaders/triangle.vert2
-rw-r--r--samples/deferred/EnvironmentPipeline.cs4
-rw-r--r--samples/deferred/deferredPbrRenderer.cs13
-rw-r--r--samples/deferred/main-crow.cs22
-rw-r--r--samples/deferred/main.cs24
-rw-r--r--samples/deferred/shaders/GBuffPbr.vert5
-rw-r--r--samples/deferred/shadowMapRenderer.cs2
-rw-r--r--samples/pbrSashaWillem/EnvironmentPipeline.cs14
-rw-r--r--samples/pbrSashaWillem/PbrPipeline.cs4
-rw-r--r--spirv.targets29
-rw-r--r--vke/CVKL.csproj6
-rw-r--r--vke/shaders/FullScreenQuad.vert10
-rw-r--r--vke/shaders/debug.frag12
-rw-r--r--vke/shaders/debug.vert34
-rw-r--r--vke/shaders/deffered/GBuffPbr.frag212
-rw-r--r--vke/shaders/deffered/GBuffPbr.vert37
-rw-r--r--vke/shaders/deffered/GBuffPbrTexArray.frag211
-rw-r--r--vke/shaders/deffered/compose.frag230
-rw-r--r--vke/shaders/deffered/compose_with_shadows.frag277
-rw-r--r--vke/shaders/deffered/show_gbuff.frag92
-rw-r--r--vke/shaders/deffered/tone_mapping.frag60
-rw-r--r--vke/shaders/emissive.frag25
-rw-r--r--vke/shaders/filtercube.vert19
-rw-r--r--vke/shaders/genbrdflut.frag90
-rw-r--r--vke/shaders/genbrdflut.vert9
-rw-r--r--vke/shaders/irradiancecube.frag37
-rw-r--r--vke/shaders/prefilterenvmap.frag105
-rw-r--r--vke/shaders/shadow.geom37
-rw-r--r--vke/shaders/shadow.vert8
-rw-r--r--vke/shaders/simpletexture.frag15
-rw-r--r--vke/shaders/skybox.frag12
-rw-r--r--vke/shaders/skybox.vert27
-rw-r--r--vke/src/Buffer.cs94
-rw-r--r--vke/src/Camera.cs4
-rw-r--r--vke/src/DebuDrawPipeline.cs83
-rw-r--r--vke/src/Device.cs34
-rw-r--r--vke/src/GPUBuffer.cs64
-rw-r--r--vke/src/GraphicPipelineConfig.cs16
-rw-r--r--vke/src/HostBuffer.cs104
-rw-r--r--vke/src/Model.cs14
-rw-r--r--vke/src/PbrModel.cs25
-rw-r--r--vke/src/PbrModelTexArray.cs20
-rw-r--r--vke/src/Resource.cs1
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 ();
}