rtx: implement more of that solid angle sampling

also tweak tonemapping and exposure a bit
This commit is contained in:
Ivan Avdeev 2021-12-28 22:54:17 -08:00
parent 74e9401e56
commit 14176f147f
2 changed files with 99 additions and 30 deletions

View File

@ -56,11 +56,20 @@ void main() {
return;
}
/* if (pix.y < res.y / 3) { */
/* imageStore(dest, pix, vec4(pow(float(pix.x) / res.x, 2.2))); return; */
/* } else if (pix.y < res.y * 2 / 3) { */
/* imageStore(dest, pix, vec4(float(pix.x) / res.x)); return; */
/* } else { */
/* imageStore(dest, pix, vec4(sqrt(float(pix.x) / res.x))); return; */
/* } */
const vec4 base_color = imageLoad(src_base_color, pix);
const float material_index = imageLoad(src_diffuse_gi, pix).a;
//imageStore(dest, pix, vec4(aces_tonemap(base_color.rgb), 0.)); return;
//imageStore(dest, pix, vec4((base_color.rgb), 0.)); return;
//imageStore(dest, pix, vec4((imageLoad(src_diffuse_gi, pix).rgb), 0.)); return;
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_diffuse_gi, pix).rgb), 0.)); return;
//imageStore(dest, pix, vec4(aces_tonemap(imageLoad(src_specular, pix).rgb), 0.)); return;
@ -128,10 +137,26 @@ void main() {
// HACK: exposure
// TODO: should be dynamic based on previous frames brightness
colour *= 4.;
#if 0
if (pix.x >= res.x / 2) {
colour *= 8.;
}
#else
colour *= .25;
#endif
//colour = aces_tonemap(colour);
colour = reinhard02(colour, vec3(400.));
colour = aces_tonemap(colour);
//colour = reinhard02(colour, vec3(400.));
//colour = reinhard02(colour, vec3(1.));
#if 0
if (pix.x < res.x / 2) {
#endif
//colour *= .25;
colour = pow(colour, vec3(1. / 2.2));
#if 0
}
#endif
imageStore(dest, pix, vec4(colour, 0.));
//imageStore(dest, pix, imageLoad(src_diffuse_gi, pix));

View File

@ -150,9 +150,21 @@ void sampleSurfaceTriangle(
void sampleEmissiveSurface(vec3 throughput, vec3 view_dir, MaterialProperties material, SampleContext ctx, uint ekusok_index, out vec3 out_diffuse, out vec3 out_specular) {
const EmissiveKusok ek = lights.kusochki[ekusok_index];
const uint emissive_kusok_index = lights.kusochki[ekusok_index].kusok_index;
if (emissive_kusok_index == uint(payload_opaque.kusok_index))
return;
out_diffuse = out_specular = vec3(0.);
const Kusok kusok = kusochki[emissive_kusok_index];
// TODO streamline matrices layouts
const mat4x3 to_world = mat4x3(
vec3(ek.tx_row_x.x, ek.tx_row_y.x, ek.tx_row_z.x),
vec3(ek.tx_row_x.y, ek.tx_row_y.y, ek.tx_row_z.y),
vec3(ek.tx_row_x.z, ek.tx_row_y.z, ek.tx_row_z.z),
vec3(ek.tx_row_x.w, ek.tx_row_y.w, ek.tx_row_z.w)
);
const mat4x3 to_shading = ctx.world_to_shading * mat4(
vec4(ek.tx_row_x.x, ek.tx_row_y.x, ek.tx_row_z.x, 0),
vec4(ek.tx_row_x.y, ek.tx_row_y.y, ek.tx_row_z.y, 0),
@ -160,24 +172,13 @@ void sampleEmissiveSurface(vec3 throughput, vec3 view_dir, MaterialProperties ma
vec4(ek.tx_row_x.w, ek.tx_row_y.w, ek.tx_row_z.w, 1)
);
const mat4x3 emissive_transform = mat4x3(
vec3(ek.tx_row_x.x, ek.tx_row_y.x, ek.tx_row_z.x),
vec3(ek.tx_row_x.y, ek.tx_row_y.y, ek.tx_row_z.y),
vec3(ek.tx_row_x.z, ek.tx_row_y.z, ek.tx_row_z.z),
vec3(ek.tx_row_x.w, ek.tx_row_y.w, ek.tx_row_z.w)
);
if (emissive_kusok_index == uint(payload_opaque.kusok_index))
return;
// Taken from Ray Tracing Gems II, ch.47, p.776, listing 47-2
// Picking a triangle is taken from Ray Tracing Gems II, ch.47, p.776, listing 47-2
int selected = -1;
float selected_contrib = 0.;
float total_contrib = 0.;
float eps1 = rand01();
solid_angle_polygon_t poly_angle;
solid_angle_polygon_t selected_angle;
vec4 selected_plane;
for (uint i = 0; i < kusok.triangles; ++i) {
const uint first_index_offset = kusok.index_offset + i * 3;
const uint vi1 = uint(indices[first_index_offset+0]) + kusok.vertex_offset;
@ -186,16 +187,20 @@ void sampleEmissiveSurface(vec3 throughput, vec3 view_dir, MaterialProperties ma
// Transform to shading space
vec3 v[MAX_POLYGON_VERTEX_COUNT];
v[0] = to_shading * vec4(vertices[vi1].pos, 1.);
v[1] = to_shading * vec4(vertices[vi2].pos, 1.);
v[2] = to_shading * vec4(vertices[vi3].pos, 1.);
v[0] = to_world * vec4(vertices[vi1].pos, 1.);
v[1] = to_world * vec4(vertices[vi2].pos, 1.);
v[2] = to_world * vec4(vertices[vi3].pos, 1.);
// TODO cull by normal
// Clip
const uint vertex_count = clip_polygon(3, v);
/* const uint vertex_count = clip_polygon(3, v); */
/* if (vertex_count == 0) */
/* continue; */
// poly_angle
poly_angle = prepare_solid_angle_polygon_sampling(vertex_count, v, payload_opaque.hit_pos_t.xyz);
const float tri_contrib = poly_angle.solid_angle;
const solid_angle_polygon_t sap = prepare_solid_angle_polygon_sampling(3, v, payload_opaque.hit_pos_t.xyz);
const float tri_contrib = sap.solid_angle;
if (tri_contrib <= 0.)
continue;
@ -203,25 +208,64 @@ void sampleEmissiveSurface(vec3 throughput, vec3 view_dir, MaterialProperties ma
const float tau = total_contrib / (total_contrib + tri_contrib);
total_contrib += tri_contrib;
#if 0
if (false) {
#else
if (eps1 < tau) {
#endif
eps1 /= tau;
} else {
selected = int(i);
selected_contrib = tri_contrib;
eps1 = (eps1 - tau) / (1. - tau);
selected_angle = sap;
selected_plane.xyz = cross(v[1] - v[0], v[2] - v[0]);
selected_plane.w = -dot(v[0], selected_plane.xyz);
}
#define MAX_BELOW_ONE .99999 // FIXME what's the correct way to do this
eps1 = clamp(eps1, 0., MAX_BELOW_ONE); // Numerical stability (?)
}
if (selected >= 0) {
sampleSurfaceTriangle(throughput * ek.emissive, view_dir, material, emissive_transform, selected, kusok.index_offset, kusok.vertex_offset, emissive_kusok_index, out_diffuse, out_specular);
if (selected < 0 || selected_angle.solid_angle <= 0.)
return;
const float tri_factor = total_contrib / selected_contrib;
out_diffuse *= tri_factor;
out_specular *= tri_factor;
//sampleSurfaceTriangle(throughput * ek.emissive, view_dir, material, emissive_transform, selected, kusok.index_offset, kusok.vertex_offset, emissive_kusok_index, out_diffuse, out_specular);
vec2 rnd = vec2(rand01(), rand01());
//const vec3 light_dir = normalize(inverse(mat3(ctx.world_to_shading)) * sample_solid_angle_polygon(poly_angle, rnd));
const vec3 light_dir = sample_solid_angle_polygon(selected_angle, rnd);
vec3 tri_diffuse = vec3(0.), tri_specular = vec3(0.);
#if 1
evalSplitBRDF(payload_opaque.normal, light_dir, view_dir, material, tri_diffuse, tri_specular);
tri_diffuse *= throughput * ek.emissive;
tri_specular *= throughput * ek.emissive;
#else
tri_diffuse = vec3(selected_angle.solid_angle);
#endif
#if 1
vec3 combined = tri_diffuse + tri_specular;
if (dot(combined,combined) > color_culling_threshold) {
const float dist = -dot(vec4(payload_opaque.hit_pos_t.xyz, 1.f), selected_plane) / dot(light_dir, selected_plane.xyz);
if (!shadowed(payload_opaque.hit_pos_t.xyz, light_dir, dist)) {
const float tri_factor = total_contrib; // selected_angle.solid_angle;
out_diffuse += tri_diffuse * tri_factor;
out_specular += tri_specular * tri_factor;
}
} else {
#ifdef DEBUG_LIGHT_CULLING
return vec3(1., 1., 0.) * color_factor;
#else
return;
#endif
}
#else
//const float tri_factor = total_contrib / selected_angle.solid_angle;
out_diffuse += tri_diffuse * tri_factor;
out_specular += tri_specular * tri_factor;
#endif
}
void sampleEmissiveSurfaces(vec3 throughput, vec3 view_dir, MaterialProperties material, uint cluster_index, inout vec3 diffuse, inout vec3 specular) {
@ -230,7 +274,7 @@ void sampleEmissiveSurfaces(vec3 throughput, vec3 view_dir, MaterialProperties m
const uint num_emissive_kusochki = uint(light_grid.clusters[cluster_index].num_emissive_surfaces);
float sampling_light_scale = 1.;
#if 1
#if 0
const uint max_lights_per_frame = 4;
uint begin_i = 0, end_i = num_emissive_kusochki;
if (end_i > max_lights_per_frame) {