From 46536765227211ab036d76e099ed9535860f0ffc Mon Sep 17 00:00:00 2001 From: saschawillems Date: Tue, 18 Apr 2017 21:59:32 +0200 Subject: [PATCH] Added shaders for PBR IBL pre-filtered environment map generation [skip ci] --- data/shaders/pbribl/filtercube.vert | 19 ++++ data/shaders/pbribl/filtercube.vert.spv | Bin 0 -> 972 bytes data/shaders/pbribl/prefilterenvmap.frag | 90 +++++++++++++++++++ data/shaders/pbribl/prefilterenvmap.frag.spv | Bin 0 -> 6952 bytes 4 files changed, 109 insertions(+) create mode 100644 data/shaders/pbribl/filtercube.vert create mode 100644 data/shaders/pbribl/filtercube.vert.spv create mode 100644 data/shaders/pbribl/prefilterenvmap.frag create mode 100644 data/shaders/pbribl/prefilterenvmap.frag.spv diff --git a/data/shaders/pbribl/filtercube.vert b/data/shaders/pbribl/filtercube.vert new file mode 100644 index 00000000..1226e28e --- /dev/null +++ b/data/shaders/pbribl/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/data/shaders/pbribl/filtercube.vert.spv b/data/shaders/pbribl/filtercube.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..d858d61a30f4fb720e1050ee69f9716ec173a890 GIT binary patch literal 972 zcmYk4$w~uJ5JjJfiSrQW*{DlFT&M`5A}->>MMTu42nG$9w4_^c=`Z+8ew7=+bGp-# z*Ho(N)^uOJ6boAeA@uPLhOLmDN+{rmFcQkCu3cVV?!?LC&ffm68RMatCYm!rou?mZ zJv7_eL&yj+i4^$?=x>rsWcB9hn;X3)H@A0L+`4AF9>wSq^T*LoFZcCE=eE&F8Xvfz z8Ln+CiknF@YLj0~XNs5jX3+Jw`1w3)#|aI~%oFpp-e1$4IqcV-oLZODTACGtzMOLZ zf+{(A#630Uih0kAo*AXo&v;<|@7EqV50;;DwuhKKrukKGfVpYyIjl0eip(>^I(_3+ zd|yFZ{HW`@+dMvu?R({Meff*oZwzfe-)D^~?;~dK3ABC0?5&@@Z3wgY75pk^+N?r*s-Ia4Z;y)n1 z!!f9LA4R> 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; + for(uint i = 0u; i < pushConsts.numSamples; i++) { + vec2 Xi = hammersley2d(i, pushConsts.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; + totalWeight += dotNL; + } + } + return (color / totalWeight); +} + + +void main() +{ + vec3 N = normalize(inPos); + outColor = vec4(prefilterEnvMap(N, pushConsts.roughness), 1.0); +} diff --git a/data/shaders/pbribl/prefilterenvmap.frag.spv b/data/shaders/pbribl/prefilterenvmap.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..0cdcde25ed2169640bfc86c40be3e6ffdca67e4a GIT binary patch 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! literal 0 HcmV?d00001