#version 450 layout(location = 0) in vec2 coords; layout(location = 0) out vec4 outColor; layout(push_constant) uniform p_constants_t { uint frame; uint test; float time; float targetNits; }; vec3 nitsToPq(vec3 nits) { vec3 y = clamp(nits / 10000.0, vec3(0.0), vec3(1.0)); const float c1 = 0.8359375; const float c2 = 18.8515625; const float c3 = 18.6875; const float m1 = 0.1593017578125; const float m2 = 78.84375; vec3 num = c1 + c2 * pow(y, vec3(m1)); vec3 den = 1.0 + c3 * pow(y, vec3(m1)); vec3 n = pow(num / den, vec3(m2)); return n; } vec3 pqToNits(vec3 pq) { const float c1 = 0.8359375; const float c2 = 18.8515625; const float c3 = 18.6875; const float oo_m1 = 1.0 / 0.1593017578125; const float oo_m2 = 1.0 / 78.84375; vec3 num = max(pow(pq, vec3(oo_m2)) - c1, vec3(0.0)); vec3 den = c2 - c3 * pow(pq, vec3(oo_m2)); return 10000.0 * pow(num / den, vec3(oo_m1)); } float gold_noise(vec2 xy, float seed) { const float PHI = 1.61803398874989484820459; return fract(tan(distance(xy*PHI, xy)*seed)*xy.x); } float positive_mod(float flX, float flPeriod) { float flVal = mod( flX, flPeriod ); return ( flVal < 0 ) ? flVal + flPeriod : abs( flVal ); // fabs fixes -0 } vec3 hsv_to_rgb(vec3 hsv) { if ( abs( hsv.y ) < 0.0000001 ) { return vec3( hsv.z ) ; } float flHue = positive_mod( hsv.x, 1.f ); flHue *= 6.f; int i = int(floor(flHue)); // integer part float f = fract(flHue); // fractional part float p = hsv.z * ( 1.f - hsv.y ); float q = hsv.z * ( 1.f - hsv.y * f ); float t = hsv.z * ( 1.f - hsv.y * ( 1.f - f ) ); switch(i) { case 0: return vec3( hsv.z, t, p ); break; case 1: return vec3( q, hsv.z, p ); break; case 2: return vec3( p, hsv.z, t ); break; case 3: return vec3( p, q, hsv.z ); break; case 4: return vec3( t, p, hsv.z ); break; case 5: return vec3( hsv.z, p, q ); break; } return vec3( 0 ); } void main() { outColor = vec4(0.0, 0.0, 0.0, 1.0); int nextTest = 0; if (test == nextTest++) { const vec3 start = vec3(0.0); const vec3 end = vec3(targetNits); vec3 color = mix(start, end, coords.x); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { const vec3 start = vec3(0.0); const vec3 end = vec3(targetNits); vec3 color = mix(start, end, coords.x); if (coords.y < 1.0 / 3.0) color.gb = vec2(0.0); else if (coords.y < 2.0 / 3.0) color.rb = vec2(0.0); else color.rg = vec2(0.0); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { const vec3 start = vec3(0.0); const vec3 end = vec3(hsv_to_rgb(vec3(coords.y, 1.0, 1.0)) * targetNits); vec3 color = mix(start, end, coords.x); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { const vec3 start = vec3(0.0); const vec3 end = vec3(targetNits); vec3 color = mix(start, end, coords.x); if (coords.y < 1.0 / 3.0) color.gb = vec2(0.0); else if (coords.y < 2.0 / 3.0) color.rb = vec2(0.0); else color.rg = vec2(0.0); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { vec3 color = vec3(0.0); if ((int(gl_FragCoord.x) & 1) == 0) color = vec3(targetNits); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { vec3 color = vec3(0.0); if ((int(gl_FragCoord.y) & 1) == 0) color = vec3(targetNits); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { vec3 color = vec3(0.0); if ((int(gl_FragCoord.x) & 1) == 0 && (int(gl_FragCoord.y) & 1) == 0) color = vec3(targetNits); outColor = vec4(nitsToPq(color), 1.0); } else if (test == nextTest++) { const vec3 barycentrics = vec3(1.0 - coords.x - coords.y, coords.x, coords.y) * targetNits; outColor = vec4(nitsToPq(barycentrics), 1.0); } else if (test == nextTest++) { float value = ((frame & 1) == 0) ? targetNits : 0.0; outColor = vec4(nitsToPq(vec3(value)), 1.0); } else if (test == nextTest++) { float value = ((frame & 1) == 0) ? targetNits : 0.0; outColor = vec4(nitsToPq(vec3(value, 0, 0)), 1.0); } else if (test == nextTest++) { float value = ((frame & 1) == 0) ? targetNits : 0.0; outColor = vec4(nitsToPq(vec3(0, value, 0)), 1.0); } else if (test == nextTest++) { float value = ((frame & 1) == 0) ? targetNits : 0.0; outColor = vec4(nitsToPq(vec3(0, 0, value)), 1.0); } else if (test == nextTest++) { const float seed = fract(time); vec3 value = vec3(gold_noise(gl_FragCoord.xy, seed + 0.2)) * targetNits; outColor = vec4(nitsToPq(value), 1.0); } else if (test == nextTest++) { const float seed = fract(time); vec3 value = vec3( gold_noise(gl_FragCoord.xy, seed + 0.1), gold_noise(gl_FragCoord.xy, seed + 0.2), gold_noise(gl_FragCoord.xy, seed + 0.3)) * targetNits; outColor = vec4(nitsToPq(value), 1.0); } }