rtx: improve emissive surface sampling

Sample a single triangle not in a loop.
This commit is contained in:
Ivan Avdeev 2021-09-04 09:47:49 -07:00 committed by Ivan Avdeev
parent e4aea1486f
commit 8cf040f9be
2 changed files with 49 additions and 69 deletions

View File

@ -1,8 +1,8 @@
## 2021-09-01, E132
- [x] rtx: ingest brdfs from ray tracing gems 2
- [x] rtx: directly select a triangle for light sampling
# Next
- [ ] rtx: directly select a triangle for light sampling
- [ ] rtx: pass alpha for transparency
- [ ] rtx: remove additive/refractive flags in favor or probability of ray continuing further instead of bouncing off
- [ ] rtx: experiment with refraction index and "refraction roughness"

View File

@ -11,6 +11,7 @@
const float dlight_attenuation_const = 10000.;
const float shadow_offset_fudge = .5;
const float normal_offset_fudge = .1;
const float brightness_fudge = 30.;
layout (constant_id = 0) const uint MAX_DLIGHTS = 32;
layout (constant_id = 1) const uint MAX_EMISSIVE_KUSOCHKI = 256;
@ -97,6 +98,50 @@ bool shadowed(vec3 pos, vec3 dir, float dist) {
return shadow;
}
vec3 sampleSurfaceTriangle(vec3 view_dir, MaterialProperties material, mat4x3 emissive_transform, mat3 emissive_transform_normal, uint triangle_index, uint index_offset, uint vertex_offset) {
const uint first_index_offset = index_offset + triangle_index * 3;
// TODO this is not entirely correct -- need to mix between all normals, or have this normal precomputed
const uint vi1 = uint(indices[first_index_offset+0]) + vertex_offset;
const vec3 n1 = normalize(emissive_transform_normal * vertices[vi1].normal);
// if (dot(n1, normal) >= 0. /* TODO epsilon */ )
// continue;
// TODO random sample point on the entire geometry ?
const uint vi2 = uint(indices[first_index_offset+1]) + vertex_offset;
const uint vi3 = uint(indices[first_index_offset+2]) + vertex_offset;
const vec3 v1 = (emissive_transform * vec4(vertices[vi1].pos, 1.)).xyz;
const vec3 v2 = (emissive_transform * vec4(vertices[vi2].pos, 1.)).xyz;
const vec3 v3 = (emissive_transform * vec4(vertices[vi3].pos, 1.)).xyz;
// TODO projected uniform sampling
const vec3 sample_pos = mix(mix(v1, v2, rand01()), v3, rand01());
//const vec3 sample_pos = vertices[vi1].pos;
// const vec3 n2 = vertices[vi2].normal;
// const vec3 n3 = vertices[vi3].normal;
vec3 light_dir = sample_pos - payload.hit_pos_t.xyz;
float light_dot = -dot(light_dir, n1);
if (light_dot <= 0.)
return vec3(0.);
const float light_dist = length(light_dir);
light_dot /= light_dist;
light_dir /= light_dist;
const float light_dir_normal_dot = dot(light_dir, payload.normal);
if (light_dir_normal_dot <= 0.)
return vec3(0.);
if (shadowed(payload.hit_pos_t.xyz, light_dir, light_dist - shadow_offset_fudge))
return vec3(0.);
// TODO sample emissive texture
return brightness_fudge * evalCombinedBRDF(payload.normal, light_dir, view_dir, material) / (light_dist * light_dist);
}
vec3 computeLighting(vec3 view_dir, MaterialProperties material) {
vec3 C = vec3(0.);
const ivec3 light_cell = ivec3(floor(payload.hit_pos_t.xyz / LIGHT_GRID_CELL_SIZE)) - light_grid.grid_min;
@ -114,8 +159,6 @@ vec3 computeLighting(vec3 view_dir, MaterialProperties material) {
//C += .3 * fract(vec3(light_cell) / 4.);
const uint num_emissive_kusochki = uint(light_grid.clusters[cluster_index].num_emissive_surfaces);
//const uint num_emissive_kusochki = emissive_kusochki.num_kusochki;
float sampling_light_scale = 1.;
#if 0
const uint max_lights_per_frame = 4;
@ -145,80 +188,17 @@ vec3 computeLighting(vec3 view_dir, MaterialProperties material) {
const mat3 emissive_transform_normal = transpose(inverse(mat3(emissive_transform)));
// if (i != picked_light) {
// continue;
// }
if (emissive_kusok_index == uint(payload.kusok_index)) {
// TODO do we need to do this when we have textures?
//C += throughput * vec3(hash(float(kusok_index)), hash(float(kusok_index)+15.43), hash(float(kusok_index)+34.));//kusok.emissive.rgb;
//C = vec3(1., 0., 1.);
if (emissive_kusok_index == uint(payload.kusok_index))
continue;
}
const uint picked_tri = rand_range(ekusok.triangles);
for (uint ti = 0; ti < ekusok.triangles; ++ti) {
const uint first_index_offset = ekusok.index_offset + ti * 3;
// TODO this is not entirely correct -- need to mix between all normals, or have this normal precomputed
const uint vi1 = uint(indices[first_index_offset+0]) + ekusok.vertex_offset;
const vec3 n1 = normalize(emissive_transform_normal * vertices[vi1].normal);
// if (dot(n1, normal) >= 0. /* TODO epsilon */ )
// continue;
if (picked_tri > ti)
continue;
// TODO random sample point on the entire ekusok geometry
const uint vi2 = uint(indices[first_index_offset+1]) + ekusok.vertex_offset;
const uint vi3 = uint(indices[first_index_offset+2]) + ekusok.vertex_offset;
const vec3 v1 = (emissive_transform * vec4(vertices[vi1].pos, 1.)).xyz;
const vec3 v2 = (emissive_transform * vec4(vertices[vi2].pos, 1.)).xyz;
const vec3 v3 = (emissive_transform * vec4(vertices[vi3].pos, 1.)).xyz;
const vec3 sample_pos = mix(mix(v1, v2, rand01()), v3, rand01());
//const vec3 sample_pos = vertices[vi1].pos;
// const vec3 n2 = vertices[vi2].normal;
// const vec3 n3 = vertices[vi3].normal;
vec3 light_dir = sample_pos - payload.hit_pos_t.xyz;
float light_dot = -dot(light_dir, n1);
if (light_dot <= 0.) {
//C = vec3(1., 0., 1.);
continue;
}
const float light_dist = length(light_dir);
light_dot /= light_dist;
light_dir /= light_dist;
const float light_dir_normal_dot = dot(light_dir, payload.normal);
if (light_dir_normal_dot <= 0.)
continue;
if (shadowed(payload.hit_pos_t.xyz, light_dir, light_dist - shadow_offset_fudge)) {
//C = vec3(0., 1., 0.);
continue;
}
// TODO
const float brightness_fudge = 30.;
C += sampling_light_scale * brightness_fudge * emissive * evalCombinedBRDF(payload.normal, light_dir, view_dir, material) / (light_dist * light_dist);
// Sample just one triangle
break;
} // for emissive kusok triangles
const uint triangle_index = rand_range(ekusok.triangles);
C += sampling_light_scale * emissive * sampleSurfaceTriangle(view_dir, material, emissive_transform, emissive_transform_normal, triangle_index, ekusok.index_offset, ekusok.vertex_offset);
} // for all emissive kusochki
for (uint i = 0; i < num_lights; ++i) {
const vec4 light_pos_r = lights[i].pos_r;
const vec3 light_color = lights[i].color.rgb;
//rand01_state = fract((pos.x + pos.y + pos.z)/100.) + uv.x + uv.y + fract(pc.t) + i;
//rand01_state += fract(fract(pc.t) + i + (light_pos_r.x + light_pos_r.y + light_pos_r.z)/1000.);
// Find random point on a sphere
// TODO proper BRDF importance sampling and correct random point distribution
vec3 rnd = normalize(vec3(rand01(), rand01(), rand01())*2.-1.);