diff --git a/app-proto/inversive-display/src/inversive.frag b/app-proto/inversive-display/src/inversive.frag index da2f415..c469edc 100644 --- a/app-proto/inversive-display/src/inversive.frag +++ b/app-proto/inversive-display/src/inversive.frag @@ -138,16 +138,34 @@ void main() { const int SPHERE_MAX_INTERNAL = 6; vec2 depth_pairs [SPHERE_MAX_INTERNAL]; taggedFrag frags [2*SPHERE_MAX_INTERNAL]; - int frag_cnt = 0; - for (int i = 0; i < sphere_cnt; ++i) { - vec2 hit_depths = sphere_cast(sphere_list[i], dir); - if (hit_depths[0] > 0.) { - frags[frag_cnt] = sphere_shading(sphere_list[i], hit_depths[0] * dir, color_list[i], i); - ++frag_cnt; - } - if (hit_depths[1] > 0.) { - frags[frag_cnt] = sphere_shading(sphere_list[i], hit_depths[1] * dir, color_list[i], i); - ++frag_cnt; + int layer_cnt = 0; + for (int id = 0; id < sphere_cnt; ++id) { + // find out where the ray hits the sphere + vec2 hit_depths = sphere_cast(sphere_list[id], dir); + + // 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; + } } } @@ -156,29 +174,16 @@ void main() { if (debug_mode) { // at the bottom of the screen, show the color scale instead of the // 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 - ivec3 bits = frag_cnt / ivec3(1, 2, 4); + ivec3 bits = layer_cnt / ivec3(1, 2, 4); outColor = vec4(mod(vec3(bits), 2.), 1.); 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 - for (int i = frag_cnt-1; i >= 1; --i) { + for (int i = layer_cnt-1; i >= 1; --i) { // intersections taggedFrag frag0 = frags[i]; taggedFrag frag1 = frags[i-1]; @@ -201,7 +206,7 @@ void main() { // composite the sphere fragments 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.) { vec4 frag_color = frags[i].color; color = mix(color, frag_color.rgb, frag_color.a);