Ray-caster: sort fragments while shading

This commit is contained in:
Aaron Fenyes 2024-08-28 14:37:29 -07:00
parent e80adf831d
commit 4afc82034b

View File

@ -138,16 +138,34 @@ void main() {
const int SPHERE_MAX_INTERNAL = 6; const int SPHERE_MAX_INTERNAL = 6;
vec2 depth_pairs [SPHERE_MAX_INTERNAL]; vec2 depth_pairs [SPHERE_MAX_INTERNAL];
taggedFrag frags [2*SPHERE_MAX_INTERNAL]; taggedFrag frags [2*SPHERE_MAX_INTERNAL];
int frag_cnt = 0; int layer_cnt = 0;
for (int i = 0; i < sphere_cnt; ++i) { for (int id = 0; id < sphere_cnt; ++id) {
vec2 hit_depths = sphere_cast(sphere_list[i], dir); // find out where the ray hits the sphere
if (hit_depths[0] > 0.) { vec2 hit_depths = sphere_cast(sphere_list[id], dir);
frags[frag_cnt] = sphere_shading(sphere_list[i], hit_depths[0] * dir, color_list[i], i);
++frag_cnt; // insertion-sort the fragments we hit into the fragment list
for (int side = 0; side < 2; ++side) {
if (hit_depths[side] > 0.) {
for (int layer = layer_cnt; layer >= 0; --layer) {
if (layer < 1 || frags[layer-1].pt.z >= -hit_depths[side]) {
// we're not as close to the screen as the fragment
// before the empty slot, so insert here
frags[layer] = sphere_shading(
sphere_list[id],
hit_depths[side] * dir,
color_list[id],
id
);
break;
} else {
// we're closer to the screen than the fragment before
// the empty slot, so move that fragment into the empty
// slot
frags[layer] = frags[layer-1];
}
}
++layer_cnt;
} }
if (hit_depths[1] > 0.) {
frags[frag_cnt] = sphere_shading(sphere_list[i], hit_depths[1] * dir, color_list[i], i);
++frag_cnt;
} }
} }
@ -156,29 +174,16 @@ void main() {
if (debug_mode) { if (debug_mode) {
// at the bottom of the screen, show the color scale instead of the // at the bottom of the screen, show the color scale instead of the
// layer count // layer count
if (gl_FragCoord.y < 10.) frag_cnt = int(8. * gl_FragCoord.x / resolution.x); if (gl_FragCoord.y < 10.) layer_cnt = int(8. * gl_FragCoord.x / resolution.x);
// convert number to color // convert number to color
ivec3 bits = frag_cnt / ivec3(1, 2, 4); ivec3 bits = layer_cnt / ivec3(1, 2, 4);
outColor = vec4(mod(vec3(bits), 2.), 1.); outColor = vec4(mod(vec3(bits), 2.), 1.);
return; return;
} }
// sort the fragments by depth, using an insertion sort
for (int take = 1; take < frag_cnt; ++take) {
taggedFrag pulled = frags[take];
for (int put = take; put >= 0; --put) {
if (put < 1 || frags[put-1].pt.z >= pulled.pt.z) {
frags[put] = pulled;
break;
} else {
frags[put] = frags[put-1];
}
}
}
// highlight intersections and cusps // highlight intersections and cusps
for (int i = frag_cnt-1; i >= 1; --i) { for (int i = layer_cnt-1; i >= 1; --i) {
// intersections // intersections
taggedFrag frag0 = frags[i]; taggedFrag frag0 = frags[i];
taggedFrag frag1 = frags[i-1]; taggedFrag frag1 = frags[i-1];
@ -201,7 +206,7 @@ void main() {
// composite the sphere fragments // composite the sphere fragments
vec3 color = vec3(0.); vec3 color = vec3(0.);
for (int i = frag_cnt-1; i >= layer_threshold; --i) { for (int i = layer_cnt-1; i >= layer_threshold; --i) {
if (frags[i].pt.z < 0.) { if (frags[i].pt.z < 0.) {
vec4 frag_color = frags[i].color; vec4 frag_color = frags[i].color;
color = mix(color, frag_color.rgb, frag_color.a); color = mix(color, frag_color.rgb, frag_color.a);