diff --git a/README.md b/README.md index 3a713055..277aad92 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,8 @@ Distance field font textures can be generated with tools like [Hiero](https://gi ## [Pipelines](pipelines/) -Pipelines replace the huge (and cumbersome) state machine of OpenGL. This example creates different pipelines with different states and shader setups. +[Pipeline state objects](https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#pipelines) replace the biggest part of the dynamic state machine from OpenGL, baking state information for culling, blending, rasterization, etc. and shaders into a fixed stat that can be optimized much easier by the implementation. +This example uses three different PSOs for rendering the same scene with different visuals and shaders and also demonstrates the use [pipeline derivatives](https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#pipelines-pipeline-derivatives).

## [Gears](gears/) @@ -220,7 +221,7 @@ Implements a simple ray tracer using a compute shader. No primitives are rendere

## [(Compute shader) Image processing](computeshader/) - + Demonstrates the use of a separate compute queue (and command buffer) to apply different convolution kernels on an input image in realtime.

@@ -255,6 +256,7 @@ Please note that (some) models and textures use separate licenses. Please comply - Voyager model by [NASA](http://nasa3d.arc.nasa.gov/models) - Astroboy COLLADA model copyright 2008 Sony Computer Entertainment Inc. - Old deer model used in tessellation example by [Čestmír Dammer](http://opengameart.org/users/cdmir) +- Hidden treasure scene used in pipeline and debug marker examples by [Laurynas Jurgila](http://www.blendswap.com/user/PigArt) - Textures used in some examples by [Hugues Muller](http://www.yughues-folio.com) - Updated compute particle system shader by [Lukas Bergdoll](https://github.com/Voultapher) - Vulkan scene model (and derived models) by [Dominic Agoro-Ombaka](http://www.agorodesign.com/) and [Sascha Willems](http://www.saschawillems.de) diff --git a/data/shaders/pipelines/base.vert b/data/shaders/pipelines/base.vert deleted file mode 100644 index 6adc1349..00000000 --- a/data/shaders/pipelines/base.vert +++ /dev/null @@ -1,28 +0,0 @@ -#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 = 2) in vec2 inUV; -layout (location = 3) in vec3 inNormal; - -layout (binding = 0) uniform UBO -{ - mat4 projectionMatrix; - mat4 modelMatrix; - mat4 viewMatrix; -} ubo; - -layout (location = 0) out vec3 outColor; -layout (location = 1) out vec2 outUV; -layout (location = 2) out vec3 outNormal; - -void main() -{ - outColor = inColor; - outUV = inUV; - outNormal = inNormal; - gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0); -} diff --git a/data/shaders/pipelines/base.vert.spv b/data/shaders/pipelines/base.vert.spv deleted file mode 100644 index 22cd95b9..00000000 Binary files a/data/shaders/pipelines/base.vert.spv and /dev/null differ diff --git a/data/shaders/pipelines/color.frag b/data/shaders/pipelines/color.frag deleted file mode 100644 index e5abb03d..00000000 --- a/data/shaders/pipelines/color.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - -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/data/shaders/pipelines/color.frag.spv b/data/shaders/pipelines/color.frag.spv deleted file mode 100644 index 1a102443..00000000 Binary files a/data/shaders/pipelines/color.frag.spv and /dev/null differ diff --git a/data/shaders/pipelines/generate-spriv.bat b/data/shaders/pipelines/generate-spriv.bat index 175c2508..17806643 100644 --- a/data/shaders/pipelines/generate-spriv.bat +++ b/data/shaders/pipelines/generate-spriv.bat @@ -1,6 +1,7 @@ -glslangvalidator -V base.vert -o base.vert.spv -glslangvalidator -V base.frag -o base.frag.spv -glslangvalidator -V color.frag -o color.frag.spv -glslangvalidator -V texture.frag -o texture.frag.spv +glslangvalidator -V phong.vert -o phong.vert.spv +glslangvalidator -V phong.frag -o phong.frag.spv +glslangvalidator -V wireframe.vert -o wireframe.vert.spv glslangvalidator -V wireframe.frag -o wireframe.frag.spv +glslangvalidator -V toon.vert -o toon.vert.spv +glslangvalidator -V toon.frag -o toon.frag.spv diff --git a/data/shaders/pipelines/phong.frag b/data/shaders/pipelines/phong.frag new file mode 100644 index 00000000..4eabd4da --- /dev/null +++ b/data/shaders/pipelines/phong.frag @@ -0,0 +1,30 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D samplerColorMap; + +layout (location = 0) in vec3 inNormal; +layout (location = 1) in vec3 inColor; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inViewVec; +layout (location = 4) in vec3 inLightVec; + +layout (location = 0) out vec4 outFragColor; + +void main() +{ + // Desaturate color + vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); + + // High ambient colors because mesh materials are pretty dark + vec3 ambient = color * vec3(1.0); + vec3 N = normalize(inNormal); + vec3 L = normalize(inLightVec); + vec3 V = normalize(inViewVec); + vec3 R = reflect(-L, N); + vec3 diffuse = max(dot(N, L), 0.0) * color; + vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.35); + outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); +} \ No newline at end of file diff --git a/data/shaders/pipelines/phong.frag.spv b/data/shaders/pipelines/phong.frag.spv new file mode 100644 index 00000000..1e547c40 Binary files /dev/null and b/data/shaders/pipelines/phong.frag.spv differ diff --git a/data/shaders/pipelines/phong.vert b/data/shaders/pipelines/phong.vert new file mode 100644 index 00000000..293173bf --- /dev/null +++ b/data/shaders/pipelines/phong.vert @@ -0,0 +1,41 @@ +#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 inNormal; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + vec4 lightPos; +} ubo; + +layout (location = 0) out vec3 outNormal; +layout (location = 1) out vec3 outColor; +layout (location = 2) out vec2 outUV; +layout (location = 3) out vec3 outViewVec; +layout (location = 4) out vec3 outLightVec; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + outNormal = inNormal; + outColor = inColor; + outUV = inUV; + gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); + + vec4 pos = ubo.model * vec4(inPos, 1.0); + outNormal = mat3(ubo.model) * inNormal; + vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; + outLightVec = lPos - pos.xyz; + outViewVec = -pos.xyz; +} \ No newline at end of file diff --git a/data/shaders/pipelines/phong.vert.spv b/data/shaders/pipelines/phong.vert.spv new file mode 100644 index 00000000..d6215eb5 Binary files /dev/null and b/data/shaders/pipelines/phong.vert.spv differ diff --git a/data/shaders/pipelines/texture.frag b/data/shaders/pipelines/texture.frag deleted file mode 100644 index 0d174f4c..00000000 --- a/data/shaders/pipelines/texture.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout (binding = 1) uniform sampler2D colorMap; - -layout (location = 1) in vec2 inUV; -layout (location = 2) in vec3 inNormal; - -layout (location = 0) out vec4 outFragColor; - -void main() -{ - outFragColor = texture(colorMap, inUV); - outFragColor.rgb = inNormal; - - vec3 N = normalize(inNormal); - vec3 L = normalize(vec3(2.0, 2.0, 2.0)); - - vec3 color = texture(colorMap, inUV).rgb; - outFragColor.rgb = vec3(clamp(max(dot(N,L), 0.0), 0.15, 1.0)) * color; -} - \ No newline at end of file diff --git a/data/shaders/pipelines/texture.frag.spv b/data/shaders/pipelines/texture.frag.spv deleted file mode 100644 index 76c3ce74..00000000 Binary files a/data/shaders/pipelines/texture.frag.spv and /dev/null differ diff --git a/data/shaders/pipelines/toon.frag b/data/shaders/pipelines/toon.frag new file mode 100644 index 00000000..0f98b5e3 --- /dev/null +++ b/data/shaders/pipelines/toon.frag @@ -0,0 +1,39 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D samplerColorMap; + +layout (location = 0) in vec3 inNormal; +layout (location = 1) in vec3 inColor; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inViewVec; +layout (location = 4) in vec3 inLightVec; + +layout (location = 0) out vec4 outFragColor; + +void main() +{ + // Desaturate color + vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); + + // High ambient colors because mesh materials are pretty dark + vec3 ambient = color * vec3(1.0); + vec3 N = normalize(inNormal); + vec3 L = normalize(inLightVec); + vec3 V = normalize(inViewVec); + vec3 R = reflect(-L, N); + vec3 diffuse = max(dot(N, L), 0.0) * color; + vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); + outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); + + float intensity = dot(N,L); + float shade = 1.0; + shade = intensity < 0.5 ? 0.75 : shade; + shade = intensity < 0.35 ? 0.6 : shade; + shade = intensity < 0.25 ? 0.5 : shade; + shade = intensity < 0.1 ? 0.25 : shade; + + outFragColor.rgb = inColor * 3.0 * shade; +} \ No newline at end of file diff --git a/data/shaders/pipelines/toon.frag.spv b/data/shaders/pipelines/toon.frag.spv new file mode 100644 index 00000000..0e3518d9 Binary files /dev/null and b/data/shaders/pipelines/toon.frag.spv differ diff --git a/data/shaders/pipelines/toon.vert b/data/shaders/pipelines/toon.vert new file mode 100644 index 00000000..293173bf --- /dev/null +++ b/data/shaders/pipelines/toon.vert @@ -0,0 +1,41 @@ +#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 inNormal; +layout (location = 2) in vec2 inUV; +layout (location = 3) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + vec4 lightPos; +} ubo; + +layout (location = 0) out vec3 outNormal; +layout (location = 1) out vec3 outColor; +layout (location = 2) out vec2 outUV; +layout (location = 3) out vec3 outViewVec; +layout (location = 4) out vec3 outLightVec; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + outNormal = inNormal; + outColor = inColor; + outUV = inUV; + gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); + + vec4 pos = ubo.model * vec4(inPos, 1.0); + outNormal = mat3(ubo.model) * inNormal; + vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; + outLightVec = lPos - pos.xyz; + outViewVec = -pos.xyz; +} \ No newline at end of file diff --git a/data/shaders/pipelines/toon.vert.spv b/data/shaders/pipelines/toon.vert.spv new file mode 100644 index 00000000..d6215eb5 Binary files /dev/null and b/data/shaders/pipelines/toon.vert.spv differ diff --git a/data/shaders/pipelines/wireframe.frag b/data/shaders/pipelines/wireframe.frag index 1625fb1f..ecfa03c2 100644 --- a/data/shaders/pipelines/wireframe.frag +++ b/data/shaders/pipelines/wireframe.frag @@ -1,10 +1,13 @@ #version 450 -layout (location = 0 ) in vec3 inColor; +#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(1.0); + outFragColor.rgb = inColor * 1.5; } \ No newline at end of file diff --git a/data/shaders/pipelines/wireframe.frag.spv b/data/shaders/pipelines/wireframe.frag.spv index 80d0acdd..987c629d 100644 Binary files a/data/shaders/pipelines/wireframe.frag.spv and b/data/shaders/pipelines/wireframe.frag.spv differ diff --git a/data/shaders/pipelines/wireframe.vert b/data/shaders/pipelines/wireframe.vert new file mode 100644 index 00000000..f842fec1 --- /dev/null +++ b/data/shaders/pipelines/wireframe.vert @@ -0,0 +1,28 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec4 inPos; +layout (location = 3) in vec3 inColor; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; +} ubo; + +layout (location = 0) out vec3 outColor; + +out gl_PerVertex +{ + vec4 gl_Position; +}; + +void main() +{ + { + outColor = inColor; + } + gl_Position = ubo.projection * ubo.model * inPos; +} diff --git a/data/shaders/pipelines/wireframe.vert.spv b/data/shaders/pipelines/wireframe.vert.spv new file mode 100644 index 00000000..9e254ace Binary files /dev/null and b/data/shaders/pipelines/wireframe.vert.spv differ diff --git a/pipelines/pipelines.cpp b/pipelines/pipelines.cpp index 684f68af..56b57e6e 100644 --- a/pipelines/pipelines.cpp +++ b/pipelines/pipelines.cpp @@ -16,21 +16,20 @@ #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include -#include #include - #include "vulkanexamplebase.h" #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false // Vertex layout for this example -struct Vertex { - float pos[3]; - float col[3]; - float uv[2]; - float normal[3]; +std::vector vertexLayout = +{ + vkMeshLoader::VERTEX_LAYOUT_POSITION, + vkMeshLoader::VERTEX_LAYOUT_NORMAL, + vkMeshLoader::VERTEX_LAYOUT_UV, + vkMeshLoader::VERTEX_LAYOUT_COLOR }; class VulkanExample: public VulkanExampleBase @@ -39,7 +38,6 @@ private: vkTools::VulkanTexture textureColorMap; public: struct { - int count; VkPipelineVertexInputStateCreateInfo inputState; std::vector bindingDescriptions; std::vector attributeDescriptions; @@ -53,9 +51,9 @@ public: // Same uniform buffer layout as shader struct { - glm::mat4 projectionMatrix; - glm::mat4 modelMatrix; - glm::mat4 viewMatrix; + glm::mat4 projection; + glm::mat4 modelView; + glm::vec4 lightPos = glm::vec4(0.0f, 2.0f, 1.0f, 0.0f); } uboVS; VkPipelineLayout pipelineLayout; @@ -63,29 +61,29 @@ public: VkDescriptorSetLayout descriptorSetLayout; struct { - VkPipeline solidColor; - VkPipeline wireFrame; - VkPipeline texture; + VkPipeline phong; + VkPipeline wireframe; + VkPipeline toon; } pipelines; VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { - zoom = -5.0f; - rotation = glm::vec3(-32.5f, 45.0f, 0.0f); + zoom = -10.5f; + rotation = glm::vec3(-25.0f, 15.0f, 0.0f); enableTextOverlay = true; - title = "Vulkan Example - Using pipelines"; + title = "Vulkan Example - Pipeline state objects"; } ~VulkanExample() { // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.solidColor, nullptr); + vkDestroyPipeline(device, pipelines.phong, nullptr); if (deviceFeatures.fillModeNonSolid) { - vkDestroyPipeline(device, pipelines.wireFrame, nullptr); + vkDestroyPipeline(device, pipelines.wireframe, nullptr); } - vkDestroyPipeline(device, pipelines.texture, nullptr); + vkDestroyPipeline(device, pipelines.toon, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); @@ -142,30 +140,29 @@ public: VkDeviceSize offsets[1] = { 0 }; vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.cube.vertices.buf, offsets); - - vkCmdSetLineWidth(drawCmdBuffers[i], 2.0f); + vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.cube.indices.buf, 0, VK_INDEX_TYPE_UINT32); // Left : Solid colored viewport.width = (float)width / 3.0; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solidColor); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong); - vkCmdDraw(drawCmdBuffers[i], vertices.count, 1, 0, 0); + vkCmdDrawIndexed(drawCmdBuffers[i], meshes.cube.indexCount, 1, 0, 0, 0); - // Center : Textured + // Center : Toon viewport.x = (float)width / 3.0; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.texture); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toon); vkCmdSetLineWidth(drawCmdBuffers[i], 2.0f); - vkCmdDraw(drawCmdBuffers[i], vertices.count, 1, 0, 0); + vkCmdDrawIndexed(drawCmdBuffers[i], meshes.cube.indexCount, 1, 0, 0, 0); if (deviceFeatures.fillModeNonSolid) { // Right : Wireframe viewport.x = (float)width / 3.0 + (float)width / 3.0; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireFrame); - vkCmdDraw(drawCmdBuffers[i], vertices.count, 1, 0, 0); + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireframe); + vkCmdDrawIndexed(drawCmdBuffers[i], meshes.cube.indexCount, 1, 0, 0, 0); } vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -174,72 +171,9 @@ public: } } - // Create vertices and buffers for uv mapped cube - void generateCube() + void loadMeshes() { - - // Setup vertices -#define colred { 1.0f, 0.0f, 0.0f } -#define colgreen { 0.0f, 1.0f, 0.0f } -#define colblue { 0.0f, 0.0f, 1.0f } -#define d 1.0f - - std::vector vertexBuffer = { - - // -Y - { { d,-d, d }, colred,{ 1.0, 1.0 }, { 0.0f, 1.0f, 0.0f } }, - { { -d,-d,-d }, colred,{ 0.0, 0.0 },{ 0.0f, 1.0f, 0.0f } }, - { { d,-d,-d }, colred,{ 1.0, 0.0 },{ 0.0f, 1.0f, 0.0f } }, - { { d,-d, d }, colred,{ 1.0, 1.0 },{ 0.0f, 1.0f, 0.0f } }, - { { -d,-d, d }, colred,{ 0.0, 1.0 },{ 0.0f, 1.0f, 0.0f } }, - { { -d,-d,-d }, colred,{ 0.0, 0.0 },{ 0.0f, 1.0f, 0.0f } }, - // +Y - { { d, d, d }, colred,{ 1.0, 1.0 },{ 0.0f, -1.0f, 0.0f } }, - { { d, d,-d }, colred,{ 1.0, 0.0 },{ 0.0f, -1.0f, 0.0f } }, - { { -d, d,-d }, colred,{ 0.0, 0.0 },{ 0.0f, -1.0f, 0.0f } }, - { { d, d, d }, colred,{ 1.0, 1.0 },{ 0.0f, -1.0f, 0.0f } }, - { { -d, d,-d }, colred,{ 0.0, 0.0 },{ 0.0f, -1.0f, 0.0f } }, - { { -d, d, d }, colred,{ 0.0, 1.0 },{ 0.0f, -1.0f, 0.0f } }, - // -X - { { -d,-d,-d }, colblue,{ 0.0, 0.0 },{ -1.0f, 0.0f, 0.0f } }, - { { -d,-d, d }, colblue,{ 0.0, 1.0 },{ -1.0f, 0.0f, 0.0f } }, - { { -d, d, d }, colblue,{ 1.0, 1.0 },{ -1.0f, 0.0f, 0.0f } }, - { { -d,-d,-d }, colblue,{ 0.0, 0.0 },{ -1.0f, 0.0f, 0.0f } }, - { { -d, d, d }, colblue,{ 1.0, 1.0 },{ -1.0f, 0.0f, 0.0f } }, - { { -d, d,-d }, colblue,{ 1.0, 0.0 },{ -1.0f, 0.0f, 0.0f } }, - // +X - { { d, d, d }, colblue,{ 1.0, 1.0 },{ 1.0f, 0.0f, 0.0f } }, - { { d,-d,-d }, colblue,{ 0.0, 0.0 },{ 1.0f, 0.0f, 0.0f } }, - { { d, d,-d }, colblue,{ 1.0, 0.0 },{ 1.0f, 0.0f, 0.0f } }, - { { d,-d,-d }, colblue,{ 0.0, 0.0 },{ 1.0f, 0.0f, 0.0f } }, - { { d, d, d }, colblue,{ 1.0, 1.0 },{ 1.0f, 0.0f, 0.0f } }, - { { d,-d, d }, colblue,{ 0.0, 1.0 },{ 1.0f, 0.0f, 0.0f } }, - // -Z - { { d, d,-d }, colgreen,{ 1.0, 1.0 },{ 0.0f, 0.0f, -1.0f } }, - { { -d,-d,-d }, colgreen,{ 0.0, 0.0 },{ 0.0f, 0.0f, -1.0f } }, - { { -d, d,-d }, colgreen,{ 0.0, 1.0 },{ 0.0f, 0.0f, -1.0f } }, - { { d, d,-d }, colgreen,{ 1.0, 1.0 },{ 0.0f, 0.0f, -1.0f } }, - { { d,-d,-d }, colgreen,{ 1.0, 0.0 },{ 0.0f, 0.0f, -1.0f } }, - { { -d,-d,-d }, colgreen,{ 0.0, 0.0 },{ 0.0f, 0.0f, -1.0f } }, - // +Z - { { -d, d, d }, colgreen,{ 0.0, 1.0 },{ 0.0f, 0.0f, 1.0f } }, - { { -d,-d, d }, colgreen,{ 0.0, 0.0 },{ 0.0f, 0.0f, 1.0f } }, - { { d,-d, d }, colgreen,{ 1.0, 0.0 },{ 0.0f, 0.0f, 1.0f } }, - { { d, d, d }, colgreen,{ 1.0, 1.0 },{ 0.0f, 0.0f, 1.0f } }, - { { -d, d, d }, colgreen,{ 0.0, 1.0 },{ 0.0f, 0.0f, 1.0f } }, - { { d,-d, d }, colgreen,{ 1.0, 0.0 },{ 0.0f, 0.0f, 1.0f } } - - }; -#undef d - - vertices.count = vertexBuffer.size(); - - createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - vertexBuffer.size() * sizeof(Vertex), - vertexBuffer.data(), - &meshes.cube.vertices.buf, - &meshes.cube.vertices.mem); + loadMesh(getAssetPath() + "models/treasure_smooth.dae", &meshes.cube, vertexLayout, 1.0f); } void setupVertexDescriptions() @@ -249,7 +183,7 @@ public: vertices.bindingDescriptions[0] = vkTools::initializers::vertexInputBindingDescription( VERTEX_BUFFER_BIND_ID, - sizeof(Vertex), + vkMeshLoader::vertexSize(vertexLayout), VK_VERTEX_INPUT_RATE_VERTEX); // Attribute descriptions @@ -387,7 +321,7 @@ public: VkPipelineRasterizationStateCreateInfo rasterizationState = vkTools::initializers::pipelineRasterizationStateCreateInfo( VK_POLYGON_MODE_FILL, - VK_CULL_MODE_FRONT_BIT, + VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0); @@ -417,8 +351,7 @@ public: std::vector dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_LINE_WIDTH + VK_DYNAMIC_STATE_SCISSOR }; VkPipelineDynamicStateCreateInfo dynamicState = vkTools::initializers::pipelineDynamicStateCreateInfo( @@ -426,12 +359,11 @@ public: dynamicStateEnables.size(), 0); - // Color pipeline - // Load shaders std::array shaderStages; - shaderStages[0] = loadShader(getAssetPath() + "shaders/pipelines/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - shaderStages[1] = loadShader(getAssetPath() + "shaders/pipelines/color.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + // Phong shading pipeline + shaderStages[0] = loadShader(getAssetPath() + "shaders/pipelines/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/pipelines/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); VkGraphicsPipelineCreateInfo pipelineCreateInfo = vkTools::initializers::pipelineCreateInfo( @@ -450,27 +382,37 @@ public: pipelineCreateInfo.stageCount = shaderStages.size(); pipelineCreateInfo.pStages = shaderStages.data(); + // We are using this pipeline as the base for the other pipelines (derivatives) + // Pipeline derivatives can be used for pipelines that share most of their state + // Depending on the implementation this may result in better performance for pipeline + // switchting and faster creation time + pipelineCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; + // Textured pipeline - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solidColor)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.phong)); - // Reuse most of the initial pipeline for the next pipelines and only change affected parameters - // Cull back faces - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; + // All pipelines created after the base pipeline will be derivatives + pipelineCreateInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; + // Base pipeline will be our first created pipeline + pipelineCreateInfo.basePipelineHandle = pipelines.phong; + // It's only allowed to either use a handle or index for the base pipeline + // As we use the handle, we must set the index to -1 (see section 9.5 of the specification) + pipelineCreateInfo.basePipelineIndex = -1; - // Pipeline for textured rendering - // Use different fragment shader - shaderStages[1] = loadShader(getAssetPath() + "shaders/pipelines/texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.texture)); + // Toon shading pipeline + shaderStages[0] = loadShader(getAssetPath() + "shaders/pipelines/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); + shaderStages[1] = loadShader(getAssetPath() + "shaders/pipelines/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); + + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.toon)); // Non solid rendering is not a mandatory Vulkan feature if (deviceFeatures.fillModeNonSolid) { // Pipeline for wire frame rendering - // Solid polygon fill rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; - // Use different fragment shader + shaderStages[0] = loadShader(getAssetPath() + "shaders/pipelines/wireframe.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/pipelines/wireframe.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wireFrame)); + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wireframe)); } } @@ -492,14 +434,14 @@ public: void updateUniformBuffers() { - uboVS.projectionMatrix = glm::perspective(glm::radians(60.0f), (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); + uboVS.projection = glm::perspective(glm::radians(60.0f), (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); - uboVS.viewMatrix = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, zoom)); + glm::mat4 viewMatrix = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, zoom)); - uboVS.modelMatrix = glm::mat4(); - uboVS.modelMatrix = glm::rotate(uboVS.modelMatrix, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - uboVS.modelMatrix = glm::rotate(uboVS.modelMatrix, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - uboVS.modelMatrix = glm::rotate(uboVS.modelMatrix, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + uboVS.modelView = viewMatrix * glm::translate(glm::mat4(), cameraPos); + uboVS.modelView = glm::rotate(uboVS.modelView, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); + uboVS.modelView = glm::rotate(uboVS.modelView, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); + uboVS.modelView = glm::rotate(uboVS.modelView, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); uint8_t *pData; VK_CHECK_RESULT(vkMapMemory(device, uniformDataVS.memory, 0, sizeof(uboVS), 0, (void **)&pData)); @@ -522,10 +464,10 @@ public: { VulkanExampleBase::prepare(); loadTextures(); + loadMeshes(); setupVertexDescriptions(); prepareUniformBuffers(); setupDescriptorSetLayout(); - generateCube(); preparePipelines(); setupDescriptorPool(); setupDescriptorSet(); @@ -545,6 +487,12 @@ public: updateUniformBuffers(); } + virtual void getOverlayText(VulkanTextOverlay *textOverlay) + { + textOverlay->addText("Phong shading pipeline",(float)width / 6.0f, height - 35.0f, VulkanTextOverlay::alignCenter); + textOverlay->addText("Toon shading pipeline", (float)width / 2.0f, height - 35.0f, VulkanTextOverlay::alignCenter); + textOverlay->addText("Wireframe pipeline", width - (float)width / 6.5f, height - 35.0f, VulkanTextOverlay::alignCenter); + } }; VulkanExample *vulkanExample; diff --git a/screenshots/basic_pipelines.png b/screenshots/basic_pipelines.png index 515980d9..18b75fdb 100644 Binary files a/screenshots/basic_pipelines.png and b/screenshots/basic_pipelines.png differ diff --git a/screenshots/compute_imageprocessing.jpg b/screenshots/compute_imageprocessing.jpg new file mode 100644 index 00000000..0b6edadd Binary files /dev/null and b/screenshots/compute_imageprocessing.jpg differ diff --git a/screenshots/compute_imageprocessing.png b/screenshots/compute_imageprocessing.png deleted file mode 100644 index 7c8c9a2e..00000000 Binary files a/screenshots/compute_imageprocessing.png and /dev/null differ diff --git a/screenshots/compute_particles.jpg b/screenshots/compute_particles.jpg index 7a814388..666b1601 100644 Binary files a/screenshots/compute_particles.jpg and b/screenshots/compute_particles.jpg differ diff --git a/screenshots/spherical_env_mapping.png b/screenshots/spherical_env_mapping.png index e29d7cae..0b0f5366 100644 Binary files a/screenshots/spherical_env_mapping.png and b/screenshots/spherical_env_mapping.png differ