Refactor: EEVEE: add utility function for 3D texture read
with manual trilinear interpolation. Currently only used for GGX BSDF LUT Pull Request: https://projects.blender.org/blender/blender/pulls/112386
This commit is contained in:
parent
05045c3e50
commit
f014e44e8b
|
@ -51,8 +51,23 @@ vec2 brdf_lut(float cos_theta, float roughness)
|
|||
return textureLod(utilTex, vec3(lut_coords(cos_theta, roughness), BRDF_LUT_LAYER), 0.0).rg;
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample Surface LUT. */
|
||||
vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
||||
vec4 sample_3D_texture(sampler2DArray tex, vec3 coords)
|
||||
{
|
||||
float layer_floored;
|
||||
float interp = modf(coords.z, layer_floored);
|
||||
|
||||
coords.z = layer_floored;
|
||||
vec4 tex_low = textureLod(tex, coords, 0.0);
|
||||
|
||||
coords.z += 1.0;
|
||||
vec4 tex_high = textureLod(tex, coords, 0.0);
|
||||
|
||||
/* Manual trilinear interpolation. */
|
||||
return mix(tex_low, tex_high, interp);
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample BSDF LUT. */
|
||||
vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
||||
{
|
||||
/* ior is sin of critical angle. */
|
||||
float critical_cos = sqrt(1.0 - ior * ior);
|
||||
|
@ -69,6 +84,7 @@ vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
|||
|
||||
/* scale and bias coordinates, for correct filtered lookup */
|
||||
coords.xy = coords.xy * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
|
||||
coords.z = coords.z * lut_btdf_layer_count + lut_btdf_layer_first;
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
@ -95,19 +111,7 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
}
|
||||
|
||||
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
||||
|
||||
float layer = coords.z * lut_btdf_layer_count;
|
||||
float layer_floored = floor(layer);
|
||||
|
||||
coords.z = lut_btdf_layer_first + layer_floored;
|
||||
vec2 btdf_brdf_low = textureLod(utilTex, coords, 0.0).rg;
|
||||
|
||||
coords.z += 1.0;
|
||||
vec2 btdf_brdf_high = textureLod(utilTex, coords, 0.0).rg;
|
||||
|
||||
/* Manual trilinear interpolation. */
|
||||
vec2 btdf_brdf = mix(btdf_brdf_low, btdf_brdf_high, layer - layer_floored);
|
||||
vec2 btdf_brdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rg;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
|
|
|
@ -1316,6 +1316,23 @@ float4 utility_tx_sample_lut(sampler2DArray util_tx, float2 uv, float layer)
|
|||
return textureLod(util_tx, float3(uv, layer), 0.0);
|
||||
}
|
||||
|
||||
/* Sample GGX BSDF LUT. */
|
||||
float4 utility_tx_sample_bsdf_lut(sampler2DArray util_tx, float2 uv, float layer)
|
||||
{
|
||||
/* Scale and bias coordinates, for correct filtered lookup. */
|
||||
uv = uv * UTIL_TEX_UV_SCALE + UTIL_TEX_UV_BIAS;
|
||||
layer = layer * UTIL_BTDF_LAYER_COUNT + UTIL_BTDF_LAYER;
|
||||
|
||||
float layer_floored;
|
||||
float interp = modf(layer, layer_floored);
|
||||
|
||||
float4 tex_low = textureLod(util_tx, float3(uv, layer_floored), 0.0);
|
||||
float4 tex_high = textureLod(util_tx, float3(uv, layer_floored + 1.0), 0.0);
|
||||
|
||||
/* Manual trilinear interpolation. */
|
||||
return mix(tex_low, tex_high, interp);
|
||||
}
|
||||
|
||||
/* Sample LTC or BSDF LUTs with `cos_theta` and `roughness` as inputs. */
|
||||
float4 utility_tx_sample_lut(sampler2DArray util_tx, float cos_theta, float roughness, float layer)
|
||||
{
|
||||
|
|
|
@ -297,6 +297,23 @@ vec2 brdf_lut(float cos_theta, float roughness)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample BSDF LUT. */
|
||||
vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
||||
{
|
||||
/* IOR is the sine of the critical angle. */
|
||||
float critical_cos = sqrt(1.0 - ior * ior);
|
||||
|
||||
vec3 coords;
|
||||
coords.x = sqr(ior);
|
||||
coords.y = cos_theta;
|
||||
coords.y -= critical_cos;
|
||||
coords.y /= (coords.y > 0.0) ? (1.0 - critical_cos) : critical_cos;
|
||||
coords.y = coords.y * 0.5 + 0.5;
|
||||
coords.z = roughness;
|
||||
|
||||
return saturate(coords);
|
||||
}
|
||||
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
if (ior <= 1e-5) {
|
||||
|
@ -318,28 +335,9 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter
|
|||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
}
|
||||
|
||||
/* IOR is sin of critical angle. */
|
||||
float critical_cos = sqrt(1.0 - ior * ior);
|
||||
|
||||
vec3 coords;
|
||||
coords.x = sqr(ior);
|
||||
coords.y = cos_theta;
|
||||
coords.y -= critical_cos;
|
||||
coords.y /= (coords.y > 0.0) ? (1.0 - critical_cos) : critical_cos;
|
||||
coords.y = coords.y * 0.5 + 0.5;
|
||||
coords.z = roughness;
|
||||
|
||||
coords = saturate(coords);
|
||||
|
||||
float layer = coords.z * UTIL_BTDF_LAYER_COUNT;
|
||||
float layer_floored = floor(layer);
|
||||
|
||||
#ifdef EEVEE_UTILITY_TX
|
||||
coords.z = UTIL_BTDF_LAYER + layer_floored;
|
||||
vec2 btdf_brdf_low = utility_tx_sample_lut(utility_tx, coords.xy, coords.z).rg;
|
||||
vec2 btdf_brdf_high = utility_tx_sample_lut(utility_tx, coords.xy, coords.z + 1.0).rg;
|
||||
/* Manual trilinear interpolation. */
|
||||
vec2 btdf_brdf = mix(btdf_brdf_low, btdf_brdf_high, layer - layer_floored);
|
||||
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
||||
vec2 btdf_brdf = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).rg;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
|
|
Loading…
Reference in New Issue