1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0028129: Visualization, Path Tracing - Improve interactivity in "steady" rendering mode

Re-basing the patch on current master.
This commit is contained in:
dbp 2017-01-26 12:56:13 +03:00 committed by apn
parent 952886f056
commit 4eaaf9d812
13 changed files with 278 additions and 96 deletions

View File

@ -62,6 +62,7 @@ public:
TwoSidedBsdfModels (Standard_False),
RadianceClampingValue (30.0),
RebuildRayTracingShaders (Standard_False),
NbRayTracingTiles (16 * 16),
// stereoscopic parameters
StereoMode (Graphic3d_StereoMode_QuadBuffer),
AnaglyphFilter (Anaglyph_RedCyan_Optimized),
@ -105,6 +106,7 @@ public:
Standard_Boolean TwoSidedBsdfModels; //!< forces path tracing to use two-sided versions of original one-sided scattering models
Standard_ShortReal RadianceClampingValue; //!< maximum radiance value used for clamping radiance estimation.
Standard_Boolean RebuildRayTracingShaders; //!< forces rebuilding ray tracing shaders at the next frame
Standard_Integer NbRayTracingTiles; //!< total number of screen tiles used in adaptive sampling mode (PT only)
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
Anaglyph AnaglyphFilter; //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default

View File

