Skip to content

Commit

Permalink
vk: rt: attenuate secondary bounces
Browse files Browse the repository at this point in the history
`throughput` should be scaled based on BRDF. I.e. diffuse bounces should
be scales by base_color at the very least.

This fixes lighting being too bright after 3-5 bounces.
  • Loading branch information
w23 committed Jan 29, 2024
1 parent be8da32 commit ae3f79c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 51 deletions.
3 changes: 3 additions & 0 deletions ref/vk/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- [ ] -vkdbgprintf or something
- [ ] performance profiling and comparison

## 2024-01-29 E370
- [x] bounce > 1 brighness

# Previously
## 2024-01-26 E369
- [x] white furnace test
Expand Down
80 changes: 39 additions & 41 deletions ref/vk/shaders/bounce.comp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ struct MaterialEx {

int max_bounces = 1;

const vec3 kThrougputExtinctionThreshold = vec3(1e-3);

ivec2 pix;
void computeBounces(MaterialEx mat, vec3 pos, vec3 direction, inout vec3 diffuse, inout vec3 specular) {
const float ray_normal_fudge = .01;
Expand All @@ -124,6 +126,28 @@ void computeBounces(MaterialEx mat, vec3 pos, vec3 direction, inout vec3 diffuse
if (brdf_type == BRDF_TYPE_NONE)
return;

if (IS_INVALIDV(throughput)) {
#ifdef SHADER_DEBUG_ENABLE
debugPrintfEXT("pix=(%d,%d) pos=(%f,%f,%f) dir=(%f,%f,%f) throughput=invalid",
pix.x, pix.y, pos.x, pos.y, pos.z, direction.x, direction.y, direction.z);
#endif
throughput = vec3(0.);
}

/*
if (any(lessThan(throughput, vec3(0.)))) {
#ifdef SHADER_DEBUG_ENABLE
debugPrintfEXT("pix=(%d,%d) pos=(%f,%f,%f) dir=(%f,%f,%f) throughput=(%f, %f, %f)",
pix.x, pix.y, pos.x, pos.y, pos.z, direction.x, direction.y, direction.z,
throughput.r, throughput.g, throughput.b
);
#endif
}
*/

if (all(lessThan(throughput,kThrougputExtinctionThreshold)))
return;

if (first_brdf_type == BRDF_TYPE_NONE)
first_brdf_type = brdf_type;

Expand All @@ -133,7 +157,7 @@ void computeBounces(MaterialEx mat, vec3 pos, vec3 direction, inout vec3 diffuse
payload.material_rmxx = vec4(0.);
payload.normals_gs = vec4(0.);

vec3 lighting = vec3(0.);
vec3 contribution = vec3(0.);
pos += mat.geometry_normal * ray_normal_fudge;
const bool did_hit = getHit(pos, bounce_direction, payload);
bool hit_skybox = false;
Expand Down Expand Up @@ -179,7 +203,13 @@ void computeBounces(MaterialEx mat, vec3 pos, vec3 direction, inout vec3 diffuse
//background += lspecular * mix(vec3(1.), payload.base_color_a.rgb, hit_material.metalness);

const vec4 blend = traceLegacyBlending(pos, bounce_direction, payload.hit_t.w);
lighting = SRGBtoLINEAR(blend.rgb) + background * blend.a;
contribution = throughput*(SRGBtoLINEAR(blend.rgb) + background * blend.a);

// FIXME check this very early before doing any lighting stuff
hit_skybox = payload.hit_t.w < 0.;
if (hit_skybox)
/* FIXME: also if last bounce (i.e. w/o direct light sampling) or */
contribution += throughput * payload.emissive.rgb;

// Prepare next bounce state
pos = hit_pos;
Expand All @@ -188,57 +218,25 @@ void computeBounces(MaterialEx mat, vec3 pos, vec3 direction, inout vec3 diffuse
mat.geometry_normal = normalDecode(payload.normals_gs.xy);
mat.shading_normal = hit_shading_normal;

hit_skybox = payload.hit_t.w < 0.;
if (brdf_type == BRDF_TYPE_DIFFUSE) {
const vec3 diffuse_color = mix(payload.base_color_a.rgb, vec3(0.), payload.material_rmxx.g);
throughput *= diffuse_color;
}
} else {
// FIXME this no-hit path should still do traceLegacyBlending()
lighting = sampleSkybox(bounce_direction);
contribution = throughput * sampleSkybox(bounce_direction);
hit_skybox = true;
} // not hit

/* TODO: also if last bounce (i.e. w/o direct light sampling) or */
if (hit_skybox)
lighting += payload.emissive.rgb;

if (first_brdf_type == BRDF_TYPE_DIFFUSE)
diffuse += throughput * lighting;
diffuse += contribution;
else
specular += throughput * lighting;

if (IS_INVALIDV(throughput)) {
#ifdef SHADER_DEBUG_ENABLE
debugPrintfEXT("pix=(%d,%d) pos=(%f,%f,%f) dir=(%f,%f,%f) throughput=invalid",
pix.x, pix.y, pos.x, pos.y, pos.z, direction.x, direction.y, direction.z);
#endif
throughput = vec3(0.);
//diffuse = 10.*vec3(1., 0., 0.);
//specular = 10.*vec3(0., 0., 1.);
} else {
//diffuse = throughput;
}

/*
if (any(lessThan(throughput, vec3(0.)))) {
#ifdef SHADER_DEBUG_ENABLE
debugPrintfEXT("pix=(%d,%d) pos=(%f,%f,%f) dir=(%f,%f,%f) throughput=(%f, %f, %f)",
pix.x, pix.y, pos.x, pos.y, pos.z, direction.x, direction.y, direction.z,
throughput.r, throughput.g, throughput.b
);
#endif
}
*/
specular += contribution;

if (hit_skybox) {
//diffuse = vec3(1.,1.,0.);
break;
} else {
//diffuse = vec3(0.,1.,1.);
}

//if (should_include_emissive)
//diffuse = lighting;// payload.emissive.rgb;
//diffuse = bounce_direction * .5 + .5;
//diffuse = throughput;

} // for bounces
}

Expand Down
13 changes: 3 additions & 10 deletions ref/vk/shaders/brdf.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void brdfComputeGltfModel(vec3 N, vec3 L, vec3 V, MaterialProperties material, o

// Specular does get the real color, as its contribution is light-direction-dependent
const vec3 f0 = mix(vec3(.04), material.base_color, material.metalness);
float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
const float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
const vec3 fresnel = vec3(1.) * fresnel_factor + f0 * (1. - fresnel_factor);

// This is taken directly from glTF 2.0 spec. It seems incorrect to me: it should not include the base_color twice.
Expand Down Expand Up @@ -349,18 +349,12 @@ vec3 SampleGGXReflection ( vec3 i , vec2 alpha , vec2 rand ) {

int brdfGetSample(vec2 rnd, MaterialProperties material, vec3 view, vec3 geometry_normal, vec3 shading_normal, /*float alpha, */out vec3 out_direction, inout vec3 inout_throughput) {
#if 1
// Idiotic sampling, super noisy, bad distribution, etc etc
// But we need to start somewhere
// TODO pick diffuse-vs-specular based on expected contribution
// TODO fresnel factor
// TODO base_color also might play a role

// See SELECTING BRDF LOBES in 14.3.6 RT Gems 2
// TODO DRY brdfComputeGltfModel
// Use shading_normal as H estimate
const float h_dot_v = max(0., dot(shading_normal, view));
const vec3 f0 = mix(vec3(.04), material.base_color, material.metalness);
float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
const float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
const vec3 fresnel = vec3(1.) * fresnel_factor + f0 * (1. - fresnel_factor);
const float est_spec = luminance(fresnel);
const float est_diff = (1. - fresnel_factor) * (1. - material.metalness);
Expand Down Expand Up @@ -393,8 +387,7 @@ if (g_mat_gltf2) {

const vec3 H = normalize(out_direction + view);
const float h_dot_v = max(0., dot(H, view));
const vec3 f0 = mix(vec3(.04), material.base_color, material.metalness);
float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
const float fresnel_factor = max(0., pow(1. - abs(h_dot_v), 5.));
// TODO use mix(), higher chance for it to be optimized
const vec3 fresnel = vec3(1.) * fresnel_factor + f0 * (1. - fresnel_factor);

Expand Down

0 comments on commit ae3f79c

Please sign in to comment.