| 
									
										
										
										
											2025-01-22 16:18:30 +01:00
										 |  |  | vec3 uncharted2Tonemap(const vec3 x) { | 
					
						
							|  |  |  | 	const float A = 0.15; | 
					
						
							|  |  |  | 	const float B = 0.50; | 
					
						
							|  |  |  | 	const float C = 0.10; | 
					
						
							|  |  |  | 	const float D = 0.20; | 
					
						
							|  |  |  | 	const float E = 0.02; | 
					
						
							|  |  |  | 	const float F = 0.30; | 
					
						
							|  |  |  | 	return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec3 tonemapUncharted2(const vec3 color) { | 
					
						
							|  |  |  | 	const float W = 11.2; | 
					
						
							|  |  |  | 	const float exposureBias = 2.0; | 
					
						
							|  |  |  | 	vec3 curr = uncharted2Tonemap(exposureBias * color); | 
					
						
							|  |  |  | 	vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W)); | 
					
						
							|  |  |  | 	return curr * whiteScale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Based on Filmic Tonemapping Operators http://filmicgames.com/archives/75 | 
					
						
							|  |  |  | vec3 tonemapFilmic(const vec3 color) { | 
					
						
							|  |  |  | 	vec3 x = max(vec3(0.0), color - 0.004); | 
					
						
							|  |  |  | 	return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ | 
					
						
							|  |  |  | vec3 acesFilm(const vec3 x) { | 
					
						
							|  |  |  |     const float a = 2.51; | 
					
						
							|  |  |  |     const float b = 0.03; | 
					
						
							|  |  |  |     const float c = 2.43; | 
					
						
							|  |  |  |     const float d = 0.59; | 
					
						
							|  |  |  |     const float e = 0.14; | 
					
						
							|  |  |  |     return clamp((x * (a * x + b)) / (x * (c * x + d ) + e), 0.0, 1.0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | vec3 tonemapReinhard(const vec3 color) { | 
					
						
							|  |  |  | 	return color / (color + vec3(1.0)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-04-05 08:12:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Blender AgX Implementation  | 
					
						
							|  |  |  | // Troy Sobotka https://github.com/sobotka/AgX | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AGX Simple | 
					
						
							|  |  |  | vec3 tonemapAgXSimple(vec3 x) { | 
					
						
							| 
									
										
										
										
											2025-04-05 13:11:56 +00:00
										 |  |  | 	// TODO CORRECT AND OPTIMIZE | 
					
						
							|  |  |  |     x = max(x, vec3(0.0)); | 
					
						
							|  |  |  |     float exposure = 0.6; | 
					
						
							|  |  |  |     x *= exposure; | 
					
						
							|  |  |  |     const vec3 AgX_A = vec3(0.92, 0.92, 0.72); | 
					
						
							|  |  |  |     const vec3 AgX_B = vec3(0.24, 0.24, 0.36); | 
					
						
							|  |  |  |     const vec3 AgX_C = vec3(0.92, 0.92, 0.72); | 
					
						
							|  |  |  |     const vec3 AgX_D = vec3(0.24, 0.24, 0.36); | 
					
						
							|  |  |  |     const vec3 AgX_E = vec3(0.08, 0.08, 0.12); | 
					
						
							|  |  |  |     const vec3 AgX_F = vec3(0.0); | 
					
						
							|  |  |  |     vec3 result = (x * (AgX_A * x + AgX_B)) / (x * (AgX_C * x + AgX_D) + AgX_E) + AgX_F; | 
					
						
							|  |  |  |     float luma = dot(result, vec3(0.2126, 0.7152, 0.0722)); | 
					
						
							|  |  |  |     result = mix(vec3(luma), result, 0.6); | 
					
						
							|  |  |  |     return clamp(result, vec3(0.0), vec3(1.0)); | 
					
						
							| 
									
										
										
										
											2025-04-05 08:12:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AGX Full Contrast Approx | 
					
						
							|  |  |  | vec3 agxDefaultContrastApprox(vec3 x) { | 
					
						
							|  |  |  |     vec3 x2 = x * x; | 
					
						
							|  |  |  |     vec3 x4 = x2 * x2; | 
					
						
							|  |  |  |     return + 15.5     * x4 * x2 | 
					
						
							|  |  |  |            - 40.14    * x4 * x | 
					
						
							|  |  |  |            + 31.96    * x4 | 
					
						
							|  |  |  |            - 6.868    * x2 * x | 
					
						
							|  |  |  |            + 0.4298   * x2 | 
					
						
							|  |  |  |            + 0.1191   * x | 
					
						
							|  |  |  |            - 0.00232; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | // AGX Full Look | 
					
						
							|  |  |  | vec3 agxLook(vec3 x, float strength) { | 
					
						
							|  |  |  |     const vec3 slope = vec3(1.0); | 
					
						
							|  |  |  |     const vec3 power = vec3(1.35); | 
					
						
							|  |  |  |     const vec3 sat = vec3(1.4); | 
					
						
							|  |  |  |     vec3 lw = vec3(0.2126, 0.7152, 0.0722); | 
					
						
							|  |  |  |     float luma = dot(x, lw); | 
					
						
							|  |  |  |     return pow(x * slope, power) * sat - (pow(luma * slope, power) * (sat - 1.0)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AGX Full | 
					
						
							|  |  |  | vec3 tonemapAgXFull(vec3 x) { | 
					
						
							|  |  |  |     // x *= 2.0 * (1.0/0.8); // Brightness scale to match Blender's default | 
					
						
							|  |  |  |     x = clamp(x, 0.0, 65504.0); | 
					
						
							|  |  |  |     x = log2(x + 1.0); | 
					
						
							|  |  |  |     x = agxDefaultContrastApprox(clamp(x * 0.5 - 10.5, -12.0, 12.0));     | 
					
						
							|  |  |  |     x = mix(x, agxLook(x, 0.5), 0.5); | 
					
						
							|  |  |  |     x = clamp(x, 0.0, 1.0); | 
					
						
							|  |  |  |     return pow(x, vec3(1.0/2.2));  | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-04-07 21:12:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Interleaved Gradient Noise (Pseudo-random, AKA Blue Noise style) | 
					
						
							|  |  |  | // Based on http://momentsingraphics.de/BlueNoise.html | 
					
						
							|  |  |  | float ditherBlueNoiseStyle(vec2 p) { | 
					
						
							|  |  |  |     return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5453123); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // White Noise Dithering | 
					
						
							|  |  |  | float ditherWhiteNoise(vec2 p) { | 
					
						
							|  |  |  |     return fract(sin(dot(p, vec2(12.9898, 4.1414))) * 43758.5453); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Ordered Dithering (4x4 Bayer Matrix) | 
					
						
							|  |  |  | float ditherOrderedBayer4x4(ivec2 p) { | 
					
						
							|  |  |  |     const float bayer[16] = float[16]( | 
					
						
							|  |  |  |          0.0,  8.0,  2.0, 10.0, | 
					
						
							|  |  |  |         12.0,  4.0, 14.0,  6.0, | 
					
						
							|  |  |  |          3.0, 11.0,  1.0,  9.0, | 
					
						
							|  |  |  |         15.0,  7.0, 13.0,  5.0 | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     int index = (p.x % 4) * 4 + (p.y % 4); | 
					
						
							|  |  |  |     return bayer[index] / 16.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Ordered Dithering (8x8 Bayer Matrix) | 
					
						
							|  |  |  | float ditherOrderedBayer8x8(ivec2 p) { | 
					
						
							|  |  |  |     const float bayer8x8[64] = float[64]( | 
					
						
							|  |  |  |          0.0, 32.0,  8.0, 40.0,  2.0, 34.0, 10.0, 42.0, | 
					
						
							|  |  |  |         48.0, 16.0, 56.0, 24.0, 50.0, 18.0, 58.0, 26.0, | 
					
						
							|  |  |  |         12.0, 44.0,  4.0, 36.0, 14.0, 46.0,  6.0, 38.0, | 
					
						
							|  |  |  |         60.0, 28.0, 52.0, 20.0, 62.0, 30.0, 54.0, 22.0, | 
					
						
							|  |  |  |          3.0, 35.0, 11.0, 43.0,  1.0, 33.0,  9.0, 41.0, | 
					
						
							|  |  |  |         51.0, 19.0, 59.0, 27.0, 49.0, 17.0, 57.0, 25.0, | 
					
						
							|  |  |  |         15.0, 47.0,  7.0, 39.0, 13.0, 45.0,  5.0, 37.0, | 
					
						
							|  |  |  |         63.0, 31.0, 55.0, 23.0, 61.0, 29.0, 53.0, 21.0 | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     int index = (p.x % 8) * 8 + (p.y % 8); | 
					
						
							|  |  |  |     return bayer8x8[index] / 64.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //vec3 applyDither(vec3 color, vec2 screenCoord) { | 
					
						
							|  |  |  | //    float quantizationLevels = 255.0; | 
					
						
							|  |  |  | //    float noise = randomDither(screenCoord); | 
					
						
							|  |  |  | //    float noiseOffset = (noise - 0.5) / quantizationLevels; | 
					
						
							|  |  |  | //    vec3 ditheredColor = color + noiseOffset; | 
					
						
							|  |  |  | //    return clamp(ditheredColor, 0.0, 1.0); | 
					
						
							|  |  |  | //} |