diff options
author | clayjohn <claynjohn@gmail.com> | 2019-11-16 16:56:34 -0800 |
---|---|---|
committer | clayjohn <claynjohn@gmail.com> | 2019-11-19 22:30:48 -0800 |
commit | cd40154890ba9791b219d66beaf187a7d8dcdba5 (patch) | |
tree | 5a2581d00361b4a1b2e14f96e263a8333e392e7c /drivers/gles3/shaders | |
parent | da4079f231acf9aeee3487e831fbf8cb3bceb6ed (diff) |
Fix issues with environment mapping
Diffstat (limited to 'drivers/gles3/shaders')
-rw-r--r-- | drivers/gles3/shaders/cubemap_filter.glsl | 119 | ||||
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 29 |
2 files changed, 126 insertions, 22 deletions
diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 619e29b130..d83a109cb9 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -30,12 +30,22 @@ uniform sampler2DArray source_dual_paraboloid_array; //texunit:0 uniform int source_array_index; #endif -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) +#ifdef USE_SOURCE_DUAL_PARABOLOID +uniform sampler2D source_dual_paraboloid; //texunit:0 +#endif + +#if defined(USE_SOURCE_DUAL_PARABOLOID) || defined(COMPUTE_IRRADIANCE) +uniform int source_mip_level; +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) uniform samplerCube source_cube; //texunit:0 #endif uniform int face_id; uniform float roughness; +uniform float source_resolution; + in highp vec2 uv_interp; layout(location = 0) out vec4 frag_color; @@ -133,6 +143,19 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { return TangentX * H.x + TangentY * H.y + N * H.z; } +float DistributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = M_PI * denom * denom; + + return nom / denom; +} + // http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html float GGX(float NdotV, float a) { float k = a / 2.0; @@ -160,10 +183,12 @@ vec2 Hammersley(uint i, uint N) { #ifdef LOW_QUALITY #define SAMPLE_COUNT 64u +#define SAMPLE_DELTA 0.05 #else -#define SAMPLE_COUNT 1024u +#define SAMPLE_COUNT 512u +#define SAMPLE_DELTA 0.01 #endif @@ -171,7 +196,7 @@ uniform bool z_flip; #ifdef USE_SOURCE_PANORAMA -vec4 texturePanorama(vec3 normal, sampler2D pano) { +vec4 texturePanorama(vec3 normal, sampler2D pano, float mipLevel) { vec2 st = vec2( atan(normal.x, normal.z), @@ -182,7 +207,7 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) { st /= vec2(M_PI * 2.0, M_PI); - return textureLod(pano, st, 0.0); + return textureLod(pano, st, mipLevel); } #endif @@ -202,6 +227,20 @@ vec4 textureDualParaboloidArray(vec3 normal) { #endif +#ifdef USE_SOURCE_DUAL_PARABOLOID +vec4 textureDualParaboloid(vec3 normal) { + + vec3 norm = normalize(normal); + norm.xy /= 1.0 + abs(norm.z); + norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); + if (norm.z < 0.0) { + norm.y = 0.5 - norm.y + 0.5; + } + return textureLod(source_dual_paraboloid, norm.xy, float(source_mip_level)); +} + +#endif + void main() { #ifdef USE_DUAL_PARABOLOID @@ -225,7 +264,7 @@ void main() { #ifdef USE_SOURCE_PANORAMA - frag_color = vec4(texturePanorama(N, source_panorama).rgb, 1.0); + frag_color = vec4(texturePanorama(N, source_panorama, 0.0).rgb, 1.0); #endif #ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY @@ -233,12 +272,51 @@ void main() { frag_color = vec4(textureDualParaboloidArray(N).rgb, 1.0); #endif -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) +#ifdef USE_SOURCE_DUAL_PARABOLOID + + frag_color = vec4(textureDualParaboloid(N).rgb, 1.0); +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) N.y = -N.y; frag_color = vec4(texture(N, source_cube).rgb, 1.0); #endif +#else // USE_DIRECT_WRITE + +#ifdef COMPUTE_IRRADIANCE + + vec3 irradiance = vec3(0.0); + + // tangent space calculation from origin point + vec3 UpVector = vec3(0.0, 1.0, 0.0); + vec3 TangentX = cross(UpVector, N); + vec3 TangentY = cross(N, TangentX); + + float num_samples = 0.0f; + + for (float phi = 0.0; phi < 2.0 * M_PI; phi += SAMPLE_DELTA) { + for (float theta = 0.0; theta < 0.5 * M_PI; theta += SAMPLE_DELTA) { + // Calculate sample positions + vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + // Find world vector of sample position + vec3 H = tangentSample.x * TangentX + tangentSample.y * TangentY + tangentSample.z * N; + + vec2 st = vec2(atan(H.x, H.z), acos(H.y)); + if (st.x < 0.0) { + st.x += M_PI * 2.0; + } + st /= vec2(M_PI * 2.0, M_PI); + + irradiance += texture(source_panorama, st, source_mip_level).rgb * cos(theta) * sin(theta); + num_samples++; + } + } + irradiance = M_PI * irradiance * (1.0 / float(num_samples)); + + frag_color = vec4(irradiance, 1.0); + #else vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); @@ -246,15 +324,26 @@ void main() { for (uint sampleNum = 0u; sampleNum < SAMPLE_COUNT; sampleNum++) { vec2 xi = Hammersley(sampleNum, SAMPLE_COUNT); - vec3 H = ImportanceSampleGGX(xi, roughness, N); + vec3 H = normalize(ImportanceSampleGGX(xi, roughness, N)); vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); + vec3 L = normalize(2.0 * dot(V, H) * H - V); - float ndotl = clamp(dot(N, L), 0.0, 1.0); + float ndotl = max(dot(N, L), 0.0); if (ndotl > 0.0) { + + float D = DistributionGGX(N, H, roughness); + float ndoth = max(dot(N, H), 0.0); + float hdotv = max(dot(H, V), 0.0); + float pdf = D * ndoth / (4.0 * hdotv) + 0.0001; + + float saTexel = 4.0 * M_PI / (6.0 * source_resolution * source_resolution); + float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); + + float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); + #ifdef USE_SOURCE_PANORAMA - sum.rgb += texturePanorama(L, source_panorama).rgb * ndotl; + sum.rgb += texturePanorama(L, source_panorama, mipLevel).rgb * ndotl; #endif #ifdef USE_SOURCE_DUAL_PARABOLOID_ARRAY @@ -262,7 +351,12 @@ void main() { sum.rgb += textureDualParaboloidArray(L).rgb * ndotl; #endif -#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) +#ifdef USE_SOURCE_DUAL_PARABOLOID + + sum.rgb += textureDualParaboloid(L).rgb * ndotl; +#endif + +#if !defined(USE_SOURCE_DUAL_PARABOLOID_ARRAY) && !defined(USE_SOURCE_PANORAMA) && !defined(USE_SOURCE_DUAL_PARABOLOID) L.y = -L.y; sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; #endif @@ -273,5 +367,6 @@ void main() { frag_color = vec4(sum.rgb, 1.0); -#endif +#endif // COMPUTE_IRRADIANCE +#endif // USE_DIRECT_WRITE } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 403de25dd0..e1b0e9f595 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -627,6 +627,8 @@ layout(std140) uniform Radiance { // ubo:2 #define RADIANCE_MAX_LOD 5.0 +uniform sampler2D irradiance_map; // texunit:-6 + #ifdef USE_RADIANCE_MAP_ARRAY uniform sampler2DArray radiance_map; // texunit:-2 @@ -1766,6 +1768,11 @@ FRAGMENT_SHADER_CODE vec3 eye_vec = view; + // IBL precalculations + float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0); + vec3 f0 = F0(metallic, specular, albedo); + vec3 F = f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(1.0 - ndotv, 5.0); + #ifdef USE_RADIANCE_MAP #ifdef AMBIENT_LIGHT_DISABLED @@ -1775,22 +1782,27 @@ FRAGMENT_SHADER_CODE { //read radiance from dual paraboloid - vec3 ref_vec = reflect(-eye_vec, normal); //2.0 * ndotv * normal - view; // reflect(v, n); + vec3 ref_vec = reflect(-eye_vec, normal); ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); vec3 radiance = textureDualParaboloid(radiance_map, ref_vec, roughness) * bg_energy; env_reflection_light = radiance; } - //no longer a cubemap - //vec3 radiance = textureLod(radiance_cube, r, lod).xyz * ( brdf.x + brdf.y); } #ifndef USE_LIGHTMAP { - vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); - vec3 env_ambient = textureDualParaboloid(radiance_map, ambient_dir, 1.0) * bg_energy; + vec3 norm = normal; + norm = normalize((radiance_inverse_xform * vec4(norm, 0.0)).xyz); + norm.xy /= 1.0 + abs(norm.z); + norm.xy = norm.xy * vec2(0.5, 0.25) + vec2(0.5, 0.25); + if (norm.z > 0.0) { + norm.y = 0.5 - norm.y + 0.5; + } + + vec3 env_ambient = texture(irradiance_map, norm.xy).rgb * bg_energy; + env_ambient *= 1.0 - F; ambient_light = mix(ambient_light_color.rgb, env_ambient, radiance_ambient_contribution); - //ambient_light=vec3(0.0,0.0,0.0); } #endif #endif //AMBIENT_LIGHT_DISABLED @@ -1892,12 +1904,9 @@ FRAGMENT_SHADER_CODE const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); vec4 r = roughness * c0 + c1; - float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0); float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - - vec3 f0 = F0(metallic, specular, albedo); - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * F + env.y; #endif } |