3 // Seed for random number generator (generated on CPU).
4 uniform int uFrameRndSeed;
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;
11 //! Number of previously rendered frames (used in non-ISS mode).
12 uniform int uAccumSamples;
14 #ifndef ADAPTIVE_SAMPLING
15 //! Input image with previously accumulated samples.
16 uniform sampler2D uAccumTexture;
19 //! Maximum radiance that can be added to the pixel.
20 //! Decreases noise level, but introduces some bias.
21 uniform float uMaxRadiance = 50.f;
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)
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);
36 float aVal = imageLoad (uRenderImage, aCoord).x;
37 imageStore (uRenderImage, aCoord, vec4 (aVal + theVal));
43 // =======================================================================
46 // =======================================================================
49 SeedRand (uFrameRndSeed, uWinSizeX, uBlockedRngEnabled == 0 ? 1 : 16);
53 SRay aRay = GenerateRay (vPixel);
57 ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);
59 #ifdef ADAPTIVE_SAMPLING
61 #ifdef ADAPTIVE_SAMPLING_ATOMIC
62 ivec2 aTileXY = imageLoad (uOffsetImage, aFragCoord / uTileSize).xy * uTileSize;
63 if (aTileXY.x < 0) { discard; }
65 ivec2 aRealBlockSize = ivec2 (min (uWinSizeX - aTileXY.x, uTileSize.x),
66 min (uWinSizeY - aTileXY.y, uTileSize.y));
68 aFragCoord.x = aTileXY.x + (aFragCoord.x % aRealBlockSize.x);
69 aFragCoord.y = aTileXY.y + (aFragCoord.y % aRealBlockSize.y);
71 int aNbTileSamples = imageAtomicAdd (uTilesImage, aFragCoord / uTileSize, int(-1));
72 if (aNbTileSamples <= 0)
78 #endif // ADAPTIVE_SAMPLING
80 vec2 aPnt = vec2 (aFragCoord.x + RandFloat(),
81 aFragCoord.y + RandFloat());
83 SRay aRay = GenerateRay (aPnt / vec2 (uWinSizeX, uWinSizeY));
85 #endif // PATH_TRACING
87 vec3 aInvDirect = InverseDirection (aRay.Direct);
91 #ifndef ADAPTIVE_SAMPLING
93 vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples);
97 float aNbSamples = addRenderImageComp (aFragCoord, ivec2 (0, 1), 1.0);
98 vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));
102 if (any (isnan (aColor.rgb)))
107 aColor.rgb = min (aColor.rgb, vec3 (uMaxRadiance));
109 #ifdef ADAPTIVE_SAMPLING
111 // accumulate RGB color and depth
112 addRenderImageComp (aFragCoord, ivec2 (0, 0), aColor.r);
113 addRenderImageComp (aFragCoord, ivec2 (1, 0), aColor.g);
114 addRenderImageComp (aFragCoord, ivec2 (1, 1), aColor.b);
115 addRenderImageComp (aFragCoord, ivec2 (2, 1), aColor.w);
117 if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only
119 addRenderImageComp (aFragCoord, ivec2 (2, 0), dot (LUMA, aColor.rgb));
124 if (uAccumSamples == 0)
130 OutColor = mix (texture (uAccumTexture, vPixel), aColor, 1.f / (uAccumSamples + 1));
133 #endif // ADAPTIVE_SAMPLING
137 OutColor = clamp (Radiance (aRay, aInvDirect), 0.f, 1.f);
139 #endif // PATH_TRACING