From bfdf821d3186ccb87937bae9cdfb129c070c00d4 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Mon, 15 Apr 2019 21:30:57 +0200 Subject: [PATCH] Much improved cube map visualization Now displays all six cube map faces as a single cross --- .../shaders/shadowmapomni/cubemapdisplay.frag | 47 ++++++++++++++++-- .../shadowmapomni/cubemapdisplay.frag.spv | Bin 936 -> 3744 bytes .../shaders/shadowmapomni/cubemapdisplay.vert | 13 ++--- .../shadowmapomni/cubemapdisplay.vert.spv | Bin 1300 -> 1528 bytes .../shadowmappingomni/shadowmappingomni.cpp | 17 ++++--- 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/data/shaders/shadowmapomni/cubemapdisplay.frag b/data/shaders/shadowmapomni/cubemapdisplay.frag index 43df99af..64b62d71 100644 --- a/data/shaders/shadowmapomni/cubemapdisplay.frag +++ b/data/shaders/shadowmapomni/cubemapdisplay.frag @@ -2,12 +2,53 @@ layout (binding = 1) uniform samplerCube shadowCubeMap; -layout (location = 0) in vec3 inUVW; +layout (location = 0) in vec2 inUV; layout (location = 0) out vec4 outFragColor; void main() { - float dist = length(texture(shadowCubeMap, inUVW).rgb) * 0.005; - outFragColor = vec4(vec3(dist), 1.0); + outFragColor.rgb = vec3(0.0, 0.0, 0.2); + + vec3 samplePos = vec3(0.0f); + + // Crude statement to visualize different cube map faces based on UV coordinates + int x = int(floor(inUV.x / 0.25f)); + int y = int(floor(inUV.y / (1.0 / 3.0))); + if (y == 1) { + vec2 uv = vec2(inUV.x * 4.0f, (inUV.y - 1.0/3.0) * 3.0); + uv = 2.0 * vec2(uv.x - float(x) * 1.0, uv.y) - 1.0; + switch (x) { + case 0: // NEGATIVE_X + samplePos = vec3(-1.0f, uv.y, uv.x); + break; + case 1: // POSITIVE_Z + samplePos = vec3(uv.x, uv.y, 1.0f); + break; + case 2: // POSITIVE_X + samplePos = vec3(1.0, uv.y, -uv.x); + break; + case 3: // NEGATIVE_Z + samplePos = vec3(-uv.x, uv.y, -1.0f); + break; + } + } else { + if (x == 1) { + vec2 uv = vec2((inUV.x - 0.25) * 4.0, (inUV.y - float(y) / 3.0) * 3.0); + uv = 2.0 * uv - 1.0; + switch (y) { + case 0: // NEGATIVE_Y + samplePos = vec3(uv.x, -1.0f, uv.y); + break; + case 2: // POSITIVE_Y + samplePos = vec3(uv.x, 1.0f, -uv.y); + break; + } + } + } + + if ((samplePos.x != 0.0f) && (samplePos.y != 0.0f)) { + float dist = length(texture(shadowCubeMap, samplePos).xyz) * 0.005; + outFragColor = vec4(vec3(dist), 1.0); + } } \ No newline at end of file diff --git a/data/shaders/shadowmapomni/cubemapdisplay.frag.spv b/data/shaders/shadowmapomni/cubemapdisplay.frag.spv index 44a0198c093759a8bc5c89118a6ee8ecbb555acf..f3843f2fc57e0a4bb78edd75fa6e202385305cc5 100644 GIT binary patch literal 3744 zcmZ9OS96tB6oxlxKtLeU#S(&I0l@+Y0wE*{mS7SQtfK}&hyyuD5{iu|qNpR58GDO> zE!Z!-b;fJG_Ln#o#u=aIJ9|0boIUfN^{#iXz1Q09OX}+uO-yM*nwTb~A5*opq&k$8 zrlh9AZtmXNy=-WB=du+muQ6g;sxJbKna;=ttk~B-FlfhQFb~WiPMrj>dS*@O7X~$= zmg5`A8{^nvFeN@P;DKz~Hv+xJ1{d zHtdniuf>iWtm;l!v|U!D^CTV18+iW1#^jaU-aFJR(>a8-C6au*|!EYo38V zPXV^@r^0{xwYz;Oy~dvhj1l&kX9m_B_D9_L@QBmSCT=FS6-+2>Lz;zkoVxYQ!CHgs zbl$mGW7Vx+-#t@vzWLZzV6$HR3kt6~egWKA=Zy7K_j|NG;uqzZ=wFO~c6_|(x2`3* ze->3Og;f^oY)mik9Ziw-HRsZMt+?r2w ztmjm2uFbZ96Fh}A&iPL(($w5HeeaSj<{yVQ|9*PyDsHU%?VYii<1ds(tYbY}-;DL@ zduG0uvfozn-5cLY^y~Xp!guXs*eGPtvWH*&=~?rxS(mlASJu|fud&9+tyQeOU|4<^5;}YUMNBkoDM)4t&p}lFxV}TrKi;!PPoJ)OQoyd8&QYTsPyJt9*u= z@YSQ<&2Y!6pUi8x1+MP9j<{Rl=8K%J^)_IveX&-xSjX*f*WnrVVr}R6a;k^l4fnom z0d?RGP!D>5=WBoL-JS5-^=w5`kC?l1OnHB|p{e)s8k(`&K_76eeb(NBRsWlu)@E*N zih1vWo4Y*kz4+=8b6<`r@Av&^>XG{axZ~8_%gC)>&h0+Lybr=_*ZmNhdc-`OW6JgQ zqp2Uw_h<)PEoylLZVk?5U(}*ruEn#6JiFkv`|v25dgR#+SBo)w;I;J+ps7bKkHHQtqjlSOm&&cmU+_yov_bt976}Vb_M;?dU{EpbSAE-Hx+Xx7$YV~%Ix-VNoOnGl#MpKV_^$Of^-YNUyUa5PJ zti{~c5c9qYug!fDO+8{>%Q5BLucN8QJ9q=G7PY(ycb-mQU(}*ruEm=4<8ErpcYZm3 z)bSR)1(f&cZG82gI4l32z5~>z0MFw+tj%{|-@8D~eUQi8@57zDyv7gk)no1t;cCup zjWLh*56;{C9|7}NxAEq%j!&>Q>oDeHpk^I%@6svkXW&fso3Wn*>$;ouO~ifyj8X65 zzZ_$}1nR;z0eIKq|CFz?=2;jUZ|E%CzH#9BjA7NRr3w2r7z1&p-(*c)^ih*>-vaw= pp?wEevzE}l&ziOMvKrU(18}_Y_FJR1Ovc*hKF2<3|7FJ2;6KFlA3^{C literal 936 zcmY+C-A)rx6ot2KDTP)F7SV#@0GB3BW005-HI~HQ)KDWvowTPXjGmW?2@Fctm zFTtyLW8(TwXN>M7cd$x{YGR zie8AOZi`k@#J{`In2S|;)5oIc)j%0VRW-X)QpuLA+Y3LOcETi@xT#B{F!|~R(KL)N zuA<8{`Cp@}(RdhMyYX=5hEcfxsy%U+-)upZ{_P8{sK;QGqzbw(TTPML@sFd~MfAx{ zJYVuNj>cck&NChJ#v$??UDYFh7a+?q@5Jt4cHNd^VCv+!p^e#j$8T@` zyrFYhT;RQ=*E8>MO})#KBIo%F>yR1!ur1vzE20b3uL>!HJIpXMV^4%v6!UuM>%!E6 zM-OHPIP{Mc(eth^_04%hzI=asNd8lunGGHJV0MPf_0M!R`}zJrzX1DF3q$iu%z`4h z?9T5+d@IZj59Q1cX2vx+^PMY;o((w~_+w?GS(n4(7`xE7rskH9mE92ntldR73>`vh?$A17lv*fxL8OLmWZOuM`oP6}$^LEU_ Mn+EdVs_;hs2M#qr^8f$< diff --git a/data/shaders/shadowmapomni/cubemapdisplay.vert b/data/shaders/shadowmapomni/cubemapdisplay.vert index 7e8b141e..1c39776d 100644 --- a/data/shaders/shadowmapomni/cubemapdisplay.vert +++ b/data/shaders/shadowmapomni/cubemapdisplay.vert @@ -1,7 +1,5 @@ #version 450 -layout (location = 0) in vec3 inPos; - layout (binding = 0) uniform UBO { mat4 projection; @@ -9,16 +7,11 @@ layout (binding = 0) uniform UBO mat4 model; } ubo; -layout (location = 0) out vec3 outUVW; - -out gl_PerVertex -{ - vec4 gl_Position; -}; +layout (location = 0) out vec2 outUV; void main() { - outUVW = inPos; - gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); + outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outUV.xy * 2.0f - 1.0f, 0.0f, 1.0f); } diff --git a/data/shaders/shadowmapomni/cubemapdisplay.vert.spv b/data/shaders/shadowmapomni/cubemapdisplay.vert.spv index 2fabb1fe0e0dac0e7d6214fabd8b353ba033d092..1b4984facd879a8fc9a5dad5203b6690f77a57c1 100644 GIT binary patch literal 1528 zcmZ9LTWb?h6opTdCQ+-cwf3UcIBC4L8hua^M6DM{3k4&keU;h_GBVASWTM5Vg75w) z5&TQO2(ItU*)jHn&E9M6>)B^gE;Vb;O}Lsn-N_6R%?)VTMr*S zAY$5;eIPM2%HvE*4)&5B_G!sk$yG^NzmoJ11y>X`9tS2i8|FK^(iQb1?_>IYH}2>0 z(Ppn39~JzSg73ur!X>Eas)Oe!r;`nmJjr@uYo2F5&nLZnJNX(DXFg_M&ag#&qzm-39lzdJBKHp-STGm*FyaC z3C!N;NB>1>`tu&tUy_a_9P+`JB-C3LzAQ~VTwNCLXEpF4++$gqnej6hxcEQ*o6Ej4 z`q)kswr+Suz`5fWhHrRW)W0K}`t)8>{#vlPM?HKya3;)jPndi2e#`{s{oo!e2TeYQ z+P}r{Z9Egpe$PqR?N71bnZU8%UxAwqJUh;m$Gt8{;H}P_Z0cCfMcHuUIrGBs9o6Mq zSddT${<)^(n}DMx{%aDr?;*YsxJcS+G-b0>|cPN z#INE7iSyYWDR867opa{Qa<6Z*(K~N;PQMHG$f~t$4PmoIYnOX}@L{l>7o+Xnr#mRF zTC)_QSyCQrL3SF(3I0XdqU@Tisb53;FNqfv=?{Xv_xnK}O~WiKq9Feij-o6`k3UBz zMgFfwp*R@_lQ0?2!f_PrKG~UuCts|kO7s1|^h{^P;n7Dcpo&>`v zJBqR*`YtH8;_->4d0fP4B7L)*9UlLN_QUL(%~B>tF1}T2xR0-K^o_W4oc%N% zMHB7RTGKu|POV?hyeZ5AGqd9ZshODt&+025j+zJ3`z);zS2M`99)DWYaE(54c_znevAhQB7St-T{# zS3Y&Y#5=;gK79BWHRdgN{E~b>2XQd>2}ivv+NsBT+Ef^1ra z@|c;v&-A6JLw^?hZ!vtomtwiI%QEicm7?4mcuxxYZpfI0GofdOn=*LU+?J1qnOt*6 zKKxJBA?L1)Jb3TRJE!kEY5e>8+jp+3I2`xu+*ZwTuAxrAIeW5>3_Wq~@JyDy_Z W8fNBx9?JNRoQrdV(fv`U=d!<=JX2Tz diff --git a/examples/shadowmappingomni/shadowmappingomni.cpp b/examples/shadowmappingomni/shadowmappingomni.cpp index eebf26d7..5418f67a 100644 --- a/examples/shadowmappingomni/shadowmappingomni.cpp +++ b/examples/shadowmappingomni/shadowmappingomni.cpp @@ -78,7 +78,7 @@ public: struct { VkPipeline scene; VkPipeline offscreen; - VkPipeline cubeMap; + VkPipeline cubemapDisplay; } pipelines; struct { @@ -154,7 +154,7 @@ public: // Pipelibes vkDestroyPipeline(device, pipelines.scene, nullptr); vkDestroyPipeline(device, pipelines.offscreen, nullptr); - vkDestroyPipeline(device, pipelines.cubeMap, nullptr); + vkDestroyPipeline(device, pipelines.cubemapDisplay, nullptr); vkDestroyPipelineLayout(device, pipelineLayouts.scene, nullptr); vkDestroyPipelineLayout(device, pipelineLayouts.offscreen, nullptr); @@ -552,10 +552,12 @@ public: if (displayCubeMap) { - vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.cubeMap); + // Display all six sides of the shadow cube map + // Note: Visualization of the different faces is done in the fragment shader, see cubemapdisplay.frag + vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.cubemapDisplay); vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.skybox.vertices.buffer, offsets); vkCmdBindIndexBuffer(drawCmdBuffers[i], models.skybox.indices.buffer, 0, VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(drawCmdBuffers[i], models.skybox.indexCount, 1, 0, 0, 0); + vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0); } else { @@ -752,15 +754,16 @@ public: // Cube map display pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmapomni/cubemapdisplay.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmapomni/cubemapdisplay.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; - VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.cubeMap)); + VkPipelineVertexInputStateCreateInfo emptyInputState = vks::initializers::pipelineVertexInputStateCreateInfo(); + pipelineCreateInfo.pVertexInputState = &emptyInputState; + VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.cubemapDisplay)); // Offscreen pipeline shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmapomni/offscreen.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmapomni/offscreen.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; pipelineCreateInfo.layout = pipelineLayouts.offscreen; pipelineCreateInfo.renderPass = offscreenPass.renderPass; + pipelineCreateInfo.pVertexInputState = &vertexInputState; VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.offscreen)); }