0027607: Visualization - Implement adaptive screen space sampling in path tracing
[occt.git] / src / Shaders / RaytraceRender.fs
1 out vec4 OutColor;
2
3 // Seed for random number generator (generated on CPU).
4 uniform int uFrameRndSeed;
5
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;
10
11 #ifndef ADAPTIVE_SAMPLING
12   //! Weight of current frame related to accumulated samples.
13   uniform float uSampleWeight;
14
15   //! Input accumulated image.
16   uniform sampler2D uAccumTexture;
17 #endif
18
19 //! Maximum radiance that can be added to the pixel. Decreases noise
20 //! level, but introduces some bias.
21 #define MAX_RADIANCE vec3 (25.f)
22
23 // =======================================================================
24 // function : main
25 // purpose  :
26 // =======================================================================
27 void main (void)
28 {
29   SeedRand (uFrameRndSeed, uWinSizeX, uBlockedRngEnabled == 0 ? 1 : 16);
30
31 #ifndef PATH_TRACING
32
33   SRay aRay = GenerateRay (vPixel);
34
35 #else
36
37   ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);
38
39 #ifdef ADAPTIVE_SAMPLING
40
41   ivec2 aTileXY = imageLoad (uOffsetImage, ivec2 (aFragCoord.x / BLOCK_SIZE,
42                                                   aFragCoord.y / BLOCK_SIZE)).xy;
43
44   ivec2 aRealBlockSize = ivec2 (min (uWinSizeX - aTileXY.x, BLOCK_SIZE),
45                                 min (uWinSizeY - aTileXY.y, BLOCK_SIZE));
46
47   aFragCoord.x = aTileXY.x + (aFragCoord.x % aRealBlockSize.x);
48   aFragCoord.y = aTileXY.y + (aFragCoord.y % aRealBlockSize.y);
49
50 #endif // ADAPTIVE_SAMPLING
51
52   vec2 aPnt = vec2 (aFragCoord.x + RandFloat(),
53                     aFragCoord.y + RandFloat());
54
55   SRay aRay = GenerateRay (aPnt / vec2 (uWinSizeX, uWinSizeY));
56
57 #endif // PATH_TRACING
58
59   vec3 aInvDirect = InverseDirection (aRay.Direct);
60
61 #ifdef PATH_TRACING
62
63   vec4 aColor = PathTrace (aRay, aInvDirect);
64
65   if (any (isnan (aColor.rgb)))
66   {
67     aColor.rgb = ZERO;
68   }
69
70   aColor.rgb = min (aColor.rgb, MAX_RADIANCE);
71
72 #ifdef ADAPTIVE_SAMPLING
73
74   // accumulate RGB color and depth
75   imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
76                                        2 * aFragCoord.y + 0), aColor.r);
77   imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,
78                                        2 * aFragCoord.y + 0), aColor.g);
79   imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,
80                                        2 * aFragCoord.y + 1), aColor.b);
81   imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
82                                        2 * aFragCoord.y + 1), aColor.w);
83
84   // accumulate number of samples
85   float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
86                                                           2 * aFragCoord.y + 1), 1.0);
87
88   if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only
89   {
90     imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
91                                          2 * aFragCoord.y + 0), dot (LUMA, aColor.rgb));
92   }
93
94   discard; // fragment should not be written to frame buffer
95
96 #else
97
98   OutColor = mix (texture2D (uAccumTexture, vPixel), aColor, uSampleWeight);
99
100 #endif // ADAPTIVE_SAMPLING
101
102 #else
103
104   OutColor = clamp (Radiance (aRay, aInvDirect), 0.f, 1.f);
105
106 #endif // PATH_TRACING
107 }