1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0026432: Improving Path Tracing functionality

Samples per pixel parameter added. Simple filtering added. Lights fixed. Max radiance parameter.

Conflicts:
	src/OpenGl/OpenGl_View_Raytrace.cxx
	src/Shaders/PathtraceBase.fs
This commit is contained in:
duv
2015-07-14 16:52:30 +03:00
committed by isk
parent 4eaeaf9aa2
commit e3abe871e2
9 changed files with 251 additions and 18 deletions

View File

@@ -59,6 +59,8 @@ public:
IsTransparentShadowEnabled (Standard_False),
UseEnvironmentMapBackground (Standard_False),
CoherentPathTracingMode (Standard_False),
IsGIFilteringEnabled (Standard_False),
RadianceClampValue (10.0),
StereoMode (Graphic3d_StereoMode_QuadBuffer),
AnaglyphFilter (Anaglyph_RedCyan_Optimized),
@@ -90,6 +92,8 @@ public:
Standard_Boolean IsTransparentShadowEnabled; //!< enables/disables light propagation through transparent media, False by default
Standard_Boolean UseEnvironmentMapBackground; //!< enables/disables environment map background
Standard_Boolean CoherentPathTracingMode; //!< enables/disables 'coherent' tracing mode (single RNG seed within 16x16 image blocks)
Standard_Boolean IsGIFilteringEnabled; //!< enables/disables post-processing of GI rendering results
Standard_Real RadianceClampValue; //!< maximum radiance value which will not be clamped.
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
Anaglyph AnaglyphFilter; //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default

View File

@@ -667,10 +667,12 @@ protected: //! @name data types related to ray-tracing
OpenGl_RT_uSphereMapForBack,
OpenGl_RT_uTexSamplersArray,
OpenGl_RT_uBlockedRngEnabled,
OpenGl_RT_uMaxRadiance,
// sampled frame params
OpenGl_RT_uSampleWeight,
OpenGl_RT_uFrameRndSeed,
OpenGl_RT_uBilateralEnabled,
// adaptive FSAA params
OpenGl_RT_uOffsetX,

View File

@@ -1566,6 +1566,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
aShaderProgram->GetUniformLocation (theGlContext, "uSampleWeight");
myUniformLocations[anIndex][OpenGl_RT_uFrameRndSeed] =
aShaderProgram->GetUniformLocation (theGlContext, "uFrameRndSeed");
myUniformLocations[anIndex][OpenGl_RT_uMaxRadiance] =
aShaderProgram->GetUniformLocation (theGlContext, "uMaxRadiance");
myUniformLocations[anIndex][OpenGl_RT_uBackColorTop] =
aShaderProgram->GetUniformLocation (theGlContext, "uBackColorTop");
@@ -1575,6 +1577,9 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
theGlContext->BindProgram (myOutImageProgram);
myUniformLocations[0][OpenGl_RT_uBilateralEnabled] =
myOutImageProgram->GetUniformLocation (theGlContext, "uBilateralEnabled");
myOutImageProgram->SetSampler (theGlContext,
"uInputTexture", OpenGl_RT_PrevAccumTexture);
@@ -2421,14 +2426,53 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
// Set frame accumulation weight
myRaytraceProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
myUniformLocations[0][OpenGl_RT_uMaxRadiance], static_cast<Standard_ShortReal> (theCView.RenderParams.RadianceClampValue));
// Set random number generator seed
myRaytraceProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
}
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
Standard_Integer aSamplesPerPixel = theCView.RenderParams.SamplesPerPixel;
if (aSamplesPerPixel == 0)
{
// Set frame accumulation weight
myRaytraceProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
}
else
{
for (int aPassIndex = 0; aPassIndex < aSamplesPerPixel; ++aPassIndex)
{
aRenderFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1 : myRaytraceFBO2;
anAccumFramebuffer = myAccumFrames % 2 ? myRaytraceFBO2 : myRaytraceFBO1;
aRenderFramebuffer->BindBuffer (theGlContext);
anAccumFramebuffer->ColorTexture()->Bind (
theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
// Set frame accumulation weight
myRaytraceProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
// Set random number generator seed
myRaytraceProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
++myAccumFrames;
glFinish();
}
}
}
else
{
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
++myAccumFrames;
}
if (myRaytraceParameters.GlobalIllumination)
{
@@ -2449,6 +2493,9 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
aRenderFramebuffer->ColorTexture()->Bind (
theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
myOutImageProgram->SetUniform (theGlContext,
myUniformLocations[0][OpenGl_RT_uBilateralEnabled], theCView.RenderParams.IsGIFilteringEnabled ? 1 : 0);
theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
}
else if (myRenderParams.IsAntialiasingEnabled)

View File

@@ -1,13 +1,56 @@
//! Input image.
uniform sampler2D uInputTexture;
uniform int uBilateralEnabled;
//! Output pixel color.
out vec4 OutColor;
const float rI = 0.270 * 1.0f; // The intensity radius (in pixels).
const float rL = 1.71 * 0.5f; // The geometric radius (in pixels).
const int WindowSize = 8; // The window size (in pixels).
float gaussian (float theL, float theR)
{
return exp (-theL * theL / (2.0f * theR * theR));
}
vec4 bilateral()
{
// Get the sizes
int aWindow = WindowSize / 2;
vec4 anOutCol = vec4 (0.f, 0.f, 0.f, 0.f);
vec4 aRefCol = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
float aNorm = 0.f;
// Compute the kernel
for (int i = -aWindow; i <= aWindow; i++)
{
for (int j = -aWindow; j <= aWindow; j++)
{
vec4 aCol = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy) + ivec2 (j, i), 0);
float A = gaussian (distance (aCol, aRefCol), rI);
float B = gaussian (length (vec2(j, i)), rL);
anOutCol += aCol * A * B;
aNorm += A * B;
}
}
return anOutCol * (1.f / aNorm);
}
void main (void)
{
vec4 aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
vec4 aColor;
if (bool (uBilateralEnabled))
{
aColor = bilateral();
}
else
{
aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
}
// apply gamma correction (we use gamma = 2)
OutColor = vec4 (sqrt (aColor.rgb), aColor.a);
}
}

