[2972] | 1 | #include "../shaderenv.h"
|
---|
| 2 |
|
---|
| 3 |
|
---|
[2974] | 4 | struct frag
|
---|
[2972] | 5 | {
|
---|
| 6 | // normalized screen position
|
---|
[2974] | 7 | float2 texCoord: TEXCOORD0;
|
---|
[2973] | 8 |
|
---|
| 9 | float2 lt: TEXCOORD1; // left top
|
---|
| 10 | float2 rb: TEXCOORD2; // right bottom
|
---|
| 11 | float2 rt: TEXCOORD3; // right top
|
---|
| 12 | float2 lb: TEXCOORD4; // left bottom
|
---|
[2972] | 13 | };
|
---|
| 14 |
|
---|
| 15 |
|
---|
[2973] | 16 | struct pixel
|
---|
[2972] | 17 | {
|
---|
[2973] | 18 | float4 col: COLOR0;
|
---|
| 19 | };
|
---|
[2972] | 20 |
|
---|
[3017] | 21 |
|
---|
[3010] | 22 | /** Does the first downsampling step and on the same time calculates the
|
---|
| 23 | intensity.
|
---|
| 24 | */
|
---|
[2974] | 25 | float4 GreyScaleDownSample(frag IN,
|
---|
[3010] | 26 | uniform sampler2D colors,
|
---|
| 27 | uniform float2 downSampleOffs[4]
|
---|
[2974] | 28 | ): COLOR
|
---|
[2972] | 29 | {
|
---|
| 30 |
|
---|
| 31 | // Compute the average of the 4 necessary samples
|
---|
[2974] | 32 | float average = .0f;
|
---|
| 33 | float maximum = .0f;
|
---|
[2972] | 34 |
|
---|
[3149] | 35 | // the rgb-to-luminance weightings
|
---|
[2972] | 36 | const float3 w = float3(0.299f, 0.587f, 0.114f);
|
---|
[3148] | 37 | //const float3 w = float3(0.2125f, 0.7154f, 0.0721f);
|
---|
[2972] | 38 |
|
---|
[3010] | 39 | float4 color;
|
---|
[2973] | 40 |
|
---|
[2972] | 41 | for (int i = 0; i < 4; ++ i)
|
---|
| 42 | {
|
---|
[3010] | 43 | color = tex2D(colors, downSampleOffs[i]);
|
---|
[2973] | 44 | const float intensity = dot(cols[i].rgb, w);
|
---|
[2972] | 45 |
|
---|
[2973] | 46 | maximum = max(maximum, intensity);
|
---|
[2974] | 47 | average += log(1e-5f + intensity);
|
---|
[2972] | 48 | }
|
---|
| 49 |
|
---|
[3010] | 50 | average *= 0.25f;
|
---|
[2972] | 51 |
|
---|
| 52 | // Output the luminance to the render target
|
---|
[3010] | 53 | return float4(average, maximum, 0.0f, 1.0f);
|
---|
[2972] | 54 | }
|
---|
[2973] | 55 |
|
---|
[2972] | 56 |
|
---|
[3010] | 57 | /** Used for downsampling the tone map parameters (average loglum, maximum)
|
---|
| 58 | to the next lower level. This has to be applied until there is only
|
---|
| 59 | a 1x1 texture which holds the required numbers.
|
---|
| 60 | */
|
---|
| 61 | float4 DownSampleForToneMapping(frag IN,
|
---|
| 62 | uniform sampler2D colors,
|
---|
| 63 | uniform float2 downSampleOffs[4]): COLOR
|
---|
| 64 | {
|
---|
| 65 | float average = .0f;
|
---|
| 66 | float maximum = .0f;
|
---|
| 67 |
|
---|
| 68 | float4 color;
|
---|
| 69 |
|
---|
| 70 | for (int i = 0; i < 4; ++ i)
|
---|
| 71 | {
|
---|
| 72 | color = tex2D(colors, downSampleOffs[i]);
|
---|
| 73 |
|
---|
| 74 | maximum = max(maximum, color.y);
|
---|
| 75 | average += color.x;
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | average *= 1.0f / (float)NUM_DOWNSAMPLES;
|
---|
| 79 |
|
---|
| 80 | return float4(average, maximum, 0.0f, 1.0f);
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 |
|
---|
| 84 |
|
---|
[2974] | 85 | pixel ToneMap(frag IN,
|
---|
[2973] | 86 | uniform sampler2D colors,
|
---|
| 87 | uniform float imageKey,
|
---|
| 88 | uniform float whiteLum,
|
---|
| 89 | uniform float middleGrey)
|
---|
| 90 | {
|
---|
| 91 | pixel OUT;
|
---|
[3008] | 92 |
|
---|
[2974] | 93 | float4 color = tex2D(colors, IN.texCoord);
|
---|
[2973] | 94 |
|
---|
| 95 | const float pixLum = 0.2125f * color.x + 0.7154f * color.y + 0.0721f * color.z;
|
---|
| 96 |
|
---|
[2974] | 97 | // obtain new image key from highest mipmap level
|
---|
[3103] | 98 | float logLumScaled = tex2Dlod(colors, float4(.5f, .5f, 0, MAX_LOD_LEVEL)).w;
|
---|
[2975] | 99 | float logLum = logLumScaled * LOGLUM_RANGE + MINLOGLUM;
|
---|
[2974] | 100 |
|
---|
[3198] | 101 | float newImageKey = max(exp(logLum), 1e-3f);
|
---|
[2974] | 102 |
|
---|
[2973] | 103 | // adjust to middle gray
|
---|
[2974] | 104 | const float lum = middleGrey * pixLum / newImageKey;
|
---|
[2973] | 105 | // map to range and calc burnout
|
---|
| 106 | const float scaleLum = lum * (1.0f + lum / whiteLum * whiteLum) / (1.0f + lum);
|
---|
| 107 |
|
---|
| 108 | OUT.col = color * scaleLum / pixLum;
|
---|
| 109 | OUT.col.w = color.w;
|
---|
| 110 |
|
---|
| 111 | return OUT;
|
---|
[2991] | 112 | }
|
---|
| 113 |
|
---|
| 114 |
|
---|
| 115 | pixel CalcAvgLogLum(frag IN, uniform sampler2D colors)
|
---|
| 116 | {
|
---|
| 117 | ////////////
|
---|
| 118 | //-- write out logaritmic luminance for tone mapping
|
---|
| 119 |
|
---|
| 120 | pixel OUT;
|
---|
| 121 |
|
---|
[3103] | 122 | const float4 color = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0));
|
---|
[2992] | 123 | OUT.col = color;
|
---|
| 124 |
|
---|
[2991] | 125 | // the old loglum is stored in the hightest mipmap-level
|
---|
| 126 | float oldLogLum = tex2Dlod(colors, float4(IN.texCoord.xy, 0, MAX_LOD_LEVEL)).w;
|
---|
| 127 |
|
---|
| 128 | // the intensity weights
|
---|
| 129 | const float3 w = float3(0.299f, 0.587f, 0.114f);
|
---|
| 130 |
|
---|
| 131 | float lum = dot(color.rgb, w);
|
---|
[3132] | 132 | float logLum = log(max(1e-3f, lum));
|
---|
[2991] | 133 |
|
---|
| 134 | float logLumOffset = MINLOGLUM * INV_LOGLUM_RANGE;
|
---|
| 135 | float logLumScaled = logLum * INV_LOGLUM_RANGE - logLumOffset;
|
---|
| 136 |
|
---|
[3149] | 137 |
|
---|
| 138 | /////////////
|
---|
| 139 | //-- exponential smoothing of the tone mapping over time
|
---|
| 140 |
|
---|
[3137] | 141 | const float expFactor = 1e-2f;
|
---|
[3149] | 142 |
|
---|
[3132] | 143 | if (oldLogLum > 1e-3f) // check if loglum from last frame too small (=> tm too bright)
|
---|
[3125] | 144 | OUT.col.w = lerp(oldLogLum, logLumScaled, expFactor);
|
---|
[2991] | 145 | else
|
---|
[2992] | 146 | OUT.col.w = logLumScaled;
|
---|
| 147 |
|
---|
[3008] | 148 | return OUT;
|
---|
[3103] | 149 | }
|
---|