@ -150,36 +150,45 @@ void OpenGl_TileSampler::SetSize (const int theSizeX,
//=======================================================================
void OpenGl_TileSampler::Upload (const Handle(OpenGl_Context)& theContext,
const Handle(OpenGl_Texture)& theTexture,
bool theAdaptive)
const int theNbTilesX,
const int theNbTilesY,
const bool theAdaptive)
{
if (theTexture.IsNull())
{
return;
}
std::vector<GLint> aData (myTilesX * myTilesY * 2);
for (int aX = 0; aX < myTilesX; ++aX)
const int aNbTilesX = theAdaptive ? theNbTilesX : myTilesX;
const int aNbTilesY = theAdaptive ? theNbTilesY : myTilesY;
Standard_ASSERT_RAISE (aNbTilesX * aNbTilesY > 0,
"Error! Number of sampling tiles should be positive");
std::vector<GLint> aData (aNbTilesX * aNbTilesY * 2);
for (int aX = 0; aX < aNbTilesX; ++aX)
{
for (int aY = 0; aY < myTilesY; ++aY)
for (int aY = 0; aY < aNbTilesY; ++aY)
{
if (!theAdaptive)
{
aData[(aY * myTilesX + aX) * 2 + 0] = aX * TileSize();
aData[(aY * myTilesX + aX) * 2 + 1] = aY * TileSize();
aData[(aY * aNbTilesX + aX) * 2 + 0] = aX * TileSize();
aData[(aY * aNbTilesX + aX) * 2 + 1] = aY * TileSize();
}
else
{
Sample (aData[(aY * myTilesX + aX) * 2 + 0],
aData[(aY * myTilesX + aX) * 2 + 1]);
Sample (aData[(aY * aNbTilesX + aX) * 2 + 0],
aData[(aY * aNbTilesX + aX) * 2 + 1]);
}
}
}
theTexture->Bind (theContext);
theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, myTilesX, myTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
const GLenum anErr = theContext->core11fwd->glGetError();
if (anErr != GL_NO_ERROR)
theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, aNbTilesX, aNbTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
if (theContext->core11fwd->glGetError() != GL_NO_ERROR)
{
theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
"Error! Failed to upload tile offset map on the GPU");

View File

@ -22,7 +22,12 @@
#include <vector>
//! Tool object used for sampling screen tiles according to estimated pixel variance (used in path tracing engine).
//! To improve GPU thread coherency, render window is split into pixel blocks or tiles.
//! To improve GPU thread coherency, rendering window is split into pixel blocks or tiles. The important feature of
//! this approach is that it is possible to keep the same number of tiles for any screen resolution (e.g. 256 tiles
//! can be used for both 512 x 512 window and 1920 x 1080 window). So, a smaller number of tiles allows to increase
//! interactivity (FPS), but at the cost of higher per-frame variance ('noise'). On the contrary a larger number of
//! tiles decrease interactivity, but leads to lower per-frame variance. Note that the total time needed to produce
//! final final image is the same for both cases.
class OpenGl_TileSampler
{
public:
@ -76,7 +81,9 @@ public:
//! Uploads offsets of sampled tiles to the given OpenGL texture.
Standard_EXPORT void Upload (const Handle(OpenGl_Context)& theContext,
const Handle(OpenGl_Texture)& theTexture,
bool theAdaptive);
const int theNbTilesX,
const int theNbTilesY,
const bool theAdaptive);
protected:

View File

@ -711,6 +711,12 @@ protected: //! @name data types related to ray-tracing
//! Maximum radiance value used for clamping radiance estimation.
Standard_ShortReal RadianceClampingValue;
//! Number of tiles in X dimension (in adaptive sampling mode).
Standard_Integer NbTilesX;
//! Number of tiles in Y dimension (in adaptive sampling mode).
Standard_Integer NbTilesY;
//! Creates default compile-time ray-tracing parameters.
RaytracingParams()
: StackSize (THE_DEFAULT_STACK_SIZE),
@ -721,7 +727,9 @@ protected: //! @name data types related to ray-tracing
TwoSidedBsdfModels (Standard_False),
AdaptiveScreenSampling (Standard_False),
UseEnvMapForBackground (Standard_False),
RadianceClampingValue (30.0) { }
RadianceClampingValue (30.0),
NbTilesX (16),
NbTilesY (16) { }
};
//! Describes state of OpenGL structure.
@ -897,7 +905,9 @@ protected: //! @name methods related to ray-tracing
const Handle(OpenGl_Context)& theGlContext);
//! Runs path tracing (global illumination) kernel.
Standard_Boolean runPathtrace (const Graphic3d_Camera::Projection theProjection,
Standard_Boolean runPathtrace (const Standard_Integer theSizeX,
const Standard_Integer theSizeY,
Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theReadDrawFbo,
const Handle(OpenGl_Context)& theGlContext);

View File

@ -1359,11 +1359,21 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
}
}
Standard_Integer aNbTilesX = 8;
Standard_Integer aNbTilesY = 8;
for (Standard_Integer anIdx = 0; aNbTilesX * aNbTilesY < myRenderParams.NbRayTracingTiles; ++anIdx)
{
(anIdx % 2 == 0 ? aNbTilesX : aNbTilesY) <<= 1;
}
if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces
|| myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows
|| myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination
|| myRenderParams.TwoSidedBsdfModels != myRaytraceParameters.TwoSidedBsdfModels
|| myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
|| myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures
|| aNbTilesX != myRaytraceParameters.NbTilesX
|| aNbTilesY != myRaytraceParameters.NbTilesY)
{
myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
@ -1371,6 +1381,18 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
myRaytraceParameters.TwoSidedBsdfModels = myRenderParams.TwoSidedBsdfModels;
myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
#ifdef RAY_TRACE_PRINT_INFO
if (aNbTilesX != myRaytraceParameters.NbTilesX
|| aNbTilesY != myRaytraceParameters.NbTilesY)
{
std::cout << "Number of tiles X: " << aNbTilesX << "\n";
std::cout << "Number of tiles Y: " << aNbTilesY << "\n";
}
#endif
myRaytraceParameters.NbTilesX = aNbTilesX;
myRaytraceParameters.NbTilesY = aNbTilesY;
aToRebuildShaders = Standard_True;
}
@ -1848,26 +1870,43 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
return Standard_True;
}
if (myRaytraceParameters.AdaptiveScreenSampling)
{
const Standard_Integer aSizeX = std::max (myRaytraceParameters.NbTilesX * 64, theSizeX);
const Standard_Integer aSizeY = std::max (myRaytraceParameters.NbTilesY * 64, theSizeY);
myRaytraceFBO1[0]->InitLazy (theGlContext, aSizeX, aSizeY, GL_RGBA32F, myFboDepthFormat);
myRaytraceFBO2[0]->InitLazy (theGlContext, aSizeX, aSizeY, GL_RGBA32F, myFboDepthFormat);
if (myRaytraceFBO1[1]->IsValid()) // second FBO not needed
{
myRaytraceFBO1[1]->Release (theGlContext.operator->());
myRaytraceFBO2[1]->Release (theGlContext.operator->());
}
}
else // non-adaptive mode
{
if (myRaytraceFBO1[0]->GetSizeX() != theSizeX
|| myRaytraceFBO1[0]->GetSizeY() != theSizeY)
{
myAccumFrames = 0;
myAccumFrames = 0; // accumulation should be restarted
}
myRaytraceFBO1[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
myRaytraceFBO2[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
// Init second set of buffers for stereographic rendering.
// Init second set of buffers for stereographic rendering
if (myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
{
myRaytraceFBO1[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
myRaytraceFBO2[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
}
else
else if (myRaytraceFBO1[1]->IsValid()) // second FBO not needed
{
myRaytraceFBO1[1]->Release (theGlContext.operator->());
myRaytraceFBO2[1]->Release (theGlContext.operator->());
}
}
myTileSampler.SetSize (theSizeX, theSizeY);
@ -1883,6 +1922,8 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
if (myRaytraceOutputTexture[0]->SizeX() / 3 != theSizeX
|| myRaytraceOutputTexture[0]->SizeY() / 2 != theSizeY)
{
myAccumFrames = 0;
// Due to limitations of OpenGL image load-store extension
// atomic operations are supported only for single-channel
// images, so we define GL_R32F image. It is used as array
@ -2634,7 +2675,7 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
if (myRaytraceParameters.GlobalIllumination) // path tracing
{
aResult &= runPathtrace (theProjection, theReadDrawFbo, theGlContext);
aResult &= runPathtrace (theSizeX, theSizeY, theProjection, theReadDrawFbo, theGlContext);
}
else // Whitted-style ray-tracing
{
@ -2775,7 +2816,9 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer theSize
// function : runPathtrace
// purpose : Runs path tracing shader
// =======================================================================
Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection theProjection,
Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer theSizeX,
const Standard_Integer theSizeY,
const Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theReadDrawFbo,
const Handle(OpenGl_Context)& theGlContext)
{
@ -2793,13 +2836,12 @@ Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection
myTileSampler.Reset(); // reset tile sampler to its initial state
}
// We upload tile offset texture each 4 frames in order
// to minimize overhead of additional memory bandwidth.
// Adaptive sampling is starting after first 30 frames.
if (myAccumFrames % 4 == 0)
{
myTileSampler.Upload (theGlContext, myRaytraceTileOffsetsTexture, myAccumFrames > 30);
}
// Adaptive sampling is starting at the second frame
myTileSampler.Upload (theGlContext,
myRaytraceTileOffsetsTexture,
myRaytraceParameters.NbTilesX,
myRaytraceParameters.NbTilesY,
myAccumFrames > 0);
}
bindRaytraceTextures (theGlContext);
@ -2859,9 +2901,25 @@ Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection
glDisable (GL_DEPTH_TEST);
if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
{
glViewport (0,
0,
myTileSampler.TileSize() * myRaytraceParameters.NbTilesX,
myTileSampler.TileSize() * myRaytraceParameters.NbTilesY);
}
// Generate for the given RNG seed
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
{
glViewport (0,
0,
theSizeX,
theSizeY);
}
// Output accumulated path traced image
theGlContext->BindProgram (myOutImageProgram);

View File

@ -2,6 +2,8 @@
#extension GL_ARB_shader_image_load_store : require
#extension GL_ARB_shader_image_size : enable
//! OpenGL image used for accumulating rendering result.
volatile restrict layout(size1x32) uniform image2D uRenderImage;
@ -87,8 +89,9 @@ void main (void)
// calculate visual error
float anError = (aAverRad - aHalfRad) * (aAverRad - aHalfRad);
// accumulate visual error to current block
imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (anError * SCALE_FACTOR));
// accumulate visual error to current block; estimated error is written only
// after the first 40 samples and path length has reached 10 bounces or more
imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (mix (SCALE_FACTOR, anError * SCALE_FACTOR, aColor.w > 40.f)));
if (uDebugAdaptive == 0) // normal rendering
{
@ -96,7 +99,13 @@ void main (void)
}
else // showing number of samples
{
aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);
vec2 aRatio = vec2 (1.f, 1.f);
#ifdef GL_ARB_shader_image_size
aRatio = vec2 (imageSize (uRenderImage)) / vec2 (3.f * 512.f, 2.f * 512.f);
#endif
aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, sqrt (aRatio.x * aRatio.y) * aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);
}
#endif // ADAPTIVE_SAMPLING

View File

@ -12,9 +12,6 @@
#ifdef PATH_TRACING
//! Number of previously rendered frames.
uniform int uAccumSamples;
///////////////////////////////////////////////////////////////////////////////////////
// Specific data types
@ -700,17 +697,26 @@ vec3 IntersectLight (in SRay theRay, in int theDepth, in float theHitDistance, o
#define MATERIAL_FRESNEL(index) (18 * index + 16)
#define MATERIAL_ABSORPT(index) (18 * index + 17)
// Enables expiremental russian roulette sampling
//! Enables experimental russian roulette sampling path termination.
//! In most cases, it provides faster image convergence with minimal
//! bias, so it is enabled by default.
#define RUSSIAN_ROULETTE
//! Frame step to increase number of bounces
#define FRAME_STEP 5
//! Frame step to increase number of bounces. This mode is used
//! for interaction with the model, when path length is limited
//! for the first samples, and gradually increasing when camera
//! is stabilizing.
#ifdef ADAPTIVE_SAMPLING
#define FRAME_STEP 4
#else
#define FRAME_STEP 5
#endif
//=======================================================================
// function : PathTrace
// purpose : Calculates radiance along the given ray
//=======================================================================
vec4 PathTrace (in SRay theRay, in vec3 theInverse)
vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)
{
float aRaytraceDepth = MAXFLOAT;
@ -867,7 +873,8 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);
#endif
if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= uAccumSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))
// here, we additionally increase path length for non-diffuse bounces
if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= theNbSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))
{
aDepth = INVALID_BOUNCES; // terminate path
}

