EEVEE: use Schlick's approximation instead of real Fresnel for glass #112390
|
@ -192,10 +192,12 @@ static void eevee_init_util_texture()
|
|||
for (int j = 0; j < 16; j++) {
|
||||
for (int x = 0; x < 64; x++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
/* BSDF LUT for `IOR < 1`. */
|
||||
texels_layer[y * 64 + x][0] = blender::eevee::lut::bsdf_ggx[j][y][x][0];
|
||||
texels_layer[y * 64 + x][1] = blender::eevee::lut::bsdf_ggx[j][y][x][1];
|
||||
texels_layer[y * 64 + x][2] = 0.0; /* UNUSED */
|
||||
texels_layer[y * 64 + x][3] = 0.0; /* UNUSED */
|
||||
texels_layer[y * 64 + x][2] = blender::eevee::lut::bsdf_ggx[j][y][x][2];
|
||||
weizhen marked this conversation as resolved
|
||||
/* BTDF LUT for `IOR > 1`, parametrized differently as above. See `eevee_lut_comp.glsl`. */
|
||||
texels_layer[y * 64 + x][3] = blender::eevee::lut::btdf_ggx[j][y][x][0];
|
||||
}
|
||||
}
|
||||
texels_layer += 64 * 64;
|
||||
|
|
|
@ -66,6 +66,18 @@ vec4 sample_3D_texture(sampler2DArray tex, vec3 coords)
|
|||
return mix(tex_low, tex_high, interp);
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample Surface LUT. */
|
||||
vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
||||
{
|
||||
vec3 coords = vec3(sqrt((ior - 1.0) / (ior + 1.0)), sqrt(1.0 - cos_theta), roughness);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample BSDF LUT. */
|
||||
vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
||||
{
|
||||
|
@ -89,37 +101,45 @@ vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
|||
return coords;
|
||||
}
|
||||
|
||||
/* Returns GGX transmittance in first component and reflectance in second. */
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
if (ior <= 1e-5) {
|
||||
if (ior == 1.0) {
|
||||
return vec2(0.0, 1.0);
|
||||
}
|
||||
|
||||
vec2 split_sum;
|
||||
float transmission_factor;
|
||||
float F0 = F0_from_ior(ior);
|
||||
float F90 = 1.0;
|
||||
|
||||
if (ior >= 1.0) {
|
||||
vec2 split_sum = brdf_lut(cos_theta, roughness);
|
||||
float f0 = F0_from_ior(ior);
|
||||
split_sum = brdf_lut(cos_theta, roughness);
|
||||
transmission_factor = sample_3D_texture(utilTex, lut_coords_btdf(cos_theta, roughness, ior)).a;
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
float f90 = fast_sqrt(saturate(f0 / 0.02));
|
||||
|
||||
float brdf = F_brdf_multi_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Energy conservation. */
|
||||
float btdf = 1.0 - brdf;
|
||||
/* Assuming the energy loss caused by single-scattering is distributed proportionally in the
|
||||
* reflection and refraction lobes. */
|
||||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
||||
}
|
||||
else {
|
||||
vec3 bsdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rgb;
|
||||
split_sum = bsdf.rg;
|
||||
transmission_factor = bsdf.b;
|
||||
}
|
||||
|
||||
vec2 btdf_brdf = sample_3D_texture(utilTex, lut_coords_bsdf(cos_theta, roughness, ior)).rg;
|
||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
||||
float transmittance = (1.0 - F0) * transmission_factor;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
* the energy loss of single-scattering is distributed proportionally in the two lobes. */
|
||||
btdf_brdf /= (btdf_brdf.x + btdf_brdf.y);
|
||||
if (do_multiscatter) {
|
||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
||||
* However, it is not necessarily desirable that the users see a different color than they
|
||||
* picked. */
|
||||
float scale = 1.0 / Ess;
|
||||
reflectance *= scale;
|
||||
transmittance *= scale;
|
||||
}
|
||||
|
||||
return btdf_brdf;
|
||||
return vec2(reflectance, transmittance);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,8 +20,10 @@ extern const float ltc_mag_ggx[64][64][2];
|
|||
extern const float ltc_disk_integral[64][64][1];
|
||||
/* Precomputed integrated split fresnel term of the GGX BRDF. */
|
||||
extern const float brdf_ggx[64][64][2];
|
||||
/* Precomputed reflectance and transmittance of glass material with IOR < 1. */
|
||||
extern const float bsdf_ggx[16][64][64][2];
|
||||
/* Precomputed Schlick reflectance and transmittance factor of glass material with IOR < 1. */
|
||||
extern const float bsdf_ggx[16][64][64][3];
|
||||
/* Precomputed Schlick transmittance factor of glass material with IOR > 1. */
|
||||
extern const float btdf_ggx[16][64][64][1];
|
||||
/* 4 different blue noise, one per channel. */
|
||||
extern const float blue_noise[64][64][4];
|
||||
|
||||
|
|
|
@ -419,6 +419,8 @@ class UtilityTexture : public Texture {
|
|||
for (auto y : IndexRange(lut_size)) {
|
||||
layer.data[y][x][0] = lut::bsdf_ggx[layer_id][y][x][0];
|
||||
layer.data[y][x][1] = lut::bsdf_ggx[layer_id][y][x][1];
|
||||
layer.data[y][x][2] = lut::bsdf_ggx[layer_id][y][x][2];
|
||||
layer.data[y][x][3] = lut::btdf_ggx[layer_id][y][x][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,8 @@ enum eDebugMode : uint32_t {
|
|||
|
||||
enum PrecomputeType : uint32_t {
|
||||
LUT_GGX_BRDF_SPLIT_SUM = 0u,
|
||||
LUT_GGX_BSDF_SPLIT_SUM = 1u,
|
||||
LUT_GGX_BTDF_IOR_GT_ONE = 1u,
|
||||
LUT_GGX_BSDF_SPLIT_SUM = 2u,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -1292,7 +1293,7 @@ BLI_STATIC_ASSERT_ALIGN(UniformData, 16)
|
|||
#define UTIL_LTC_MAT_LAYER 2
|
||||
#define UTIL_LTC_MAG_LAYER 3
|
||||
#define UTIL_BSDF_LAYER 3
|
||||
#define UTIL_BTDF_LAYER 4
|
||||
#define UTIL_BTDF_LAYER 5
|
||||
#define UTIL_DISK_INTEGRAL_LAYER 4
|
||||
#define UTIL_DISK_INTEGRAL_COMP 3
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/* Generate BRDF LUT following "Real shading in unreal engine 4" by Brian Karis
|
||||
* https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
|
||||
* Parametrizing with `x = roughness` and `y = sqrt(1.0 - cos(theta))`.
|
||||
* The result is interpreted as: `integral = f0 * scale + f90 * bias`. */
|
||||
* The result is interpreted as: `integral = F0 * scale + F90 * bias`. */
|
||||
vec4 ggx_brdf_split_sum(vec3 lut_coord)
|
||||
{
|
||||
/* Squaring for perceptually linear roughness, see [Physically Based Shading at Disney]
|
||||
|
@ -54,7 +54,12 @@ vec4 ggx_brdf_split_sum(vec3 lut_coord)
|
|||
return vec4(scale, bias, 0.0, 0.0);
|
||||
}
|
||||
|
||||
/* Generate BSDF LUT for `IOR < 1`. Returns the transmittance and the reflectance. */
|
||||
/* Generate BSDF LUT for `IOR < 1` using Schlick's approximation. Returns the transmittance and the
|
||||
* scale and bias for reflectance.
|
||||
*
|
||||
* The result is interpreted as:
|
||||
* `reflectance = F0 * scale + F90 * bias`,
|
||||
* `transmittance = (1 - F0) * transmission_factor`. */
|
||||
vec4 ggx_bsdf_split_sum(vec3 lut_coord)
|
||||
{
|
||||
float ior = sqrt(lut_coord.x);
|
||||
|
@ -78,9 +83,9 @@ vec4 ggx_bsdf_split_sum(vec3 lut_coord)
|
|||
vec3 V = vec3(sqrt(1.0 - square(NV)), 0.0, NV);
|
||||
|
||||
/* Integrating BSDF */
|
||||
float transmittance = 0.0;
|
||||
float reflectance = 0.0;
|
||||
|
||||
float scale = 0.0;
|
||||
float bias = 0.0;
|
||||
float transmission_factor = 0.0;
|
||||
const uint sample_count = 512u * 512u;
|
||||
for (uint i = 0u; i < sample_count; i++) {
|
||||
vec2 rand = hammersley_2d(i, sample_count);
|
||||
|
@ -88,14 +93,17 @@ vec4 ggx_bsdf_split_sum(vec3 lut_coord)
|
|||
|
||||
/* Microfacet normal. */
|
||||
vec3 H = sample_ggx(Xi, roughness, V);
|
||||
float fresnel = F_eta(ior, dot(V, H));
|
||||
float HL = 1.0 - (1.0 - square(dot(V, H))) / square(ior);
|
||||
float s = saturate(pow5f(1.0 - saturate(HL)));
|
||||
|
||||
/* Reflection. */
|
||||
vec3 R = -reflect(V, H);
|
||||
float NR = R.z;
|
||||
if (NR > 0.0) {
|
||||
/* Assuming sample visible normals, accumulating `brdf * NV / pdf.` */
|
||||
reflectance += fresnel * bxdf_ggx_smith_G1(NR, roughness_sq);
|
||||
/* Assuming sample visible normals, `weight = brdf * NV / (pdf * fresnel).` */
|
||||
float weight = bxdf_ggx_smith_G1(NR, roughness_sq);
|
||||
scale += (1.0 - s) * weight;
|
||||
bias += s * weight;
|
||||
}
|
||||
|
||||
/* Refraction. */
|
||||
|
@ -103,16 +111,63 @@ vec4 ggx_bsdf_split_sum(vec3 lut_coord)
|
|||
float NT = T.z;
|
||||
/* In the case of TIR, `T == vec3(0)`. */
|
||||
if (NT < 0.0) {
|
||||
/* Assuming sample visible normals, accumulating `btdf * NV / pdf.` */
|
||||
transmittance += (1.0 - fresnel) * bxdf_ggx_smith_G1(NT, roughness_sq);
|
||||
/* Assuming sample visible normals, accumulating `btdf * NV / (pdf * (1 - F0)).` */
|
||||
transmission_factor += (1.0 - s) * bxdf_ggx_smith_G1(NT, roughness_sq);
|
||||
}
|
||||
}
|
||||
transmittance /= float(sample_count);
|
||||
reflectance /= float(sample_count);
|
||||
transmission_factor /= float(sample_count);
|
||||
scale /= float(sample_count);
|
||||
bias /= float(sample_count);
|
||||
|
||||
/* There is place to put multi-scatter result (which is a little bit different still)
|
||||
* and / or lobe fitting for better sampling of. */
|
||||
return vec4(transmittance, reflectance, 0.0, 0.0);
|
||||
return vec4(scale, bias, transmission_factor, 0.0);
|
||||
}
|
||||
|
||||
/* Generate BTDF LUT for `IOR > 1` using Schlick's approximation. Only the transmittance is needed
|
||||
* because the scale and bias does not depend on the IOR and can be obtained from the BRDF LUT.
|
||||
*
|
||||
* Parametrize with `x = sqrt((ior - 1) / (ior + 1))` for higher precision in 1 < IOR < 2,
|
||||
* and `y = sqrt(1.0 - cos(theta))`, `z = roughness` similar to BRDF LUT.
|
||||
*
|
||||
* The result is interpreted as:
|
||||
* `transmittance = (1 - F0) * transmission_factor`. */
|
||||
vec4 ggx_btdf_gt_one(vec3 lut_coord)
|
||||
{
|
||||
float f0 = square(lut_coord.x);
|
||||
float inv_ior = (1.0 - f0) / (1.0 + f0);
|
||||
|
||||
float NV = clamp(1.0 - square(lut_coord.y), 1e-4, 0.9999);
|
||||
vec3 V = vec3(sqrt(1.0 - square(NV)), 0.0, NV);
|
||||
|
||||
/* Squaring for perceptually linear roughness, see [Physically Based Shading at Disney]
|
||||
* (https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf)
|
||||
* Section 5.4. */
|
||||
float roughness = square(lut_coord.z);
|
||||
float roughness_sq = square(roughness);
|
||||
|
||||
/* Integrating BTDF. */
|
||||
float transmission_factor = 0.0;
|
||||
const uint sample_count = 512u * 512u;
|
||||
for (uint i = 0u; i < sample_count; i++) {
|
||||
vec2 rand = hammersley_2d(i, sample_count);
|
||||
vec3 Xi = sample_cylinder(rand);
|
||||
|
||||
/* Microfacet normal. */
|
||||
vec3 H = sample_ggx(Xi, roughness, V);
|
||||
|
||||
/* Refraction. */
|
||||
vec3 L = refract(-V, H, inv_ior);
|
||||
float NL = L.z;
|
||||
|
||||
if (NL < 0.0) {
|
||||
/* Schlick's Fresnel. */
|
||||
float s = saturate(pow5f(1.0 - saturate(dot(V, H))));
|
||||
/* Assuming sample visible normals, accumulating `btdf * NV / (pdf * (1 - F0)).` */
|
||||
transmission_factor += (1.0 - s) * bxdf_ggx_smith_G1(NL, roughness_sq);
|
||||
}
|
||||
}
|
||||
transmission_factor /= float(sample_count);
|
||||
|
||||
return vec4(transmission_factor, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
|
@ -125,6 +180,9 @@ void main()
|
|||
case LUT_GGX_BRDF_SPLIT_SUM:
|
||||
result = ggx_brdf_split_sum(lut_normalized_coordinate);
|
||||
break;
|
||||
case LUT_GGX_BTDF_IOR_GT_ONE:
|
||||
result = ggx_btdf_gt_one(lut_normalized_coordinate);
|
||||
break;
|
||||
case LUT_GGX_BSDF_SPLIT_SUM:
|
||||
result = ggx_bsdf_split_sum(lut_normalized_coordinate);
|
||||
break;
|
||||
|
|
|
@ -314,38 +314,54 @@ vec3 lut_coords_bsdf(float cos_theta, float roughness, float ior)
|
|||
return saturate(coords);
|
||||
}
|
||||
|
||||
/* Return texture coordinates to sample Surface LUT. */
|
||||
vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
||||
{
|
||||
return vec3(sqrt((ior - 1.0) / (ior + 1.0)), sqrt(1.0 - cos_theta), roughness);
|
||||
}
|
||||
|
||||
/* Computes the reflectance and transmittance based on the BSDF LUT. */
|
||||
vec2 bsdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
if (ior <= 1e-5) {
|
||||
#ifdef EEVEE_UTILITY_TX
|
||||
if (ior == 1.0) {
|
||||
return vec2(0.0, 1.0);
|
||||
}
|
||||
|
||||
vec2 split_sum;
|
||||
float transmission_factor;
|
||||
float F0 = F0_from_ior(ior);
|
||||
float F90 = 1.0;
|
||||
|
||||
if (ior >= 1.0) {
|
||||
vec2 split_sum = brdf_lut(cos_theta, roughness);
|
||||
float f0 = F0_from_ior(ior);
|
||||
split_sum = brdf_lut(cos_theta, roughness);
|
||||
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
||||
transmission_factor = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).a;
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
float f90 = fast_sqrt(saturate(f0 / 0.02));
|
||||
|
||||
float brdf = F_brdf_multi_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Energy conservation. */
|
||||
float btdf = 1.0 - brdf;
|
||||
/* Assuming the energy loss caused by single-scattering is distributed proportionally in the
|
||||
* reflection and refraction lobes. */
|
||||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
F90 = saturate(2.33 / 0.33 * (ior - 1.0) / (ior + 1.0));
|
||||
}
|
||||
else {
|
||||
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
||||
vec3 bsdf = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).rgb;
|
||||
split_sum = bsdf.rg;
|
||||
transmission_factor = bsdf.b;
|
||||
}
|
||||
|
||||
#ifdef EEVEE_UTILITY_TX
|
||||
vec3 coords = lut_coords_bsdf(cos_theta, roughness, ior);
|
||||
vec2 btdf_brdf = utility_tx_sample_bsdf_lut(utility_tx, coords.xy, coords.z).rg;
|
||||
float reflectance = F_brdf_single_scatter(vec3(F0), vec3(F90), split_sum).r;
|
||||
float transmittance = (1.0 - F0) * transmission_factor;
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
* the energy loss of single-scattering is distributed proportionally in the two lobes. */
|
||||
btdf_brdf /= (btdf_brdf.x + btdf_brdf.y);
|
||||
if (do_multiscatter) {
|
||||
float Ess = F0 * split_sum.x + split_sum.y + (1.0 - F0) * transmission_factor;
|
||||
/* TODO: maybe add saturation for higher roughness similar as in `F_brdf_multi_scatter()`.
|
||||
* However, it is not necessarily desirable that the users see a different color than they
|
||||
* picked. */
|
||||
float scale = 1.0 / Ess;
|
||||
reflectance *= scale;
|
||||
transmittance *= scale;
|
||||
}
|
||||
|
||||
return btdf_brdf;
|
||||
return vec2(reflectance, transmittance);
|
||||
#else
|
||||
return vec2(0.0);
|
||||
#endif
|
||||
|
|
|
@ -1449,13 +1449,16 @@ static void test_eevee_lut_gen()
|
|||
|
||||
/* Check if LUT generation matches the header version. */
|
||||
auto brdf_ggx_gen = Precompute(manager, LUT_GGX_BRDF_SPLIT_SUM, {64, 64, 1}).data<float2>();
|
||||
auto bsdf_ggx_gen = Precompute(manager, LUT_GGX_BSDF_SPLIT_SUM, {64, 64, 16}).data<float2>();
|
||||
auto btdf_ggx_gen = Precompute(manager, LUT_GGX_BTDF_IOR_GT_ONE, {64, 64, 16}).data<float1>();
|
||||
auto bsdf_ggx_gen = Precompute(manager, LUT_GGX_BSDF_SPLIT_SUM, {64, 64, 16}).data<float3>();
|
||||
|
||||
Span<float2> brdf_ggx_lut((const float2 *)&eevee::lut::brdf_ggx, 64 * 64);
|
||||
Span<float2> bsdf_ggx_lut((const float2 *)&eevee::lut::bsdf_ggx, 64 * 64 * 16);
|
||||
Span<float1> btdf_ggx_lut((const float1 *)&eevee::lut::btdf_ggx, 64 * 64 * 16);
|
||||
Span<float3> bsdf_ggx_lut((const float3 *)&eevee::lut::bsdf_ggx, 64 * 64 * 16);
|
||||
|
||||
EXPECT_NEAR_ARRAY_ND(brdf_ggx_lut.data(), brdf_ggx_gen.data(), brdf_ggx_gen.size(), 2, 1e-4f);
|
||||
EXPECT_NEAR_ARRAY_ND(bsdf_ggx_lut.data(), bsdf_ggx_gen.data(), bsdf_ggx_gen.size(), 2, 1e-4f);
|
||||
EXPECT_NEAR_ARRAY_ND(btdf_ggx_lut.data(), btdf_ggx_gen.data(), btdf_ggx_gen.size(), 1, 1e-4f);
|
||||
EXPECT_NEAR_ARRAY_ND(bsdf_ggx_lut.data(), bsdf_ggx_gen.data(), bsdf_ggx_gen.size(), 3, 1e-4f);
|
||||
|
||||
GPU_render_end();
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ void node_bsdf_glass(vec4 color,
|
|||
vec2 bsdf = bsdf_lut(NV, roughness, ior, do_multiscatter);
|
||||
|
||||
ClosureReflection reflection_data;
|
||||
reflection_data.weight = bsdf.y * weight;
|
||||
reflection_data.weight = bsdf.x * weight;
|
||||
reflection_data.color = color.rgb;
|
||||
reflection_data.N = N;
|
||||
reflection_data.roughness = roughness;
|
||||
|
||||
ClosureRefraction refraction_data;
|
||||
refraction_data.weight = bsdf.x * weight;
|
||||
refraction_data.weight = bsdf.y * weight;
|
||||
refraction_data.color = color.rgb;
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
|
|
|
@ -84,7 +84,7 @@ void node_bsdf_principled(vec4 base_color,
|
|||
coat_data.N = CN;
|
||||
coat_data.roughness = coat_roughness;
|
||||
float coat_NV = dot(coat_data.N, V);
|
||||
float reflectance = bsdf_lut(coat_NV, coat_data.roughness, coat_ior, 0.0).y;
|
||||
float reflectance = bsdf_lut(coat_NV, coat_data.roughness, coat_ior, 0.0).x;
|
||||
coat_data.weight = weight * coat * reflectance;
|
||||
coat_data.color = vec3(1.0);
|
||||
/* Attenuate lower layers */
|
||||
|
@ -127,9 +127,9 @@ void node_bsdf_principled(vec4 base_color,
|
|||
if (true) {
|
||||
vec2 bsdf = bsdf_lut(NV, roughness, ior, do_multiscatter);
|
||||
|
||||
reflection_data.color += weight * transmission * bsdf.y * reflection_tint;
|
||||
reflection_data.color += weight * transmission * bsdf.x * reflection_tint;
|
||||
|
||||
refraction_data.weight = weight * transmission * bsdf.x;
|
||||
refraction_data.weight = weight * transmission * bsdf.y;
|
||||
refraction_data.color = base_color.rgb * coat_tint.rgb;
|
||||
refraction_data.N = N;
|
||||
refraction_data.roughness = roughness;
|
||||
|
|
Loading…
Reference in New Issue
Maybe note that this doesn't share the same parametrization.