Updated env map prefiltering shader (requires less samples)

This commit is contained in:
saschawillems 2017-04-21 18:59:45 +02:00
parent 486a6a94c0
commit b672bee4e5
3 changed files with 22 additions and 9 deletions

View file

@ -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);
}