View File

@ -8,6 +8,9 @@ uniform int uFrameRndSeed;
//! become structured. Can be used fo final rendering.
uniform int uBlockedRngEnabled;
//! Number of previously rendered frames (used in non-ISS mode).
uniform int uAccumSamples;
#ifndef ADAPTIVE_SAMPLING
//! Input image with previously accumulated samples.
uniform sampler2D uAccumTexture;
@ -57,7 +60,18 @@ void main (void)
#ifdef PATH_TRACING
vec4 aColor = PathTrace (aRay, aInvDirect);
#ifndef ADAPTIVE_SAMPLING
vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples);
#else
float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
2 * aFragCoord.y + 1), 1.0);
vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));
#endif
if (any (isnan (aColor.rgb)))
{
@ -78,18 +92,12 @@ void main (void)
imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
2 * aFragCoord.y + 1), aColor.w);
// accumulate number of samples
float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
2 * aFragCoord.y + 1), 1.0);
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));
}
discard; // fragment should not be written to frame buffer
#else
if (uAccumSamples == 0)

View File

@ -5,6 +5,8 @@ static const char Shaders_Display_fs[] =
"\n"
" #extension GL_ARB_shader_image_load_store : require\n"
"\n"
" #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"
"\n"
@ -90,8 +92,9 @@ static const char Shaders_Display_fs[] =
" // calculate visual error\n"
" float anError = (aAverRad - aHalfRad) * (aAverRad - aHalfRad);\n"
"\n"
" // accumulate visual error to current block\n"
" imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (anError * SCALE_FACTOR));\n"
" // accumulate visual error to current block; estimated error is written only\n"
" // after the first 40 samples and path length has reached 10 bounces or more\n"
" imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (mix (SCALE_FACTOR, anError * SCALE_FACTOR, aColor.w > 40.f)));\n"
"\n"
" if (uDebugAdaptive == 0) // normal rendering\n"
" {\n"
@ -99,7 +102,13 @@ static const char Shaders_Display_fs[] =
" }\n"
" else // showing number of samples\n"
" {\n"
" aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);\n"
" vec2 aRatio = vec2 (1.f, 1.f);\n"
"\n"
"#ifdef GL_ARB_shader_image_size\n"
" aRatio = vec2 (imageSize (uRenderImage)) / vec2 (3.f * 512.f, 2.f * 512.f);\n"
"#endif\n"
"\n"
" aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, sqrt (aRatio.x * aRatio.y) * aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);\n"
" }\n"
"\n"
"#endif // ADAPTIVE_SAMPLING\n"