View File

@@ -473,7 +473,7 @@ void sampleMaterial (in SMaterial theMaterial,
theBounce = SPEC_REFLECT_BOUNCE; // specular bounce
}
else // specular transmission
else if (aKsi < aReflection) // specular transmission
{
theWeight *= theMaterial.Kt.rgb * (aReflection / aPt) *
sampleSpecularTransmission (theOutput, theInput, theBounce, theWeight, theMaterial.Fresnel);
@@ -493,12 +493,12 @@ void sampleMaterial (in SMaterial theMaterial,
//=======================================================================
float handlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance)
{
float aDistance = dot (theToLight, theToLight);
float aSquareLightDist = dot (theToLight, theToLight);
float aCosMax = inversesqrt (1.f + theRadius * theRadius / aDistance);
float aCosMax = inversesqrt (1.f + theRadius * theRadius / aSquareLightDist);
return float (aDistance < theDistance * theDistance) *
step (aCosMax, dot (theToLight, theInput) * inversesqrt (aDistance));
return float (aSquareLightDist < theDistance * theDistance) *
step (aCosMax, dot (theToLight, theInput) * inversesqrt (aSquareLightDist));
}
//=======================================================================
@@ -514,13 +514,12 @@ float handleDirectLight (in vec3 theInput, in vec3 theToLight, in float theCosMa
// function : sampleLight
// purpose : general sampling function for directional and point lights
//=======================================================================
vec3 sampleLight (in vec3 theToLight, in bool isDirectional, in float theSmoothness, inout float thePDF)
vec3 sampleLight (in vec3 theToLight, in float theDistance, in bool isDirectional, in float theSmoothness, inout float thePDF)
{
SLocalSpace aSpace = LocalSpace (theToLight);
// for point lights smoothness defines radius
float aCosMax = isDirectional ? theSmoothness :
inversesqrt (1.f + theSmoothness * theSmoothness / dot (theToLight, theToLight));
float aCosMax = inversesqrt (1.f + theSmoothness * theSmoothness / (theDistance * theDistance));
float aKsi1 = RandFloat();
float aKsi2 = RandFloat();
@@ -593,8 +592,8 @@ vec3 intersectLight (in SRay theRay, in bool isViewRay, in int theBounce, in flo
return aRadiance;
}
#define MIN_THROUGHPUT vec3 (0.02f)
#define MIN_CONTRIBUTION vec3 (0.01f)
#define MIN_THROUGHPUT vec3 (2.0e-2f)
#define MIN_CONTRIBUTION vec3 (0.5e-2f)
#define MATERIAL_KD(index) (18 * index + 11)
#define MATERIAL_KR(index) (18 * index + 12)
@@ -720,7 +719,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
float aPDF = 1.f / uLightCount, aDistance = length (aLight.xyz);
aLight.xyz = sampleLight (aLight.xyz * (1.f / aDistance),
aLight.xyz = sampleLight (aLight.xyz * (1.f / aDistance), aDistance,
aLight.w == 0.f /* is infinite */, aParam.w /* angle cosine */, aPDF);
vec3 aContrib = (1.f / aPDF) * aParam.rgb /* Le */ * handleMaterial (

View File

@@ -13,7 +13,8 @@ uniform sampler2D uAccumTexture;
//! Increases performance up to 4 times, but noise becomes structured.
uniform int uBlockedRngEnabled;
#define MAX_RADIANCE vec3 (10.f)
//! Maximum value for radiance clamping.
uniform float uMaxRadiance;
// =======================================================================
// function : main
@@ -46,7 +47,7 @@ void main (void)
aColor.rgb = ZERO;
}
aColor.rgb = min (aColor.rgb, MAX_RADIANCE);
aColor.rgb = min (aColor.rgb, vec3 (uMaxRadiance));
OutColor = mix (texture2D (uAccumTexture, vPixel), aColor, uSampleWeight);
#else

View File

@@ -8273,6 +8273,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
theDI << "rayDepth: " << aParams.RaytracingDepth << "\n";
theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
theDI << "samples: " << aParams.SamplesPerPixel << "\n";
theDI << "filtering: " << (aParams.IsGIFilteringEnabled ? "on" : "off") << "\n";
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
theDI << "shadingModel: ";
switch (aView->ShadingModel())
@@ -8372,6 +8374,48 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
aParams.RaytracingDepth = aDepth;
}
}
else if (aFlag == "-maxrad"
|| aFlag == "-rclamp")
{
if (toPrint)
{
theDI << aParams.RadianceClampValue << " ";
continue;
}
else if (++anArgIter >= theArgNb)
{
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
return 1;
}
aParams.RadianceClampValue = Draw::Atoi (theArgVec[anArgIter]);
}
else if (aFlag == "-samples"
|| aFlag == "-spp")
{
if (toPrint)
{
theDI << aParams.SamplesPerPixel << " ";
continue;
}
else if (++anArgIter >= theArgNb)
{
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
return 1;
}
const Standard_Integer aSamples = Draw::Atoi (theArgVec[anArgIter]);
if (aSamples < 0)
{
std::cerr << "Error: invalid ray-tracing samples per pixel " << aSamples << ". SPP should be a positive number.\n";
return 1;
}
else
{
aParams.SamplesPerPixel = aSamples;
}
}
else if (aFlag == "-shad"
|| aFlag == "-shadows")
{
@@ -8458,6 +8502,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
}
}
else if (aFlag == "-filter" || aFlag == "-pp" )
{
if (toPrint)
{
theDI << (aParams.IsGIFilteringEnabled ? "on" : "off") << " ";
continue;
}
Standard_Boolean toEnable = Standard_True;
if (++anArgIter < theArgNb
&& !parseOnOff (theArgVec[anArgIter], toEnable))
{
--anArgIter;
}
aParams.IsGIFilteringEnabled = toEnable;
}
else if (aFlag == "-blockedrng"
|| aFlag == "-brng")
{

View File

@@ -0,0 +1,40 @@
puts "========"
puts "Ray Tracing - check PT lights correctness"
puts "========"
pload ALL
vinit
vsetdispmode 1
vvbo 0
box b 500 500 1
box b1 2 50 20
vdisplay b
vdisplay b1
vsetlocation b -250 -250 0
vsetlocation b1 -1 -25 0
vlight del 0
vlight del 0
vlight add positional head 0 pos -10 0 20
vlight change 0 sm 5.0
vrenderparams -ray -gi
vsetmaterial b plaster
vsetmaterial b1 plaster
vviewparams -scale 23.40302443511418 -proj 3.1690307533723025e-006 -0.053740375441171516 0.99855494192227556 -up 0.00011815109169240122 0.99855493498157033 0.05374037461975216 -at -0.039728087058276865 17.658749465576971 0.40052090530867673 -eye -0.038141096586915293 -9.2534108729671232 500.45788900604856
vlight change 0 int 20
psphere s 5.0
vdisplay s
vsetlocation s 10 0 20
vbsdf s -Kd 0.0 -Ks 0.0 -Kr 0.0 -Kt 0.0
vbsdf s -Le 20.0
vfps 500

View File

@@ -0,0 +1,37 @@
puts "========"
puts "Ray Tracing - check PT lights correctness"
puts "========"
pload ALL
vinit
vsetdispmode 1
vvbo 0
box b 500 500 1
psphere s 6.0
vdisplay b
vdisplay s
vsetlocation b -250 -250 0
vsetlocation s 0.0 0.0 7.0
vlight del 0
vlight del 0
vlight add positional head 0 pos -15 0 20 sm 4.0 int 20
vrenderparams -ray -gi -rayDepth 12
vsetmaterial b plaster
vsetmaterial s glass
psphere ls 4.0
vdisplay ls
vsetlocation ls 15 0 20
vbsdf ls -Kd 0.0 -Ks 0.0 -Kr 0.0 -Kt 0.0
vbsdf ls -Le 20.0
vviewparams -scale 23.40302443511418 -proj 3.1690307533720754e-006 -0.053740375441171412 0.99855494192227556 -up 0.00011815108764545944 0.99855493500381731 0.053740374206389462 -at 0.062905867278332972 2.1147318213590474 -0.43602962811169049 -eye 0.064492857749694432 -24.79742851718504 499.62133847262908
vfps 400