diff --git a/app-proto/inversive-display/src/main.rs b/app-proto/inversive-display/src/main.rs index d2bc742..c19e8ab 100644 --- a/app-proto/inversive-display/src/main.rs +++ b/app-proto/inversive-display/src/main.rs @@ -72,7 +72,7 @@ fn main() { sycamore::render(|| { let ctrl_x = create_signal(0.0); let ctrl_y = create_signal(0.0); - let opacity = create_signal(0.6); + let opacity = create_signal(0.5); let layer_threshold = create_signal(0.0); let display = create_node_ref(); @@ -123,6 +123,33 @@ fn main() { const float focal_slope = 0.3; const vec3 light_dir = normalize(vec3(2., 2., 1.)); + // --- sRGB --- + + // map colors from RGB space to sRGB space, as specified in the + // sRGB standard (IEC 61966-2-1:1999) + // + // https://www.color.org/sRGB.pdf + // https://www.color.org/chardata/rgb/srgb.xalter + // + // in RGB space, color value is proportional to light intensity, + // so linear color-vector interpolation corresponds to physical + // light mixing. in sRGB space, the color encoding used by many + // monitors, we use more of the value interval to represent low + // intensities, and less of the interval to represent high + // intensities. this improves color quantization + + float sRGB(float t) { + if (t <= 0.0031308) { + return 12.92*t; + } else { + return 1.055*pow(t, 5./12.) - 0.055; + } + } + + vec3 sRGB(vec3 color) { + return vec3(sRGB(color.r), sRGB(color.g), sRGB(color.b)); + } + // --- inversive geometry --- struct vecInv { @@ -203,8 +230,8 @@ fn main() { // initialize two spheres vecInv v0 = sphere(vec3(0.5, 0.5, -5. + ctrl.x), 1.); vecInv v1 = sphere(vec3(-0.5, -0.5, -5. + ctrl.y), 1.); - vec3 color0 = vec3(1.0, 0.5, 0.0); - vec3 color1 = vec3(0.0, 0.5, 1.0); + vec3 color0 = vec3(1., 0.214, 0.); + vec3 color1 = vec3(0., 0.214, 1.); // cast rays through the spheres vec2 u0 = sphere_cast(v0, dir); @@ -236,7 +263,7 @@ fn main() { color = mix(color, frag_color.rgb, frag_color.a); } } - outColor = vec4(color, 1.); + outColor = vec4(sRGB(color), 1.); } "##, );