mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0030476: Visualization, Path Tracing - Adaptive Screen Sampling leads to unstable results
OpenGl_View::runPathtrace() has been extended with alternative multi-pass Adaptive Screen Sampling mode, not relying on atomic floating point operations. Although atomic operations on floats allows single-pass rendering, such operations leads to instability in case of different calculation order. Atomic float operations are also currently supported only by single GPU vendor. Fixed GLSL compilation on Intel drivers (follow ARB_shader_image_load_store specs rather than EXT_shader_image_load_store). Graphic3d_RenderingParams::AdaptiveScreenSamplingAtomic option has been added to activate 1-pass Adaptive Screen Sampling mode when supported by hardware. vfps command has been extended with -duration argument allowing to limit command execution time. vactivate command has been extended with -noUpdate argument.
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
#extension GL_ARB_shader_image_size : enable
|
||||
|
||||
//! OpenGL image used for accumulating rendering result.
|
||||
volatile restrict layout(size1x32) uniform image2D uRenderImage;
|
||||
volatile restrict layout(r32f) uniform image2D uRenderImage;
|
||||
|
||||
//! OpenGL image storing variance of sampled pixels blocks.
|
||||
volatile restrict layout(size1x32) uniform iimage2D uVarianceImage;
|
||||
volatile restrict layout(r32i) uniform iimage2D uVarianceImage;
|
||||
|
||||
//! Scale factor used to quantize visual error (float) into signed integer.
|
||||
uniform float uVarianceScaleFactor;
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
#extension GL_ARB_shader_image_load_store : require
|
||||
#endif
|
||||
#ifdef ADAPTIVE_SAMPLING_ATOMIC
|
||||
#extension GL_NV_shader_atomic_float : require
|
||||
#endif
|
||||
|
||||
@@ -97,10 +99,15 @@ uniform float uSceneEpsilon;
|
||||
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
//! OpenGL image used for accumulating rendering result.
|
||||
volatile restrict layout(size1x32) uniform image2D uRenderImage;
|
||||
volatile restrict layout(r32f) uniform image2D uRenderImage;
|
||||
|
||||
#ifdef ADAPTIVE_SAMPLING_ATOMIC
|
||||
//! OpenGL image storing offsets of sampled pixels blocks.
|
||||
coherent restrict layout(size2x32) uniform iimage2D uOffsetImage;
|
||||
coherent restrict layout(rg32i) uniform iimage2D uOffsetImage;
|
||||
#else
|
||||
//! OpenGL image defining per-tile amount of samples.
|
||||
volatile restrict layout(r32i) uniform iimage2D uTilesImage;
|
||||
#endif
|
||||
|
||||
//! Screen space tile size.
|
||||
uniform ivec2 uTileSize;
|
||||
@@ -274,7 +281,7 @@ vec3 InverseDirection (in vec3 theInput)
|
||||
//=======================================================================
|
||||
vec4 BackgroundColor()
|
||||
{
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
#ifdef ADAPTIVE_SAMPLING_ATOMIC
|
||||
|
||||
ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);
|
||||
|
||||
|
@@ -20,6 +20,26 @@ uniform int uAccumSamples;
|
||||
//! Decreases noise level, but introduces some bias.
|
||||
uniform float uMaxRadiance = 50.f;
|
||||
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
//! Wrapper over imageLoad()+imageStore() having similar syntax as imageAtomicAdd().
|
||||
//! Modifies one component of 3Wx2H uRenderImage:
|
||||
//! |RGL| Red, Green, Luminance
|
||||
//! |SBH| Samples, Blue, Hit time transformed into OpenGL NDC space
|
||||
//! Returns previous value of the component.
|
||||
float addRenderImageComp (in ivec2 theFrag, in ivec2 theComp, in float theVal)
|
||||
{
|
||||
ivec2 aCoord = ivec2 (3 * theFrag.x + theComp.x,
|
||||
2 * theFrag.y + theComp.y);
|
||||
#ifdef ADAPTIVE_SAMPLING_ATOMIC
|
||||
return imageAtomicAdd (uRenderImage, aCoord, theVal);
|
||||
#else
|
||||
float aVal = imageLoad (uRenderImage, aCoord).x;
|
||||
imageStore (uRenderImage, aCoord, vec4 (aVal + theVal));
|
||||
return aVal;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// =======================================================================
|
||||
// function : main
|
||||
// purpose :
|
||||
@@ -38,6 +58,7 @@ void main (void)
|
||||
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
|
||||
#ifdef ADAPTIVE_SAMPLING_ATOMIC
|
||||
ivec2 aTileXY = imageLoad (uOffsetImage, aFragCoord / uTileSize).xy * uTileSize;
|
||||
if (aTileXY.x < 0) { discard; }
|
||||
|
||||
@@ -46,6 +67,13 @@ void main (void)
|
||||
|
||||
aFragCoord.x = aTileXY.x + (aFragCoord.x % aRealBlockSize.x);
|
||||
aFragCoord.y = aTileXY.y + (aFragCoord.y % aRealBlockSize.y);
|
||||
#else
|
||||
int aNbTileSamples = imageAtomicAdd (uTilesImage, aFragCoord / uTileSize, int(-1));
|
||||
if (aNbTileSamples <= 0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ADAPTIVE_SAMPLING
|
||||
|
||||
@@ -66,9 +94,7 @@ void main (void)
|
||||
|
||||
#else
|
||||
|
||||
float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
|
||||
2 * aFragCoord.y + 1), 1.0);
|
||||
|
||||
float aNbSamples = addRenderImageComp (aFragCoord, ivec2 (0, 1), 1.0);
|
||||
vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));
|
||||
|
||||
#endif
|
||||
@@ -83,19 +109,14 @@ void main (void)
|
||||
#ifdef ADAPTIVE_SAMPLING
|
||||
|
||||
// accumulate RGB color and depth
|
||||
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
|
||||
2 * aFragCoord.y + 0), aColor.r);
|
||||
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,
|
||||
2 * aFragCoord.y + 0), aColor.g);
|
||||
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,
|
||||
2 * aFragCoord.y + 1), aColor.b);
|
||||
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
|
||||
2 * aFragCoord.y + 1), aColor.w);
|
||||
addRenderImageComp (aFragCoord, ivec2 (0, 0), aColor.r);
|
||||
addRenderImageComp (aFragCoord, ivec2 (1, 0), aColor.g);
|
||||
addRenderImageComp (aFragCoord, ivec2 (1, 1), aColor.b);
|
||||
addRenderImageComp (aFragCoord, ivec2 (2, 1), aColor.w);
|
||||
|
||||
if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only
|
||||
{
|
||||
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
|
||||
2 * aFragCoord.y + 0), dot (LUMA, aColor.rgb));
|
||||
addRenderImageComp (aFragCoord, ivec2 (2, 0), dot (LUMA, aColor.rgb));
|
||||
}
|
||||
|
||||
#else
|
||||
|
@@ -8,10 +8,10 @@ static const char Shaders_Display_fs[] =
|
||||
" #extension GL_ARB_shader_image_size : enable\n"
|
||||
"\n"
|
||||
" //! OpenGL image used for accumulating rendering result.\n"
|
||||
" volatile restrict layout(size1x32) uniform image2D uRenderImage;\n"
|
||||
" volatile restrict layout(r32f) uniform image2D uRenderImage;\n"
|
||||
"\n"
|
||||
" //! OpenGL image storing variance of sampled pixels blocks.\n"
|
||||
" volatile restrict layout(size1x32) uniform iimage2D uVarianceImage;\n"
|
||||
" volatile restrict layout(r32i) uniform iimage2D uVarianceImage;\n"
|
||||
"\n"
|
||||
" //! Scale factor used to quantize visual error (float) into signed integer.\n"
|
||||
" uniform float uVarianceScaleFactor;\n"
|
||||
|
@@ -3,6 +3,8 @@
|
||||
static const char Shaders_RaytraceBase_fs[] =
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
" #extension GL_ARB_shader_image_load_store : require\n"
|
||||
"#endif\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING_ATOMIC\n"
|
||||
" #extension GL_NV_shader_atomic_float : require\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
@@ -100,10 +102,15 @@ static const char Shaders_RaytraceBase_fs[] =
|
||||
"\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
" //! OpenGL image used for accumulating rendering result.\n"
|
||||
" volatile restrict layout(size1x32) uniform image2D uRenderImage;\n"
|
||||
" volatile restrict layout(r32f) uniform image2D uRenderImage;\n"
|
||||
"\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING_ATOMIC\n"
|
||||
" //! OpenGL image storing offsets of sampled pixels blocks.\n"
|
||||
" coherent restrict layout(size2x32) uniform iimage2D uOffsetImage;\n"
|
||||
" coherent restrict layout(rg32i) uniform iimage2D uOffsetImage;\n"
|
||||
"#else\n"
|
||||
" //! OpenGL image defining per-tile amount of samples.\n"
|
||||
" volatile restrict layout(r32i) uniform iimage2D uTilesImage;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" //! Screen space tile size.\n"
|
||||
" uniform ivec2 uTileSize;\n"
|
||||
@@ -277,7 +284,7 @@ static const char Shaders_RaytraceBase_fs[] =
|
||||
"//=======================================================================\n"
|
||||
"vec4 BackgroundColor()\n"
|
||||
"{\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING_ATOMIC\n"
|
||||
"\n"
|
||||
" ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);\n"
|
||||
"\n"
|
||||
|
@@ -23,6 +23,26 @@ static const char Shaders_RaytraceRender_fs[] =
|
||||
"//! Decreases noise level, but introduces some bias.\n"
|
||||
"uniform float uMaxRadiance = 50.f;\n"
|
||||
"\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
"//! Wrapper over imageLoad()+imageStore() having similar syntax as imageAtomicAdd().\n"
|
||||
"//! Modifies one component of 3Wx2H uRenderImage:\n"
|
||||
"//! |RGL| Red, Green, Luminance\n"
|
||||
"//! |SBH| Samples, Blue, Hit time transformed into OpenGL NDC space\n"
|
||||
"//! Returns previous value of the component.\n"
|
||||
"float addRenderImageComp (in ivec2 theFrag, in ivec2 theComp, in float theVal)\n"
|
||||
"{\n"
|
||||
" ivec2 aCoord = ivec2 (3 * theFrag.x + theComp.x,\n"
|
||||
" 2 * theFrag.y + theComp.y);\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING_ATOMIC\n"
|
||||
" return imageAtomicAdd (uRenderImage, aCoord, theVal);\n"
|
||||
"#else\n"
|
||||
" float aVal = imageLoad (uRenderImage, aCoord).x;\n"
|
||||
" imageStore (uRenderImage, aCoord, vec4 (aVal + theVal));\n"
|
||||
" return aVal;\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// =======================================================================\n"
|
||||
"// function : main\n"
|
||||
"// purpose :\n"
|
||||
@@ -41,6 +61,7 @@ static const char Shaders_RaytraceRender_fs[] =
|
||||
"\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
"\n"
|
||||
"#ifdef ADAPTIVE_SAMPLING_ATOMIC\n"
|
||||
" ivec2 aTileXY = imageLoad (uOffsetImage, aFragCoord / uTileSize).xy * uTileSize;\n"
|
||||
" if (aTileXY.x < 0) { discard; }\n"
|
||||
"\n"
|
||||
@@ -49,6 +70,13 @@ static const char Shaders_RaytraceRender_fs[] =
|
||||
"\n"
|
||||
" aFragCoord.x = aTileXY.x + (aFragCoord.x % aRealBlockSize.x);\n"
|
||||
" aFragCoord.y = aTileXY.y + (aFragCoord.y % aRealBlockSize.y);\n"
|
||||
"#else\n"
|
||||
" int aNbTileSamples = imageAtomicAdd (uTilesImage, aFragCoord / uTileSize, int(-1));\n"
|
||||
" if (aNbTileSamples <= 0)\n"
|
||||
" {\n"
|
||||
" discard;\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#endif // ADAPTIVE_SAMPLING\n"
|
||||
"\n"
|
||||
@@ -69,9 +97,7 @@ static const char Shaders_RaytraceRender_fs[] =
|
||||
"\n"
|
||||
"#else\n"
|
||||
"\n"
|
||||
" float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
|
||||
" 2 * aFragCoord.y + 1), 1.0);\n"
|
||||
"\n"
|
||||
" float aNbSamples = addRenderImageComp (aFragCoord, ivec2 (0, 1), 1.0);\n"
|
||||
" vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
@@ -86,19 +112,14 @@ static const char Shaders_RaytraceRender_fs[] =
|
||||
"#ifdef ADAPTIVE_SAMPLING\n"
|
||||
"\n"
|
||||
" // accumulate RGB color and depth\n"
|
||||
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
|
||||
" 2 * aFragCoord.y + 0), aColor.r);\n"
|
||||
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,\n"
|
||||
" 2 * aFragCoord.y + 0), aColor.g);\n"
|
||||
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 1,\n"
|
||||
" 2 * aFragCoord.y + 1), aColor.b);\n"
|
||||
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,\n"
|
||||
" 2 * aFragCoord.y + 1), aColor.w);\n"
|
||||
" addRenderImageComp (aFragCoord, ivec2 (0, 0), aColor.r);\n"
|
||||
" addRenderImageComp (aFragCoord, ivec2 (1, 0), aColor.g);\n"
|
||||
" addRenderImageComp (aFragCoord, ivec2 (1, 1), aColor.b);\n"
|
||||
" addRenderImageComp (aFragCoord, ivec2 (2, 1), aColor.w);\n"
|
||||
"\n"
|
||||
" if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only\n"
|
||||
" {\n"
|
||||
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,\n"
|
||||
" 2 * aFragCoord.y + 0), dot (LUMA, aColor.rgb));\n"
|
||||
" addRenderImageComp (aFragCoord, ivec2 (2, 0), dot (LUMA, aColor.rgb));\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
"#else\n"
|
||||
|
Reference in New Issue
Block a user