From 75b2a72957c37337b88908d0dae6f83ee75368f5 Mon Sep 17 00:00:00 2001 From: saschawillems Date: Thu, 21 Dec 2017 21:28:31 +0100 Subject: [PATCH] Texture tree and terrain scene, refactoring and cleanup --- .../shadowmappingcascade/debugshadowmap.frag | 7 +- .../debugshadowmap.frag.spv | Bin 1144 -> 1020 bytes .../shadowmappingcascade/debugshadowmap.vert | 8 +- .../debugshadowmap.vert.spv | Bin 956 -> 1304 bytes .../shadowmappingcascade/depthpass.frag | 8 + .../shadowmappingcascade/depthpass.frag.spv | Bin 180 -> 696 bytes .../shadowmappingcascade/depthpass.vert | 8 +- .../shadowmappingcascade/depthpass.vert.spv | Bin 1172 -> 1592 bytes data/shaders/shadowmappingcascade/scene.frag | 18 +- .../shadowmappingcascade/scene.frag.spv | Bin 8188 -> 8704 bytes data/shaders/shadowmappingcascade/scene.vert | 14 +- .../shadowmappingcascade/scene.vert.spv | Bin 1920 -> 2400 bytes .../shadowmappingcascade.cpp | 234 ++++++++++++------ 13 files changed, 200 insertions(+), 97 deletions(-) diff --git a/data/shaders/shadowmappingcascade/debugshadowmap.frag b/data/shaders/shadowmappingcascade/debugshadowmap.frag index 70aaf94a..37bcad80 100644 --- a/data/shaders/shadowmappingcascade/debugshadowmap.frag +++ b/data/shaders/shadowmappingcascade/debugshadowmap.frag @@ -3,15 +3,12 @@ layout (binding = 1) uniform sampler2DArray shadowMap; layout (location = 0) in vec2 inUV; +layout (location = 1) flat in uint inCascadeIndex; layout (location = 0) out vec4 outFragColor; -layout(push_constant) uniform PushConsts { - uint cascadeIndex; -} pushConsts; - void main() { - float depth = texture(shadowMap, vec3(inUV, float(pushConsts.cascadeIndex))).r; + float depth = texture(shadowMap, vec3(inUV, float(inCascadeIndex))).r; outFragColor = vec4(vec3((depth)), 1.0); } \ No newline at end of file diff --git a/data/shaders/shadowmappingcascade/debugshadowmap.frag.spv b/data/shaders/shadowmappingcascade/debugshadowmap.frag.spv index 04713235782d2a08667a324205b25f3e40b0ddef..89357ed7c537eb7114a158f49d1334c4e254b1c4 100644 GIT binary patch literal 1020 zcmZ9K-Ahzq5XL9>BTLiFuhc%yW*>qeU8n?6UI;FMff42Pp|j*d?Jn+$UiP>3S9KHk z`@Op_h;ta`eV%z{&dhsGZEEvw#2udL*ov_uGUCYmX>kG~%83`f<@?%rD!b5Tn| zHS^TfiTdxd+cWVHU&4!YuB99=p{hpbh`$szU~krlr^!{F!RU3&&sNQ`MDe< zuAX{#d*8kTQ8d$gy1m14_@k^kpL$j2YRnhp`xm35^YZ6m|5yK9eVcdK^MwG*xW(CB z#LoT<*V@eM9&_njPiJ#kTX4?WMK*J{R@ySsd4+QmPF+E7??9JZi+eodv;DN&afAB% z@an9eQH068pJ4aVR>96`Z|6`yPqe4Jda?V-ErTBs3tUsbNHiy}UhMvI_FpC1->)y; zm|(x-HrTqSxMsiSM78SdCoXU~_4eAtBmNxh^EI8@UYeSJFb$%$-kbl2@dMa9c!0aV z*c}&e_Y*tIGVc5Xu#>dkw{&QcJ~ J{ink_{2C0|F+BhP literal 1144 zcmYk4U279j5QfJlX{y!MTH9Kybz{_4tHlcyK~$t*6)HqTy$`(e@lrEktP?0AOXBEmjLXOp+5`L~17 z_tB}`L;A7)Z5^ccJDiSJ*BuzE@2qd-Ij)XO-`pFN2ukXIa)w5f+L!q5?-J_n^xe-2>Tcc; zW$&A)^E#6p`@4>ckMXU)Rbd~A(Z7kBN2xL2hnRcn!Ez6`P`Tcj<16tQwu9Q2_jP=? z!ZGoR$(%#Xo~(Hf6{~aaRG7G0=ef_>JEg`Ra2B(-8r!Qd_t|4(8TKJ+ynOH7yS?~7 Ky!%In=jeaTQ#dtyX)nw)Gm5#%rswf{GyC=tC6x5E1(-p$Qt$M0!%_qu{$gN(BFs zFM@0BvyTRMm@_lq%>MRVQYp9RLMZW@5BEZTRzev+goRL#y1Vyguaiv&o%;`V%vcPS zm}t&YI1%kC-%tI~SV!a(avo_T6@F#(cP`XImEXTyee)+r)3^KR8gF{{{l|Cv!^7$D z_|Z>1Yz`s)xCVTlc{% z3BEj+&7a}1mKGSb^oECdIk=Hu++(bGqDG(g>*=Px8o3*N`&vM@Qrv!wThGhX2j*Xn z0y8e}GScM@`*ohii#p`>7#B0X%2(Y2b7R`;Saoz0*`P+2AAMs@{CTvw;*XQ>e#F-B zPokShDe7wMM_b%{>#$F;?UcXxpKl+&C*KCTiFkbf9NM?U<ihEz*y^6{2ytU15z}iB4-`FPFcf`D_-%eQ3%T;`jzI9xWUU**kH>3aM zS>bQz@yLG{TYler$nKnheR#xwfz;4XK%M7l#996T)n7`O^Zc2xm4rLfNvi1#ws^s_ ziY-rZ=Pb6^?431y@gBVHejSlV{3+ErGqD%Mo#7S4xmt_w6nhjm-<>s6OulP~9N!ZE zjf6SB;>}yw&QJN8^0u(eHTD|JncqglJq30LTdaii=)f6w5Oa;W2YIdEJ?tRv)_q#9 LzWKjlc!c}`a~x4h delta 433 zcmXw!%}&Bl6ok*UBG|~vMN3gEqC(=D1Y-Q#nYbxWU|5+Z3JZ0OiF*^$jc?#X=*EZe zaY*>4+@5A~XXc*HJ?AU@tv7?MUfs;`HEghK4%-b=ZG-1&J`>*sdmvd(?_FGUUDS%@ zQ;$y%+59Dc&F3?#Szt*qasApIJTCs+KHdNBdl3;A(Y*r{+@Vtm@=}}@X8`0~c%69f z938^jKqal5!&2EzrH@MeeqHI~&AswNJ45J!sCWy07MDb@vmF5K_Q|-?9q%bR^Ii&9 zwD94*E?m7SnBZxg9+0o9yc4)Q2QpsJx~FF2vRRj!QNg!_Xv99y-rDtwfu;GuRz!@z E8ZPr6r~m)} diff --git a/data/shaders/shadowmappingcascade/depthpass.frag b/data/shaders/shadowmappingcascade/depthpass.frag index 9941acf4..2e239363 100644 --- a/data/shaders/shadowmappingcascade/depthpass.frag +++ b/data/shaders/shadowmappingcascade/depthpass.frag @@ -1,5 +1,13 @@ #version 450 +layout (set = 1, binding = 0) uniform sampler2D colorMap; + +layout (location = 0) in vec2 inUV; + void main() { + float alpha = texture(colorMap, inUV).a; + if (alpha < 0.5) { + discard; + } } \ No newline at end of file diff --git a/data/shaders/shadowmappingcascade/depthpass.frag.spv b/data/shaders/shadowmappingcascade/depthpass.frag.spv index b128ff56de2d0080840b51d4953af6720527a40e..803c2dcaccaf92d25750dec72d868c0a02c77177 100644 GIT binary patch literal 696 zcmYk3&r3o<6on_Bnq_I_ugnOoWgsmof~b~mY!OkdAGJs@mFkac-9J@CLEkqjcpvB8 zd(WJ?bKblpbFdu35>FxQg=uVt41Ea2kdL|7zwLM5-k-Y1Cr2tuA&EjYWi(l`cu5B% z7d9f2$T1vs!o(0h*^q->)Y=zVONW!^l$_&PBR`IZ%|6h> zyzfvO_Uh-~Q{i;a??fjd)^+MUTstBg^eN<;VTET}JAX0eeT)68EU0U9UU4RpJD>G> zG#d0Jva|J}zD#zOyn1^*%clyipb4IuY{USB&i cPQPF1cge;Nde>S&POsL#+={i_AN3jd2Q$1OFaQ7m delta 56 zcmdnNx`mOKnMs+Qfq@YSIT+X`@|yCqGO#c(fN^eOW*)=DQ0<9NL?+*1l;QXbRAd3f E0PKMYxBvhE diff --git a/data/shaders/shadowmappingcascade/depthpass.vert b/data/shaders/shadowmappingcascade/depthpass.vert index 9bf8daf2..0abfbda0 100644 --- a/data/shaders/shadowmappingcascade/depthpass.vert +++ b/data/shaders/shadowmappingcascade/depthpass.vert @@ -1,11 +1,13 @@ #version 450 layout (location = 0) in vec3 inPos; +layout (location = 1) in vec2 inUV; // todo: pass via specialization constant #define SHADOW_MAP_CASCADE_COUNT 4 layout(push_constant) uniform PushConsts { + vec4 position; uint cascadeIndex; } pushConsts; @@ -13,11 +15,15 @@ layout (binding = 0) uniform UBO { mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat; } ubo; +layout (location = 0) out vec2 outUV; + out gl_PerVertex { vec4 gl_Position; }; void main() { - gl_Position = ubo.cascadeViewProjMat[pushConsts.cascadeIndex] * vec4(inPos, 1.0); + outUV = inUV; + vec3 pos = inPos + pushConsts.position.xyz; + gl_Position = ubo.cascadeViewProjMat[pushConsts.cascadeIndex] * vec4(pos, 1.0); } \ No newline at end of file diff --git a/data/shaders/shadowmappingcascade/depthpass.vert.spv b/data/shaders/shadowmappingcascade/depthpass.vert.spv index c9a61d1a1485fa8280228196365c0d0da3a893a9..60475d8533994ac9f1d629fc26bee4854998594a 100644 GIT binary patch literal 1592 zcmYk6+fGwK6o#iqswj$xpki&Uii*|~Ac^q+UKA4yHHO}rN*k@w*7Oj))JO1@d@65D z{Jz~i%IvJY=Kt3}Yu2pUZ7y4z2_eH%3R_`1=0g@7!fYrezOnaauRa=g>gyZ#RLq53 zB2;rK982bT-k;mOzCdOco5!kHjwg%%#ezb}^ZeI})ek1)gBD)w+Fn0_;2e8|@MSPc zV&?4in;^A?u!wI?Mju`b`lB&qkw?zKn%=lKNNOsEnS{6I!}jQ~-RZvUce>xynP*A; zkvs+RT!wr9>20$+Y;}j@sn-1R4r6f(>-4M+=hyHDJNu|h$y`3&x7F)@Z4L(?U$w_m z?JBX!yFqBAy(lYYi0y^gy2YM9#&^^6Lxq|zMXoyHo}V^6#Thx0)%R=RDKjg}nL1esk9B`el3tGyhtO&og&e&jq|%bC#*v`*Loqg7+M9<`!2m zxn;0@S8J{2wx(K&SHRx48aZ=&Z*u0oj<@G><`%D}T&(j3ID@IbiMP&p?%T{=Z+`Xm zEcp`&-=C@91Y4)|ZSrlYwN8ipZyo_W=|r}fCWhiAWqxraS*5Bso&$!~Ld z`*8=eht^?Co&Bj}#$x?d{6ot>sP(V=-Q9woPF#g7bc%jC`_=8>yCK!hpxiurxXbHAvTB4V{0DvgVw<&f2?cpSIKP&4tk7Hy<8^I+jD5JcNZXTdn=Qk9*riIof{wKR7AAz0I?t zEPUQv#ZA?}%SN>q^{X8Gn9@6kv!xlz&hRdRi~n)H}nb0%8SLzKg~;>wcA;o@1~^ ze|?zy4mUY-KDij?9IJJ5&nLOxfZSDb?JZ$ESIS+g}uNu$P>30KoX0E>&=xv|g`q~09FdDAMJ_fBR?)HS!>j39^zXPmS?|B!T d(bu!Pz-Oy*4rjg({66&fl1a_g{pCr|z(026LwNuI diff --git a/data/shaders/shadowmappingcascade/scene.frag b/data/shaders/shadowmappingcascade/scene.frag index 9ba3e9c5..470b5da6 100644 --- a/data/shaders/shadowmappingcascade/scene.frag +++ b/data/shaders/shadowmappingcascade/scene.frag @@ -2,20 +2,22 @@ #define SHADOW_MAP_CASCADE_COUNT 4 -layout (binding = 1) uniform sampler2DArray shadowMap; +layout (set = 0, binding = 1) uniform sampler2DArray shadowMap; +layout (set = 1, binding = 0) uniform sampler2D colorMap; layout (location = 0) in vec3 inNormal; layout (location = 1) in vec3 inColor; layout (location = 2) in vec3 inViewPos; layout (location = 3) in vec3 inPos; +layout (location = 4) in vec2 inUV; layout (constant_id = 0) const int enablePCF = 0; layout (location = 0) out vec4 outFragColor; -#define ambient 0.1 +#define ambient 0.3 -layout (binding = 2) uniform UBO { +layout (set = 0, binding = 2) uniform UBO { vec4 cascadeSplits; mat4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT]; mat4 inverseViewMat; @@ -69,6 +71,11 @@ float filterPCF(vec4 sc, uint cascadeIndex) void main() { + vec4 color = texture(colorMap, inUV); + if (color.a < 0.5) { + discard; + } + // Get cascade index for the current fragment's view position uint cascadeIndex = 0; for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) { @@ -91,10 +98,11 @@ void main() vec3 N = normalize(inNormal); vec3 L = normalize(-ubo.lightDir); vec3 H = normalize(L + inViewPos); - float diffuse = max(dot(N, L), 0.0); + float diffuse = max(dot(N, L), ambient); vec3 lightColor = vec3(1.0); - outFragColor.rgb = max(lightColor * (diffuse * inColor), vec3(0.0)); + outFragColor.rgb = max(lightColor * (diffuse * color.rgb), vec3(0.0)); outFragColor.rgb *= shadow; + outFragColor.a = color.a; // Color cascades (if enabled) if (ubo.colorCascades == 1) { diff --git a/data/shaders/shadowmappingcascade/scene.frag.spv b/data/shaders/shadowmappingcascade/scene.frag.spv index 20bef5b8855150f6a53039c6635936c1d246b15a..35124f216d74f744ff4cc0249864bf116da5880c 100644 GIT binary patch literal 8704 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 G!T$kz>k%&i diff --git a/data/shaders/shadowmappingcascade/scene.vert b/data/shaders/shadowmappingcascade/scene.vert index a75dfd89..4ef0b3a9 100644 --- a/data/shaders/shadowmappingcascade/scene.vert +++ b/data/shaders/shadowmappingcascade/scene.vert @@ -15,6 +15,12 @@ layout (location = 0) out vec3 outNormal; layout (location = 1) out vec3 outColor; layout (location = 2) out vec3 outViewPos; layout (location = 3) out vec3 outPos; +layout (location = 4) out vec2 outUV; + +layout(push_constant) uniform PushConsts { + vec4 position; + uint cascadeIndex; +} pushConsts; out gl_PerVertex { vec4 gl_Position; @@ -24,8 +30,10 @@ void main() { outColor = inColor; outNormal = inNormal; - outPos = inPos; - outViewPos = (ubo.view * vec4(inPos.xyz, 1.0)).xyz; - gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0); + outUV = inUV; + vec3 pos = inPos + pushConsts.position.xyz; + outPos = pos; + outViewPos = (ubo.view * vec4(pos.xyz, 1.0)).xyz; + gl_Position = ubo.projection * ubo.view * ubo.model * vec4(pos.xyz, 1.0); } diff --git a/data/shaders/shadowmappingcascade/scene.vert.spv b/data/shaders/shadowmappingcascade/scene.vert.spv index f7395d5d29e523a2d4842fedf224c3a7880eedf2..612e8feaacc91d283279c02ad4fd593b87764c29 100644 GIT binary patch literal 2400 zcmZ9N+fr0l5QdiwGoBI@PmmK15;dNXBuGez3ZeoA6)PpT7Q$3A7RmXkl#cK@mY$~ajHeOgluo8rzSlN?+?*W@_h#qs z%xN)}8re{rQ+zz5(7{f(Cx09|34I8SL1&VYSc~u~V%YS9}E0b6{;Jot2n-6Frcm5yfIzU=M{c6atV8@;{GZ`v7W zO8Z(I-)ujqD<{*&-XL#xJHJ*~BV7l3`QUlZEAM&RFWz)^%ginO#LfE)j_L!mzX!!$ zr|eB5-9$coUEtA5-@^a2|7xq#-|qB>Wu3lF+@mg@XOEnjXN|g@jqfq1vU5>3pR#jN z_9(jt%5ILb^H6r?%I=49#B&DWzfQH$?-_7UVA_kFhSrF#UDRN2>pAVMvify$MlYLL zE_(=@<9VASZ1|Dn9N}l)x?j|>T=Nrq-_P82KV|EG2Sq-y@bgX9AZDMO-zCTs@^mR? z|CpWg@aQk5|5?7hr@@?q`~|occN>}@zIm0^w~>!ky!cWjJNwX|fRA^oS2nj;*t-kb zhu&RKZ$9T{K5H@GIJdUq+AF&&k?$dp5txB1+=^L&58 z-G)3<$nK9eB|e%ygZI7S)}!nWiRpilyA2utMomTpAEno&tudn?SKy-`_Sd~sp2Yqd zx3<-fCF#63qK-|{;#)L({- ztDQN0hgjsi3NNP4`6`>=-rt6tk2BHUIm|)g;r}JP{x9%xK3_v(p1|he#jGu`I~8WF zTU1)kq4d{Yy|eyvn51V`N@4xpx znE0R6;ro{%{lvrX0la=IP{dw^7Z1OO@XL^R^zIRSy?2k1#XQlcHF&Xl@7619ggbh- i0k6OI>g&CGf^2?mtl8b)g#3N9A^WAQ-9Kbng#HEOq>ons literal 1920 zcmZ9L*-jKe6oyO28BtV3WO2g*6c-dx0a3*D0xpPP4BQ%&iD?7VW*F2U@fLZi4>*50qp?00u&=H_ShI2&q( zqdxs0&v9gLJ8P?-MEa03h}Lt+05XW&LY9#le?8p4Nm3^|jjzL)BR}ZA$#?S(YT;wf ztX)$2m>-|Fd1r5XxA3VK?`7@(R1xR<_-*9-WgctE+6Ba3FY3a+m9@TCKD986&*tlO zCeSE!VEEd}zqCGevz#s)#OdP=C;QvD*_nmlQjf z)ZcxH&9{ob{d(%iYSq7Z(tn(k{Z(LE90M>oImPq_6ppZzXz`(Cs^L$^+O^NZcF+yedU=PW$t`2*wkw+!o!P9yH; zIac>5j<$YuccaaniKFd2x_i;)zQnJ{>};+e&eNIc@9eK4@-g0T(D--6*iRFQztzZ% zSDd{>ZldDsYl9A)%Oui7^w;h#ev(()b;P&zS?BAu=NpK;;xWJZ?8R?Od+g;7y1lrg z*vmA!eDt}Cezf0vaPq&X!~SOw=wbkua7nREj~s3ew~N&66^PumllzKJbY(3 diff --git a/examples/shadowmappingcascade/shadowmappingcascade.cpp b/examples/shadowmappingcascade/shadowmappingcascade.cpp index da236042..be539ca0 100644 --- a/examples/shadowmappingcascade/shadowmappingcascade.cpp +++ b/examples/shadowmappingcascade/shadowmappingcascade.cpp @@ -21,6 +21,7 @@ #include #include "vulkanexamplebase.h" #include "VulkanBuffer.hpp" +#include "VulkanTexture.hpp" #include "VulkanModel.hpp" #define ENABLE_VALIDATION false @@ -28,7 +29,7 @@ #if defined(__ANDROID__) #define SHADOWMAP_DIM 1024 #else -#define SHADOWMAP_DIM 2048 +#define SHADOWMAP_DIM 4096 #endif #define SHADOW_MAP_CASCADE_COUNT 4 @@ -41,7 +42,7 @@ public: bool colorCascades = false; bool filterPCF = false; - float cascadeSplitLambda = 1.0f; + float cascadeSplitLambda = 0.95f; float zNear = 0.5f; float zFar = 48.0f; @@ -56,23 +57,27 @@ public: vks::VERTEX_COMPONENT_NORMAL, }); - std::vector scenes; - std::vector sceneNames; - int32_t sceneIndex = 0; + std::vector models; - struct { + struct Material { + vks::Texture2D texture; + VkDescriptorSet descriptorSet; + }; + std::vector materials; + + struct uniformBuffers { vks::Buffer VS; vks::Buffer FS; } uniformBuffers; - struct { + struct UBOVS { glm::mat4 projection; glm::mat4 view; glm::mat4 model; glm::vec3 lightDir; } uboVS; - struct { + struct UBOFS { float cascadeSplits[4]; glm::mat4 cascadeViewProjMat[4]; glm::mat4 inverseViewMat; @@ -81,15 +86,24 @@ public: int32_t colorCascades; } uboFS; - struct { + VkPipelineLayout pipelineLayout; + struct Pipelines { VkPipeline debugShadowMap; VkPipeline sceneShadow; VkPipeline sceneShadowPCF; } pipelines; - VkPipelineLayout pipelineLayout; + struct DescriptorSetLayouts { + VkDescriptorSetLayout base; + VkDescriptorSetLayout material; + } descriptorSetLayouts; VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; + + // For simplicity all pipelines use the same push constant block layout + struct PushConstBlock { + glm::vec4 position; + uint32_t cascadeIndex; + }; // Resources of the depth map generation pass struct DepthPass { @@ -139,15 +153,18 @@ public: VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) { title = "Cascaded shadow mapping"; - timerSpeed *= 0.05f; + timerSpeed *= 0.025f; camera.type = Camera::CameraType::firstperson; camera.movementSpeed = 2.5f; camera.setPerspective(45.0f, (float)width / (float)height, zNear, zFar); - camera.setPosition(glm::vec3(2.0f, 0.375f, -1.25f)); - camera.setRotation(glm::vec3(-19.0f, 42.0f, 0.0f)); + camera.setPosition(glm::vec3(0.0f, 0.62f, -2.4f)); + camera.setRotation(glm::vec3(0.0f, -13.0f, 0.0f)); + + camera.setPosition(glm::vec3(-0.12f, 1.14f, -2.25f)); + camera.setRotation(glm::vec3(-17.0f, 7.0f, 0.0f)); + settings.overlay = true; - timer = 0.317028880f; - paused = true; + timer = 0.2f; } ~VulkanExample() @@ -167,10 +184,14 @@ public: vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.base, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.material, nullptr); - for (auto scene : scenes) { - scene.destroy(); + for (auto model : models) { + model.destroy(); + } + for (auto material : materials) { + material.texture.destroy(); } depthPass.uniformBuffer.destroy(); @@ -183,6 +204,7 @@ public: virtual void getEnabledFeatures() { + enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; // Depth clamp to avoid near plane clipping enabledFeatures.depthClamp = deviceFeatures.depthClamp; } @@ -194,7 +216,7 @@ public: vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat); depthPass.commandBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); - // Create a semaphore used to synchronize offscreen rendering and usage + // Create a semaphore used to synchronize depth map generation and use VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &depthPass.semaphore)); @@ -328,6 +350,48 @@ public: VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &depth.sampler)); } + void renderScene(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VkDescriptorSet descriptorSet, uint32_t cascadeIndex = 0) { + const VkDeviceSize offsets[1] = { 0 }; + PushConstBlock pushConstBlock = { glm::vec4(0.0f), cascadeIndex }; + + std::array sets; + sets[0] = descriptorSet; + + // Floor + sets[1] = materials[0].descriptorSet; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL); + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[0].vertices.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, models[0].indices.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, models[0].indexCount, 1, 0, 0, 0); + + // Trees + const std::vector positions = { + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(1.25f, 0.25f, 1.25f), + glm::vec3(-1.25f, -0.2f, 1.25f), + glm::vec3(1.25f, 0.1f, -1.25f), + glm::vec3(-1.25f, -0.25f, -1.25f), + }; + + for (auto position : positions) { + pushConstBlock.position = glm::vec4(position, 0.0f); + vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); + + sets[1] = materials[1].descriptorSet; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[1].vertices.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, models[1].indices.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, models[1].indexCount, 1, 0, 0, 0); + + sets[1] = materials[2].descriptorSet; + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[2].vertices.buffer, offsets); + vkCmdBindIndexBuffer(commandBuffer, models[2].indices.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(commandBuffer, models[2].indexCount, 1, 0, 0, 0); + } + } + void buildOffscreenCommandBuffer() { VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); @@ -358,12 +422,9 @@ public: renderPassBeginInfo.framebuffer = cascades[i].frameBuffer; vkCmdBeginRenderPass(depthPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline); - vkCmdPushConstants(depthPass.commandBuffer, depthPass.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(uint32_t), &i); VkDeviceSize offsets[1] = { 0 }; vkCmdBindDescriptorSets(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipelineLayout, 0, 1, &cascades[i].descriptorSet, 0, NULL); - vkCmdBindVertexBuffers(depthPass.commandBuffer, 0, 1, &scenes[sceneIndex].vertices.buffer, offsets); - vkCmdBindIndexBuffer(depthPass.commandBuffer, scenes[sceneIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(depthPass.commandBuffer, scenes[sceneIndex].indexCount, 1, 0, 0, 0); + renderScene(depthPass.commandBuffer, depthPass.pipelineLayout, cascades[i].descriptorSet, i); vkCmdEndRenderPass(depthPass.commandBuffer); } @@ -407,16 +468,15 @@ public: if (displayDepthMap) { vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debugShadowMap); - vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uint32_t), &displayDepthMapCascadeIndex); + PushConstBlock pushConstBlock = {}; + pushConstBlock.cascadeIndex = displayDepthMapCascadeIndex; + vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); } // Render shadowed scene - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow); - vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &scenes[sceneIndex].vertices.buffer, offsets); - vkCmdBindIndexBuffer(drawCmdBuffers[i], scenes[sceneIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], scenes[sceneIndex].indexCount, 1, 0, 0, 0); + renderScene(drawCmdBuffers[i], pipelineLayout, descriptorSet); vkCmdEndRenderPass(drawCmdBuffers[i]); @@ -426,80 +486,65 @@ public: void loadAssets() { - scenes.resize(2); - scenes[0].loadFromFile(getAssetPath() + "models/trees.dae", vertexLayout, 1.0f, vulkanDevice, queue); - scenes[1].loadFromFile(getAssetPath() + "models/samplescene.dae", vertexLayout, 0.25f, vulkanDevice, queue); - sceneNames = { "Trees", "Teapots and pillars" }; + materials.resize(3); + materials[0].texture.loadFromFile(getAssetPath() + "textures/gridlines.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); + materials[1].texture.loadFromFile(getAssetPath() + "textures/oak_bark.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); + materials[2].texture.loadFromFile(getAssetPath() + "textures/oak_leafs.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue); + models.resize(3); + models[0].loadFromFile(getAssetPath() + "models/terrain_simple.dae", vertexLayout, 1.0f, vulkanDevice, queue); + models[1].loadFromFile(getAssetPath() + "models/oak_trunk.dae", vertexLayout, 2.0f, vulkanDevice, queue); + models[2].loadFromFile(getAssetPath() + "models/oak_leafs.dae", vertexLayout, 2.0f, vulkanDevice, queue); } - void setupDescriptorPool() + void setupLayoutsAndDescriptors() { + /* + Descriptor pool + */ std::vector poolSizes = { - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 12), + vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32), vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32) }; VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 3 + SHADOW_MAP_CASCADE_COUNT); + vks::initializers::descriptorPoolCreateInfo(static_cast(poolSizes.size()), poolSizes.data(), 4 + SHADOW_MAP_CASCADE_COUNT); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - void setupLayoutsAndDescriptors() - { /* - Layouts + Descriptor set layouts */ + // Shared matrices and samplers std::vector setLayoutBindings = { vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), - vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3), }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); - VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.base)); - // Shared pipeline layout - { - // Pass cascade index as push constant - VkPushConstantRange pushConstantRange = - vks::initializers::pushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(uint32_t), 0); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - // Offscreen pipeline layout - { - // Pass cascade matrix as push constant - VkPushConstantRange pushConstantRange = - vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &depthPass.pipelineLayout)); - } + // Material texture + setLayoutBindings = { + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0), + }; + descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.material)); /* - Dscriptor sets + Descriptor sets */ std::vector writeDescriptorSets; - VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); - - // Scene rendering / debug display - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - VkDescriptorImageInfo depthMapDescriptor = vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + VkDescriptorSetAllocateInfo allocInfo = + vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.base, 1); + + // Scene rendering / debug display + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); writeDescriptorSets = { vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor), @@ -507,7 +552,7 @@ public: }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); - // Per-cascade descriptor set + // Per-cascade descriptor sets // Each descriptor set represents a single layer of the array texture for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &cascades[i].descriptorSet)); @@ -518,6 +563,38 @@ public: }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); } + + // Per-material descriptor sets + allocInfo.pSetLayouts = &descriptorSetLayouts.material; + for (auto& material : materials) { + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.descriptorSet)); + VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &material.texture.descriptor); + vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr); + } + + /* + Pipeline layouts + */ + + // Shared pipeline layout (scene and depth map debug display) + { + VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0); + std::array setLayouts = { descriptorSetLayouts.base, descriptorSetLayouts.material }; + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + } + + // Depth pass pipeline layout + { + VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0); + std::array setLayouts = { descriptorSetLayouts.base, descriptorSetLayouts.material }; + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast(setLayouts.size())); + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &depthPass.pipelineLayout)); + } } void preparePipelines() @@ -597,7 +674,7 @@ public: /* Shadow mapped scene rendering */ - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizationState.cullMode = VK_CULL_MODE_NONE; shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); // Use specialization constants to select between horizontal and vertical blur @@ -605,9 +682,7 @@ public: VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t)); VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &enablePCF); shaderStages[1].pSpecializationInfo = &specializationInfo; - // No filtering VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadow)); - // PCF filtering enablePCF = 1; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadowPCF)); @@ -816,7 +891,6 @@ public: updateCascades(); prepareShadowMaps(); prepareUniformBuffers(); - setupDescriptorPool(); setupLayoutsAndDescriptors(); preparePipelines(); buildCommandBuffers(); @@ -845,10 +919,6 @@ public: virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) { if (overlay->header("Settings")) { - if (overlay->comboBox("Scenes", &sceneIndex, sceneNames)) { - buildCommandBuffers(); - buildOffscreenCommandBuffer(); - } if (overlay->sliderFloat("Split lambda", &cascadeSplitLambda, 0.1f, 1.0f)) { updateCascades(); updateUniformBuffers();