| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- <!--
- Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
- All rights reserved.
- Code licensed under the BSD License.
- http://www.anki3d.org/LICENSE
- -->
- <shaderProgram>
- <shaders>
- <shader type="comp">
- <inputs>
- <input name="INPUT_TEX_SIZE" type="uvec2" const="1"/>
- </inputs>
- <source><![CDATA[
- #define LOG_AVG 0
- #include "shaders/Common.glsl"
- #include "shaders/Tonemapping.glsl"
- const uint WORKGROUP_SIZE_X = 16u;
- const uint WORKGROUP_SIZE_Y = 16u;
- const uint WORKGROUP_SIZE = WORKGROUP_SIZE_X * WORKGROUP_SIZE_Y;
- layout(local_size_x = WORKGROUP_SIZE_X, local_size_y = WORKGROUP_SIZE_Y, local_size_z = 1) in;
- const uint PIXEL_READ_X = INPUT_TEX_SIZE.x / WORKGROUP_SIZE_X;
- const uint PIXEL_READ_Y = INPUT_TEX_SIZE.y / WORKGROUP_SIZE_Y;
- layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex;
- #define TONEMAPPING_RESOURCE_AS_BUFFER 1
- #include "shaders/TonemappingResources.glsl"
- shared float s_avgLum[WORKGROUP_SIZE];
- void main()
- {
- // Gather the log-average luminance of a tile
- float avgLum = 0.0;
- uint yStart = gl_LocalInvocationID.y * PIXEL_READ_Y;
- uint xStart = gl_LocalInvocationID.x * PIXEL_READ_X;
- for(uint y = 0; y < PIXEL_READ_Y; ++y)
- {
- for(uint x = 0; x < PIXEL_READ_X; ++x)
- {
- ivec2 uv = ivec2(xStart, yStart) + ivec2(x, y);
- vec3 color = texelFetch(u_tex, uv, 0).rgb;
- float lum = computeLuminance(color);
- #if LOG_AVG
- avgLum += log(max(EPSILON, lum));
- #else
- avgLum += lum;
- #endif
- }
- }
- s_avgLum[gl_LocalInvocationIndex] = avgLum;
- memoryBarrierShared();
- barrier();
- // Gather the results into one
- for(uint s = WORKGROUP_SIZE / 2u; s > 0u; s >>= 1u)
- {
- if(gl_LocalInvocationIndex < s)
- {
- s_avgLum[gl_LocalInvocationIndex] += s_avgLum[gl_LocalInvocationIndex + s];
- }
- memoryBarrierShared();
- barrier();
- }
- // Write the result
- if(gl_LocalInvocationIndex == 0)
- {
- #if LOG_AVG
- float crntLum = exp(s_avgLum[0] / float(INPUT_TEX_SIZE.x * INPUT_TEX_SIZE.y));
- #else
- float crntLum = s_avgLum[0] / float(INPUT_TEX_SIZE.x * INPUT_TEX_SIZE.y);
- #endif
- #if 1
- float prevLum = u_averageLuminance;
- // Lerp between previous and new L value
- const float INTERPOLATION_FACTOR = 0.05;
- float finalAvgLum = mix(prevLum, crntLum, INTERPOLATION_FACTOR);
- #else
- float finalAvgLum = crntLum;
- #endif
- // This is a workaround because sometimes the avg lum becomes nan
- finalAvgLum = clamp(finalAvgLum, EPSILON, FLT_MAX);
- u_averageLuminance = finalAvgLum;
- u_exposureThreshold0 = computeExposure(u_averageLuminance, 0.0);
- }
- }
- ]]></source>
- </shader>
- </shaders>
- </shaderProgram>
|