View File

@ -15,9 +15,6 @@ static const char Shaders_PathtraceBase_fs[] =
"\n"
"#ifdef PATH_TRACING\n"
"\n"
"//! Number of previously rendered frames.\n"
"uniform int uAccumSamples;\n"
"\n"
"///////////////////////////////////////////////////////////////////////////////////////\n"
"// Specific data types\n"
"\n"
@ -703,17 +700,26 @@ static const char Shaders_PathtraceBase_fs[] =
"#define MATERIAL_FRESNEL(index) (18 * index + 16)\n"
"#define MATERIAL_ABSORPT(index) (18 * index + 17)\n"
"\n"
"// Enables expiremental russian roulette sampling\n"
"//! Enables experimental russian roulette sampling path termination.\n"
"//! In most cases, it provides faster image convergence with minimal\n"
"//! bias, so it is enabled by default.\n"
"#define RUSSIAN_ROULETTE\n"
"\n"
"//! Frame step to increase number of bounces\n"
"#define FRAME_STEP 5\n"
"//! Frame step to increase number of bounces. This mode is used\n"
"//! for interaction with the model, when path length is limited\n"
"//! for the first samples, and gradually increasing when camera\n"
"//! is stabilizing.\n"
"#ifdef ADAPTIVE_SAMPLING\n"
" #define FRAME_STEP 4\n"
"#else\n"
" #define FRAME_STEP 5\n"
"#endif\n"
"\n"
"//=======================================================================\n"
"// function : PathTrace\n"
"// purpose : Calculates radiance along the given ray\n"
"//=======================================================================\n"
"vec4 PathTrace (in SRay theRay, in vec3 theInverse)\n"
"vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)\n"
"{\n"
" float aRaytraceDepth = MAXFLOAT;\n"
"\n"
@ -870,7 +876,8 @@ static const char Shaders_PathtraceBase_fs[] =
" aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);\n"
"#endif\n"
"\n"
" if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= uAccumSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))\n"
" // here, we additionally increase path length for non-diffuse bounces\n"
" if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= theNbSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))\n"
" {\n"
" aDepth = INVALID_BOUNCES; // terminate path\n"
" }\n"

