From b672bee4e5e1c5ca5ac3b734a2dda31f332d165d Mon Sep 17 00:00:00 2001 From: saschawillems Date: Fri, 21 Apr 2017 18:59:45 +0200 Subject: [PATCH] Updated env map prefiltering shader (requires less samples) --- data/shaders/pbribl/prefilterenvmap.frag | 25 +++++++++++++++---- data/shaders/pbribl/prefilterenvmap.frag.spv | Bin 6952 -> 9020 bytes pbribl/pbribl.cpp | 6 ++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/data/shaders/pbribl/prefilterenvmap.frag b/data/shaders/pbribl/prefilterenvmap.frag index dada35f0..ae1212ed 100644 --- a/data/shaders/pbribl/prefilterenvmap.frag +++ b/data/shaders/pbribl/prefilterenvmap.frag @@ -8,7 +8,7 @@ layout (binding = 0) uniform samplerCube samplerEnv; layout(push_constant) uniform PushConsts { layout (offset = 64) float roughness; layout (offset = 68) uint numSamples; -} pushConsts; +} consts; const float PI = 3.1415926536; @@ -69,14 +69,29 @@ vec3 prefilterEnvMap(vec3 R, float roughness) vec3 V = R; vec3 color = vec3(0.0); float totalWeight = 0.0; - for(uint i = 0u; i < pushConsts.numSamples; i++) { - vec2 Xi = hammersley2d(i, pushConsts.numSamples); + 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) { - color += texture(samplerEnv, L).rgb * dotNL; + // 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); @@ -86,5 +101,5 @@ vec3 prefilterEnvMap(vec3 R, float roughness) void main() { vec3 N = normalize(inPos); - outColor = vec4(prefilterEnvMap(N, pushConsts.roughness), 1.0); + outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0); } diff --git a/data/shaders/pbribl/prefilterenvmap.frag.spv b/data/shaders/pbribl/prefilterenvmap.frag.spv index 0cdcde25ed2169640bfc86c40be3e6ffdca67e4a..269e5d554dccfb65521b8bc7de7eaf662f9a6fe6 100644 GIT binary patch literal 9020 zcmZXY2b5LS6^1X&P?W9|5rF|zuz`RmNR*)tD#8F#><%+;n9-Se;}p!b~h(`KVoBzvRP7me?e>;rD9 zYi%ubbhZ>OoYpX@d+Kcd(zwC+nlbwfpzVl5-V9mVeTO>KqF&eUI->`&WP>}aiPF{XD?1z(URBN2a4 z^vYxmZ9}nZ>Ee|4O2*RenX7Md5L$ajp|QE8tI)BqZNtfR?UXbzYjqt1BeXd7*PvGbIsLYLvGb|Y>_~a9x)>Q^*8@Ocxf+ICWFAc=e;r+vInn7 zhQUkoTbT^s!&jN?SH}0>gI6S@;Y+B;8YY6>x51Chc;uc@;;UmVkA=54G^TxLi+Amf z%H+5*z8GF?Ev&CwSsH6u@LGAVWDUHvxqV4tL!rfaa}F*>E3IQ?dY&}5)fU~f#(TCD zySwIR%ZXB%T#lBnVQY@p;CCIzo1827xDsXlO6w@~*{jAvBTcF;psk@U*Vc2)9G-JN z?_P523cfE<#*L$or=@tf{b{SP5yX2g%Jo&j`_iguQ^5IA3$4$c^N;D)>!p% z+{2)Zt82y#%{22k<}g~ZHR&HtYYz2sct&K{G3~40+@opjr>3cmr?sCkYKM`}m`T{I zCzs6)ekgp&#+&8^KODa8g+ptC&wxMl`r>N2_fm~{rUzdHUd0uBF}z34e-ii>uJE(1 zlIdK*SHPX);H$tpxq_btAH)^>47l&7;Aewh;tJjX|A2qN8{y7ZaL)z<nBsrW>U6(sC zHO(BM-<9$3Mc!x8pB{8Vb;P{{j~LsL?8sMXy(jli{&GFMM&Wsl);Raq>xx`zvor3q z=;fY%i?#~0zjesp#=P9G@6xKdeq-Q1e~#}yF@GO;`kc_3U+#IT7Wwvq^OqREcjmKy z-1iurY`fs|QoeZ?Uj!d<_pfG#zZT9s?b_eV)A$E=#h;b(WRCTp3$|YOljC0k*X{aP zuiSG)P5%~vb8A2Sa?h1`UathF_e;#tJcG`QxxI{e3#AvWeSI!HM}5A7drk)Tnf08M zA4j}3ZGu}*|7;I!2J@FJ%zVc)iaFJz&lO-bedd?Xr3!1k3UfVNQ{$bBt25nr$CuB_ z#=8dW?<4c*TTUMPTnpCc720)~rX1R~OmkjpxijZ+J7$05_4_P1w)3j*J??NO=6pJq zzeT;A=VOTT+4i@nbK9TRxpeL(V)?l|q>TG}Ebl*}j8D(FwV2CuQ*0j3OtCpUFP%Gc zO~$Mx=5h+yzQK&e%#F*Cf8PykYv%ucZ)-3O_U}M#zuRo;i>pkj!pE*~H_3@te!MuFmxjw$@ z2Iue)uxqt1t!t&<-@W#YwQJ3|wG9Bz!OZb6waMpZS~YFN%mW+qU=}kUtX7RZl4%RT z_SNTHIj&md@HtX@G>fkRt1ZG}>=VH1zUQLfiQs&{C2+Nqu&C!`u)6)Co~2;(>5F>Q zBJZ+P-(AmgxLPe1^{fP|`yP#cr-1YItcI(t!lIrvV0HUNJ!`?{(--xqMcz|WeRn;l z!_|C8M?GhP)qPJ#zq7#kdd`8X`RcHn<_KSMffz78c>QRfl^{KwQo&sF00gHOp zgVh_c=+^|!*K;mhtr?4Y&I7C4FY0Lln@?ZVqZWDFQr+JarL(jMSKG>d^4U8dQ)|cU z-@`KY@E8!uRNaLVc=1i z*9a`m*Znd)ly+o>htuwl`79qm8_(`V;66FNDaZSQx8}I{ww3W4bKEg@l<`~3_}yjv zzKqBHUktbA;Fn}P*5p#SG3u^~^{e@gw7$zQ?|%yxIWEui$Z-XHGp25g^LQoZ{48TO zoR6zAP2H;}=6KGBzFFBCUJdStsYm{6!RpswTe7(8z>cfWJkGOP)O|hJx))cpk#`+>S#?tRt z?o;*1{Uxwk@Gpa1lgRNEusH@|`l5!fg6*q6`hE?Z&-Hb9KG!$k<{E(Mi(EH@?W;d> z-2!$FYB>$um*2!3(^!4p%MM!gSi5h5-McHW$n$Nmdfd-AQzLbvx~MF@3jT zH)mshFVpX&y$f?ppJR3NTh~39TJZ0Kt)V|pkN$fx$6J6ItKVAm{Q%Rq5HrsFo(t-c z?}uRX1-~C`OyvI&IPx2-Kk`42`OI&e`R}8B0E>J-2AePD@ImknYzt;gZ`y}2_3N1{ z>wXxspL*nZ1Z?ie^AoUn^3U<3aP`RZQ?UKieU8li7-oKbk^5(0=OA+b9Bl6VI`4$5 zNAAbL_EV4CzW|$GU(C@j!96hNNWbqEwRpF9|5cdRXv}wu=j)gp9t-w;GLAOhCr^O; zXJNXkmG&9ez%SM`u%pB=YG2l?)ZMY4Q_wG-v)PlzuyKo z-tV`0?)Tf^#!oEce#6cC{f3+8e#6akzvJe)-*NMNaT)hJZr<;A+&o{Kao627`w!+C zxsO~6dH7z)`CJ#dajwZr8FoGH!0huH?VH#eSOff3+IKQ-J$v_E@P9MyZCbw%yhZz7 zrql2{xpZc}pXrY08q3A5?-uNB_K^pV`^okV`t_u(z`XQVW`0}i8-U&mY!1)Dy}|u3 zzlHccDq{L)`fbGcZW{o%pZYuIq3wY=p5u$7?_jX`t<}9IkFoXvmyfkCn!54sMY-Qy zT(hD2Xw9R~827Wf;~6sotftSsD%a;ZF%s-Er_X&W*XO#A0=wS&+{5x&WYl+noYs8y z({G&5hQ7!#7VN$VUIjNMzG;jD8>1d)&v>xk_Vh)+31IuhyXQc#nz0dc5ZJLiE3NTh zxN+*%=5wbO@sq&bU+_cV#zbw0f{jt{&(|d9>o72X>Gu%*?(6NC`F)P{o6p$8!D{zr zd*lePntk3RehS#j{i1I&rsjSTM_p6F`8ub;^K&>IZj5@=c@&txv`+o`Iz3{M6JUI5B=a$^P?flIFSJB!> zU-YR4n=kguT(Gg~5i=ib9TBqtJP%Wkchy3$ef7nAvj(ib2(w<#TD5pSPXL!cpC_WJ z$N#-g0;@$WOTgxdT22NVqaL*^1-p;*IqqUwwaBpo>=_q1R>GHK>Jf8FSXt46v7bR^RE^nV5T4Y|gc`#(TaRug{nm<7}|^ z7yKNsbwrJIU}Mzd{}k)M{H4F2^v68ZgU`bB#~L<()tyg&!@HLXaQ@P7wfe0uYSovo z)taNWMzHr|>>66RKHp>O!M?}jo;OYK(V5>do5A*3OAY7Jo`>1TINnI9e;MbBeOofW zF;XN6R|k|+Q9ZvkMWCO-@DF(IosiC##+BVwa9rs*qp&Tz`m0{foZOg-{$xY}Nr`ShvT-y1exPujSj4Pa}I`ZmI?A^yL5 W0bDK2{o{RKh-P2?{sxu%8}xtp_Bq4= literal 6952 zcmZ9Q37l4C6~-@oGeEK_vIr#1hzf2fpcYNYAn0I%j3T0K`oRp$luLEt-`XYGyykT(X5sE6qwX%iVJM|L^ynx_oyyzxR2bbKdiwce{6n($E>h zvup@IBeJrspG^(Z6p^_6?tD&4a-uAAG0Qp$EgTU#-Hcs35)QSR<; z@9XbsKXY!|tPOLT_?O4+imwy1&u+BG<#=Q^RlU2n(l=1@mZBM1IyWC~Wh^ztL+tcy=m7Zyf5wAglEyV4OHu!4en=k zUAy_R3R)?<9BpatFJ)V3H}qCxZveBj>)U$wXm+X2-*DP?zqPr{tX zJ+x~pU6sC^*Jt<94paupU8~zW*LMsMQ_Ai~tL|-mwgcR{p}%8srKjK7593G8r?|eM z4?*wQ&|Tel;+^w@XuX9Tj`0Xub?@u4NA>@2jq0+;cH*V%ad>qt>ar(x^3`Qe*6^ox z;-&0q_%h77zf9X!891)W>$BHUY=3@2Jx#`xvT115b*szoRA*0Xg=ysT@P1V`3@lE| zm*?CUtyuf40$)l*tkn#1G-II=mZ>elS{Tg;?*_TP2KWeCHLcO{Y4xj5fRCnazSw0n#Z-9|GrgU^It z^yL06!F`F|_UzJTxpg;TzQckq0Nl;?K$b)&9m` zfNkHlZ9&9u&i#W6gI^6l8B}k=FZUgy=6U=BZ37njBY!Ay&(_0WW6c+JKLh4zo{VQ09UafJ zSbWUqGZoKpV=(iLNDejYk$XpdJlmtd=5s%dpAOgU`WP>7NSgi`V8^zfez|v8&3c{B zK5!r7_XEeBjQPw#+cEZ-=EJ!oo;%0(F~p-uO=Qt_Am<72G@JJ4?QR`20S? zt#?$~~aMeAC+c6(vPwcNXg?_0xX)$rMgTZ_47V0m4%zSG3!n2EV|j%ifcTiu%9SU|nn^NAxz{aXa-^0Q7b&mR9Va?TIf1J}e%*St!`!j~t_jzD{Cv~rO zr**IN`#YR{WA8c=w>IAuZ^F!RJGIH*oHV}`5wien%+?fhMD8G=F=DTs72nlfQxyT z!PSn%qMqZx>dUd{w*p-3cRXCJ6^nXK0ISRAakpT4L^E%KfSF6KQ6uC@w`di>>A z-S24hI|W?q_cpki-`1$-?O=8LMLq8Tn@?ZVqZWDJ2`=V64X)-lI_g;iJ`F2l(Qhrd z*smR~)`mqr>%i*vi+a|B&8IKwQH#8tVDt8JZimsn3sc*~d6IV}?Q~lEd(PFOe>d1O z9Q}L1YT>Vdy+7ga1*>gN`QHt;kGg#vvk!Bec<1zkjZ^pj%H#g}jhTx1_S%Evohalm<08hb|W0B`duzJkrDzG)wVft?3OkG3!O-$d_*p+F_ZzcUY z+UqgL+(N5ve(U-+rWX7=U~3q~?a}{T%<-0B#_G2gec!|M9fcWZe%}k~k?$t3`GS8R zY)s_8865eI)gSqPkbLGh&ipshsz<&bg3T9e_#?3ET6}NZ0$0C;wX*IXWA;;zJhy_) z9eI8NHc#;$Z-uKzp4-5;V(Q)_bKj1cUti?D1MC_^?w^9qUEJq8;p&n5XJGrONAA18 z=GPZ%^mB0RfquU&YQ=9$1Kej%%%fuBGjBtmUt1e}nnx|1GV4TgMws`#a1Wo{xuV z|A;+^J%mNfpOSuky6=C6+fV%^^2i^+9MAmX==&G2`JIF7E|0PP3a%aNZ)obqyDxJ8 z7WF**9UF(4N1rk7t-9kG^AAi-pZg})H;ne5nCDHOdnniE-T4>hUg&c_<@3{f=-=R} znEC9d-#E{SzR2+`*gXsW9N3unJMVe0G3xRDegXUprZ4)v2)19`$Ctor#zxG4z>eiN z%=-U}8K-V-o2pozp!1eA!z)||5g=v<~C#I_e|?IpRq&1 zYB#4dQi7}5=Xv7m!9JcBeRY_c=S6HD|4(NZ%>U1cI!A)7b2WMWzk|`3G3qO*)47jH zx;`J9p;**57QxzLJ$HrMM?J>b4eT9@_uV+Snz7DTpIYSH9c<3vAK9~DGe+>bXlK=n! diff --git a/pbribl/pbribl.cpp b/pbribl/pbribl.cpp index 0bf5ef39..8f37014f 100644 --- a/pbribl/pbribl.cpp +++ b/pbribl/pbribl.cpp @@ -260,8 +260,6 @@ public: models.objects.push_back(model); } textures.environmentCube.loadFromFile(ASSET_PATH "textures/hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); - // Irradiance map generated offline with https://github.com/dariomanesku/cmft - // textures.irradianceCube.loadFromFile(ASSET_PATH "textures/hdr/pisa_cube_irradiance.ktx", VK_FORMAT_R16G16B16A16_SFLOAT, vulkanDevice, queue); } void setupDescriptors() @@ -1199,7 +1197,7 @@ public: struct PushBlock { glm::mat4 mvp; float roughness; - uint32_t numSamples = 1024u; + uint32_t numSamples = 32u; } pushBlock; VkPipelineLayout pipelinelayout; @@ -1439,7 +1437,7 @@ public: // 3D object uboMatrices.projection = camera.matrices.perspective; uboMatrices.view = camera.matrices.view; - uboMatrices.model = glm::rotate(glm::mat4(), glm::radians(-90.0f + (models.objectIndex == 1 ? 45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f)); + uboMatrices.model = glm::rotate(glm::mat4(), glm::radians(90.0f + (models.objectIndex == 1 ? -45.0f : 0.0f)), glm::vec3(0.0f, 1.0f, 0.0f)); uboMatrices.camPos = camera.position * -1.0f; memcpy(uniformBuffers.object.mapped, &uboMatrices, sizeof(uboMatrices));