fc73a202 |
1 | out vec4 OutColor; |
2 | |
3a9b5dc8 |
3 | // Seed for random number generator (generated on CPU). |
189f85a3 |
4 | uniform int uFrameRndSeed; |
5 | |
3a9b5dc8 |
6 | //! Enables/disables using of single RNG seed for 16x16 image |
7 | //! blocks. Increases performance up to 4x, but the noise has |
8 | //! become structured. Can be used fo final rendering. |
9 | uniform int uBlockedRngEnabled; |
189f85a3 |
10 | |
4eaaf9d8 |
11 | //! Number of previously rendered frames (used in non-ISS mode). |
12 | uniform int uAccumSamples; |
13 | |
3a9b5dc8 |
14 | #ifndef ADAPTIVE_SAMPLING |
383c6c9f |
15 | //! Input image with previously accumulated samples. |
3a9b5dc8 |
16 | uniform sampler2D uAccumTexture; |
17 | #endif |
8c820969 |
18 | |
b09447ed |
19 | //! Maximum radiance that can be added to the pixel. |
20 | //! Decreases noise level, but introduces some bias. |
93cdaa76 |
21 | uniform float uMaxRadiance; |
8c820969 |
22 | |
e084dbbc |
23 | #ifdef ADAPTIVE_SAMPLING |
24 | //! Wrapper over imageLoad()+imageStore() having similar syntax as imageAtomicAdd(). |
25 | //! Modifies one component of 3Wx2H uRenderImage: |
26 | //! |RGL| Red, Green, Luminance |
27 | //! |SBH| Samples, Blue, Hit time transformed into OpenGL NDC space |
28 | //! Returns previous value of the component. |
29 | float addRenderImageComp (in ivec2 theFrag, in ivec2 theComp, in float theVal) |
30 | { |
31 | ivec2 aCoord = ivec2 (3 * theFrag.x + theComp.x, |
32 | 2 * theFrag.y + theComp.y); |
33 | #ifdef ADAPTIVE_SAMPLING_ATOMIC |
34 | return imageAtomicAdd (uRenderImage, aCoord, theVal); |
35 | #else |
36 | float aVal = imageLoad (uRenderImage, aCoord).x; |
37 | imageStore (uRenderImage, aCoord, vec4 (aVal + theVal)); |
38 | return aVal; |
39 | #endif |
40 | } |
41 | #endif |
42 | |
fc73a202 |
43 | // ======================================================================= |
44 | // function : main |
45 | // purpose : |
46 | // ======================================================================= |
47 | void main (void) |
48 | { |
3a9b5dc8 |
49 | SeedRand (uFrameRndSeed, uWinSizeX, uBlockedRngEnabled == 0 ? 1 : 16); |
50 | |
189f85a3 |
51 | #ifndef PATH_TRACING |
3a9b5dc8 |
52 | |
fc73a202 |
53 | SRay aRay = GenerateRay (vPixel); |
3a9b5dc8 |
54 | |
189f85a3 |
55 | #else |
189f85a3 |
56 | |
3a9b5dc8 |
57 | ivec2 aFragCoord = ivec2 (gl_FragCoord.xy); |
189f85a3 |
58 | |
3a9b5dc8 |
59 | #ifdef ADAPTIVE_SAMPLING |
189f85a3 |
60 | |
e084dbbc |
61 | #ifdef ADAPTIVE_SAMPLING_ATOMIC |
66d1cdc6 |
62 | ivec2 aTileXY = imageLoad (uOffsetImage, aFragCoord / uTileSize).xy * uTileSize; |
63 | if (aTileXY.x < 0) { discard; } |
189f85a3 |
64 | |
66d1cdc6 |
65 | ivec2 aRealBlockSize = ivec2 (min (uWinSizeX - aTileXY.x, uTileSize.x), |
66 | min (uWinSizeY - aTileXY.y, uTileSize.y)); |
3a9b5dc8 |
67 | |
68 | aFragCoord.x = aTileXY.x + (aFragCoord.x % aRealBlockSize.x); |
69 | aFragCoord.y = aTileXY.y + (aFragCoord.y % aRealBlockSize.y); |
e084dbbc |
70 | #else |
71 | int aNbTileSamples = imageAtomicAdd (uTilesImage, aFragCoord / uTileSize, int(-1)); |
72 | if (aNbTileSamples <= 0) |
73 | { |
74 | discard; |
75 | } |
76 | #endif |
3a9b5dc8 |
77 | |
78 | #endif // ADAPTIVE_SAMPLING |
79 | |
93cdaa76 |
80 | vec2 aPnt = vec2 (float(aFragCoord.x) + RandFloat(), |
81 | float(aFragCoord.y) + RandFloat()); |
3a9b5dc8 |
82 | |
83 | SRay aRay = GenerateRay (aPnt / vec2 (uWinSizeX, uWinSizeY)); |
84 | |
85 | #endif // PATH_TRACING |
86 | |
87 | vec3 aInvDirect = InverseDirection (aRay.Direct); |
fc73a202 |
88 | |
189f85a3 |
89 | #ifdef PATH_TRACING |
3a9b5dc8 |
90 | |
4eaaf9d8 |
91 | #ifndef ADAPTIVE_SAMPLING |
4eaaf9d8 |
92 | vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples); |
4eaaf9d8 |
93 | #else |
e084dbbc |
94 | float aNbSamples = addRenderImageComp (aFragCoord, ivec2 (0, 1), 1.0); |
4eaaf9d8 |
95 | vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples)); |
4eaaf9d8 |
96 | #endif |
189f85a3 |
97 | |
3a9b5dc8 |
98 | if (any (isnan (aColor.rgb))) |
189f85a3 |
99 | { |
8c820969 |
100 | aColor.rgb = ZERO; |
189f85a3 |
101 | } |
b09447ed |
102 | aColor.rgb = min (aColor.rgb, vec3 (uMaxRadiance)); |
189f85a3 |
103 | |
3a9b5dc8 |
104 | #ifdef ADAPTIVE_SAMPLING |
105 | |
106 | // accumulate RGB color and depth |
e084dbbc |
107 | addRenderImageComp (aFragCoord, ivec2 (0, 0), aColor.r); |
108 | addRenderImageComp (aFragCoord, ivec2 (1, 0), aColor.g); |
109 | addRenderImageComp (aFragCoord, ivec2 (1, 1), aColor.b); |
110 | addRenderImageComp (aFragCoord, ivec2 (2, 1), aColor.w); |
3a9b5dc8 |
111 | if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only |
112 | { |
e084dbbc |
113 | addRenderImageComp (aFragCoord, ivec2 (2, 0), dot (LUMA, aColor.rgb)); |
3a9b5dc8 |
114 | } |
115 | |
3a9b5dc8 |
116 | #else |
117 | |
383c6c9f |
118 | if (uAccumSamples == 0) |
be86ba90 |
119 | { |
120 | OutColor = aColor; |
121 | } |
122 | else |
123 | { |
93cdaa76 |
124 | OutColor = mix (texture (uAccumTexture, vPixel), aColor, 1.0 / float(uAccumSamples + 1)); |
be86ba90 |
125 | } |
3a9b5dc8 |
126 | |
127 | #endif // ADAPTIVE_SAMPLING |
128 | |
189f85a3 |
129 | #else |
3a9b5dc8 |
130 | |
fc73a202 |
131 | OutColor = clamp (Radiance (aRay, aInvDirect), 0.f, 1.f); |
3a9b5dc8 |
132 | |
133 | #endif // PATH_TRACING |
ee5befae |
134 | } |