View File

@ -11,6 +11,9 @@ static const char Shaders_RaytraceRender_fs[] =
"//! become structured. Can be used fo final rendering.\n"
"uniform int uBlockedRngEnabled;\n"
"\n"
"//! Number of previously rendered frames (used in non-ISS mode).\n"
"uniform int uAccumSamples;\n"
"\n"
"#ifndef ADAPTIVE_SAMPLING\n"
" //! Input image with previously accumulated samples.\n"
" uniform sampler2D uAccumTexture;\n"
@ -60,7 +63,18 @@ static const char Shaders_RaytraceRender_fs[] =
"\n"
"#ifdef PATH_TRACING\n"
"\n"
" vec4 aColor = PathTrace (aRay, aInvDirect);\n"
"#ifndef ADAPTIVE_SAMPLING\n"
"\n"
" vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples);\n"
"\n"
"#else\n"
"\n"
" float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
" 2 * aFragCoord.y + 1), 1.0);\n"
"\n"
" vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));\n"
"\n"
"#endif\n"
"\n"
" if (any (isnan (aColor.rgb)))\n"
" {\n"
@ -81,18 +95,12 @@ static const char Shaders_RaytraceRender_fs[] =
" imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,\n"
" 2 * aFragCoord.y + 1), aColor.w);\n"
"\n"
" // accumulate number of samples\n"
" float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
" 2 * aFragCoord.y + 1), 1.0);\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"
" }\n"
"\n"
" discard; // fragment should not be written to frame buffer\n"
"\n"
"#else\n"
"\n"
" if (uAccumSamples == 0)\n"

View File

@ -9076,6 +9076,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels ? "on" : "off") << "\n";
theDI << "max radiance: " << aParams.RadianceClampingValue << "\n";
theDI << "nb tiles (iss): " << aParams.NbRayTracingTiles << "\n";
theDI << "shadingModel: ";
switch (aView->ShadingModel())
{
@ -9364,6 +9365,32 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
}
aParams.ShowSamplingTiles = toEnable;
}
else if (aFlag == "-nbtiles")
{
if (toPrint)
{
theDI << aParams.NbRayTracingTiles << " ";
continue;
}
else if (++anArgIter >= theArgNb)
{
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
return 1;
}
const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
if (aNbTiles < 64)
{
std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
std::cerr << "Specify value in range [64, 1024].\n";
return 1;
}
else
{
aParams.NbRayTracingTiles = aNbTiles;
}
}
else if (aFlag == "-env")
{
if (toPrint)
@ -10939,6 +10966,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n '-iss on|off' Enables/disables adaptive screen sampling (PT mode)"
"\n '-issd on|off' Shows screen sampling distribution in ISS mode"
"\n '-maxrad > 0.0' Value used for clamping radiance estimation (PT mode)"
"\n '-nbtiles 64..1024' Specifies number of screen tiles in ISS mode"
"\n '-rebuildGlsl on|off' Rebuild Ray-Tracing GLSL programs (for debugging)"
"\n '-shadingModel model' Controls shading model from enumeration"
"\n color, flat, gouraud, phong"

View File

@ -0,0 +1,20 @@
puts "============"
puts "Visualization - Path Tracing, Ball sample (ISS mode)"
puts "============"
puts ""
cpulimit 1000
source $env(CSF_OCCTSamplesPath)/tcl/pathtrace_ball.tcl
vrenderparams -iss -nbtiles 64
vfps 1024
vdump $imagedir/${casename}_iss_64.png
vrenderparams -iss -nbtiles 256
vfps 256
vdump $imagedir/${casename}_iss_256.png
vrenderparams -iss -nbtiles 1024
vfps 64
vdump $imagedir/${casename}_iss_1024.png