1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-16 10:54:53 +03:00

0028126: Visualization, Path tracing - Provide ability to use two-sided scattering models

This commit is contained in:
dbp 2016-11-18 11:13:29 +03:00 committed by apn
parent a148c938b0
commit b4327ba8df
7 changed files with 237 additions and 159 deletions

View File

@ -28,9 +28,6 @@ public:
//! Default pixels density.
static const unsigned int THE_DEFAULT_RESOLUTION = 72u;
//! Default number of samples per pixel.
static const Standard_Integer THE_DEFAULT_SPP = 1;
//! Default ray-tracing depth.
static const Standard_Integer THE_DEFAULT_DEPTH = 3;
@ -53,7 +50,6 @@ public:
NbMsaaSamples (0),
// ray tracing parameters
IsGlobalIlluminationEnabled (Standard_False),
SamplesPerPixel (THE_DEFAULT_SPP),
RaytracingDepth (THE_DEFAULT_DEPTH),
IsShadowEnabled (Standard_True),
IsReflectionEnabled (Standard_False),
@ -63,6 +59,7 @@ public:
CoherentPathTracingMode (Standard_False),
AdaptiveScreenSampling (Standard_False),
ShowSamplingTiles (Standard_False),
TwoSidedBsdfModels (Standard_False),
RebuildRayTracingShaders (Standard_False),
// stereoscopic parameters
StereoMode (Graphic3d_StereoMode_QuadBuffer),
@ -104,6 +101,7 @@ public:
Standard_Boolean CoherentPathTracingMode; //!< enables/disables 'coherent' tracing mode (single RNG seed within 16x16 image blocks)
Standard_Boolean AdaptiveScreenSampling; //!< enables/disables adaptive screen sampling mode for path tracing, FALSE by default
Standard_Boolean ShowSamplingTiles; //!< enables/disables debug mode for adaptive screen sampling, FALSE by default
Standard_Boolean TwoSidedBsdfModels; //!< forces path tracing to use two-sided versions of original one-sided scattering models
Standard_Boolean RebuildRayTracingShaders; //!< forces rebuilding ray tracing shaders at the next frame
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default

View File

@ -696,6 +696,9 @@ protected: //! @name data types related to ray-tracing
//! Enables/disables the use of OpenGL bindless textures.
Standard_Boolean UseBindlessTextures;
//! Enables/disables two-sided BSDF models instead of one-sided.
Standard_Boolean TwoSidedBsdfModels;
//! Enables/disables adaptive screen sampling for path tracing.
Standard_Boolean AdaptiveScreenSampling;
@ -703,13 +706,11 @@ protected: //! @name data types related to ray-tracing
RaytracingParams()
: StackSize (THE_DEFAULT_STACK_SIZE),
NbBounces (THE_DEFAULT_NB_BOUNCES),
TransparentShadows (Standard_False),
GlobalIllumination (Standard_False),
UseBindlessTextures (Standard_False),
AdaptiveScreenSampling (Standard_False)
{
//
}
TransparentShadows (Standard_False),
GlobalIllumination (Standard_False),
UseBindlessTextures (Standard_False),
TwoSidedBsdfModels (Standard_False),
AdaptiveScreenSampling (Standard_False) { }
};
//! Describes state of OpenGL structure.

View File

@ -1144,6 +1144,11 @@ TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_C
TCollection_AsciiString ("\n#define BLOCK_SIZE ") + TCollection_AsciiString (OpenGl_TileSampler::TileSize());
}
}
if (myRaytraceParameters.TwoSidedBsdfModels) // two-sided BSDFs requested
{
aPrefixString += TCollection_AsciiString ("\n#define TWO_SIDED_BXDF");
}
}
return aPrefixString;
@ -1354,27 +1359,18 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
}
}
if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces)
{
myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
aToRebuildShaders = Standard_True;
}
if (myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces
|| myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows
|| myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination
|| myRenderParams.TwoSidedBsdfModels != myRaytraceParameters.TwoSidedBsdfModels
|| myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
{
myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth;
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
myRaytraceParameters.TwoSidedBsdfModels = myRenderParams.TwoSidedBsdfModels;
myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
aToRebuildShaders = Standard_True;
}
if (myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows)
{
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
aToRebuildShaders = Standard_True;
}
if (myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination)
{
myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
aToRebuildShaders = Standard_True;
}

View File

@ -244,12 +244,12 @@ void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)
//////////////////////////////////////////////////////////////////////////////////////////////
//=======================================================================
// function : HandleLambertianReflection
// purpose : Handles Lambertian BRDF, with cos(N, PSI)
// function : EvalLambertianReflection
// purpose : Evaluates Lambertian BRDF, with cos(N, PSI)
//=======================================================================
float HandleLambertianReflection (in vec3 theInput, in vec3 theOutput)
float EvalLambertianReflection (in vec3 theWi, in vec3 theWo)
{
return (theInput.z <= 0.f || theOutput.z <= 0.f) ? 0.f : theInput.z * (1.f / M_PI);
return (theWi.z <= 0.f || theWo.z <= 0.f) ? 0.f : theWi.z * (1.f / M_PI);
}
//=======================================================================
@ -285,13 +285,13 @@ float SmithG1 (in vec3 theDirection, in vec3 theM, in float theRoughness)
}
//=======================================================================
// function : HandleBlinnReflection
// purpose : Handles Blinn glossy BRDF, with cos(N, PSI)
// function : EvalBlinnReflection
// purpose : Evaluates Blinn glossy BRDF, with cos(N, PSI)
//=======================================================================
vec3 HandleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnel, in float theRoughness)
vec3 EvalBlinnReflection (in vec3 theWi, in vec3 theWo, in vec3 theFresnel, in float theRoughness)
{
// calculate the reflection half-vec
vec3 aH = normalize (theInput + theOutput);
vec3 aH = normalize (theWi + theWo);
// roughness value -> Blinn exponent
float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);
@ -300,41 +300,55 @@ vec3 HandleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFres
float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);
// calculate shadow-masking function
float aG = SmithG1 (theOutput, aH, theRoughness) * SmithG1 (theInput, aH, theRoughness);
float aG = SmithG1 (theWo, aH, theRoughness) *
SmithG1 (theWi, aH, theRoughness);
// return total amount of reflection
return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :
aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);
return (theWi.z <= 0.f || theWo.z <= 0.f) ? ZERO :
aD * aG / (4.f * theWo.z) * fresnelMedia (dot (theWo, aH), theFresnel);
}
//=======================================================================
// function : HandleMaterial
// purpose : Returns BSDF value for specified material, with cos(N, PSI)
// function : EvalMaterial
// purpose : Evaluates BSDF for specified material, with cos(N, PSI)
//=======================================================================
vec3 HandleMaterial (in SMaterial theBSDF, in vec3 theInput, in vec3 theOutput)
vec3 EvalMaterial (in SMaterial theBSDF, in vec3 theWi, in vec3 theWo)
{
return theBSDF.Kd.rgb * HandleLambertianReflection (theInput, theOutput) +
theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);
#ifdef TWO_SIDED_BXDF
theWi.z *= sign (theWi.z);
theWo.z *= sign (theWo.z);
#endif
return theBSDF.Kd.rgb * EvalLambertianReflection (theWi, theWo) +
theBSDF.Ks.rgb * EvalBlinnReflection (theWi, theWo, theBSDF.Fresnel, theBSDF.Ks.w);
}
//=======================================================================
// function : SampleLambertianReflection
// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
//=======================================================================
vec3 SampleLambertianReflection (in vec3 theOutput, out vec3 theInput, inout float thePDF)
vec3 SampleLambertianReflection (in vec3 theWo, out vec3 theWi, inout float thePDF)
{
float aKsi1 = RandFloat();
float aKsi2 = RandFloat();
float aTemp = sqrt (aKsi2);
theWi = vec3 (cos (M_2_PI * aKsi1),
sin (M_2_PI * aKsi1),
sqrt (1.f - aKsi2));
theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),
aTemp * sin (M_2_PI * aKsi1),
sqrt (1.f - aKsi2));
theWi.xy *= sqrt (aKsi2);
thePDF *= abs (theInput.z) * (1.f / M_PI);
#ifdef TWO_SIDED_BXDF
theWi.z *= sign (theWo.z);
#endif
return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;
thePDF *= theWi.z * (1.f / M_PI);
#ifdef TWO_SIDED_BXDF
return UNIT;
#else
return mix (UNIT, ZERO, theWo.z <= 0.f);
#endif
}
//=======================================================================
@ -347,7 +361,7 @@ vec3 SampleLambertianReflection (in vec3 theOutput, out vec3 theInput, inout flo
// terms would be complex, and it is the D term that accounts
// for most of the variation.
//=======================================================================
vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel, in float theRoughness, inout float thePDF)
vec3 SampleBlinnReflection (in vec3 theWo, out vec3 theWi, in vec3 theFresnel, in float theRoughness, inout float thePDF)
{
float aKsi1 = RandFloat();
float aKsi2 = RandFloat();
@ -367,56 +381,72 @@ vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFre
// calculate PDF of sampled direction
thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);
float aCosDelta = dot (theOutput, aM);
#ifdef TWO_SIDED_BXDF
bool toFlip = theWo.z < 0.f;
if (toFlip)
theWo.z = -theWo.z;
#endif
float aCosDelta = dot (theWo, aM);
// pick input based on half direction
theInput = -theOutput + 2.f * aCosDelta * aM;
theWi = -theWo + 2.f * aCosDelta * aM;
if (theInput.z <= 0.f || theOutput.z <= 0.f)
if (theWi.z <= 0.f || theWo.z <= 0.f)
{
return ZERO;
}
// Jacobian of half-direction mapping
thePDF /= 4.f * dot (theInput, aM);
thePDF /= 4.f * dot (theWi, aM);
// compute shadow-masking coefficient
float aG = SmithG1 (theOutput, aM, theRoughness) * SmithG1 (theInput, aM, theRoughness);
float aG = SmithG1 (theWo, aM, theRoughness) *
SmithG1 (theWi, aM, theRoughness);
return aG * aCosDelta / (theOutput.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);
#ifdef TWO_SIDED_BXDF
if (toFlip)
theWi.z = -theWi.z;
#endif
return (aG * aCosDelta) / (theWo.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);
}
//=======================================================================
// function : SampleSpecularReflection
// purpose : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
//=======================================================================
vec3 SampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel)
vec3 SampleSpecularReflection (in vec3 theWo, out vec3 theWi, in vec3 theFresnel)
{
// Sample input direction
theInput = vec3 (-theOutput.x,
-theOutput.y,
theOutput.z);
theWi = vec3 (-theWo.x,
-theWo.y,
theWo.z);
return fresnelMedia (theOutput.z, theFresnel);
#ifdef TWO_SIDED_BXDF
return fresnelMedia (theWo.z, theFresnel);
#else
return fresnelMedia (theWo.z, theFresnel) * step (0.f, theWo.z);
#endif
}
//=======================================================================
// function : SampleSpecularTransmission
// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)
//=======================================================================
vec3 SampleSpecularTransmission (in vec3 theOutput,
out vec3 theInput, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)
vec3 SampleSpecularTransmission (in vec3 theWo, out vec3 theWi, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)
{
vec3 aFactor = fresnelMedia (theOutput.z, theFresnel);
vec3 aFactor = fresnelMedia (theWo.z, theFresnel);
float aReflection = convolve (aFactor, theWeight);
// sample specular BRDF/BTDF
if (RandFloat() <= aReflection)
{
theInput = vec3 (-theOutput.x,
-theOutput.y,
theOutput.z);
theWi = vec3 (-theWo.x,
-theWo.y,
theWo.z);
theWeight = aFactor * (1.f / aReflection);
}
@ -424,7 +454,7 @@ vec3 SampleSpecularTransmission (in vec3 theOutput,
{
theInside = !theInside;
transmitted (theFresnel.y, theOutput, theInput);
transmitted (theFresnel.y, theWo, theWi);
theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));
}
@ -438,10 +468,7 @@ vec3 SampleSpecularTransmission (in vec3 theOutput,
// function : BsdfPdf
// purpose : Calculates BSDF of sampling input knowing output
//=======================================================================
float BsdfPdf (in SMaterial theBSDF,
in vec3 theOutput,
in vec3 theInput,
in vec3 theWeight)
float BsdfPdf (in SMaterial theBSDF, in vec3 theWo, in vec3 theWi, in vec3 theWeight)
{
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
float aPs = convolve (theBSDF.Ks.rgb, theWeight);
@ -452,15 +479,15 @@ float BsdfPdf (in SMaterial theBSDF,
float aPDF = 0.f; // PDF of sampling input direction
if (theInput.z * theOutput.z > 0.f)
if (theWi.z * theWo.z > 0.f)
{
vec3 aHalf = normalize (theInput + theOutput);
vec3 aH = normalize (theWi + theWo);
// roughness value --> Blinn exponent
float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);
aPDF = aPd * abs (theInput.z / M_PI) +
aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (aHalf.z, aPower + 1.f) / (4.f * dot (theInput, aHalf));
aPDF = aPd * abs (theWi.z / M_PI) +
aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / (4.f * dot (theWi, aH));
}
return aPDF / aReflection;
@ -473,11 +500,7 @@ float BsdfPdf (in SMaterial theBSDF,
// function : SampleBsdf
// purpose : Samples specified composite material (BSDF)
//=======================================================================
float SampleBsdf (in SMaterial theBSDF,
in vec3 theOutput,
out vec3 theInput,
inout vec3 theWeight,
inout bool theInside)
float SampleBsdf (in SMaterial theBSDF, in vec3 theWo, out vec3 theWi, inout vec3 theWeight, inout bool theInside)
{
// compute probability of each reflection type (BxDF)
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
@ -497,13 +520,13 @@ float SampleBsdf (in SMaterial theBSDF,
{
PICK_BXDF (aPd, theBSDF.Kd.rgb);
theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);
theWeight *= SampleLambertianReflection (theWo, theWi, aPDF);
}
else if (aKsi < aPd + aPs) // glossy reflection
{
PICK_BXDF (aPs, theBSDF.Ks.rgb);
theWeight *= SampleBlinnReflection (theOutput, theInput, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);
theWeight *= SampleBlinnReflection (theWo, theWi, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);
}
else if (aKsi < aPd + aPs + aPr) // specular reflection
{
@ -511,7 +534,7 @@ float SampleBsdf (in SMaterial theBSDF,
aPDF = MAXFLOAT;
theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);
theWeight *= SampleSpecularReflection (theWo, theWi, theBSDF.Fresnel);
}
else if (aKsi < aReflection) // specular transmission
{
@ -519,7 +542,7 @@ float SampleBsdf (in SMaterial theBSDF,
aPDF = MAXFLOAT;
theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);
theWeight *= SampleSpecularTransmission (theWo, theWi, theWeight, theBSDF.Fresnel, theInside);
}
// path termination for extra small weights
@ -810,7 +833,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
// MIS weight including division by explicit PDF
float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);
vec3 aContrib = aMIS * aParam.rgb /* Le */ * HandleMaterial (
vec3 aContrib = aMIS * aParam.rgb /* Le */ * EvalMaterial (
aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));
if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important

View File

@ -247,12 +247,12 @@ static const char Shaders_PathtraceBase_fs[] =
"//////////////////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"//=======================================================================\n"
"// function : HandleLambertianReflection\n"
"// purpose : Handles Lambertian BRDF, with cos(N, PSI)\n"
"// function : EvalLambertianReflection\n"
"// purpose : Evaluates Lambertian BRDF, with cos(N, PSI)\n"
"//=======================================================================\n"
"float HandleLambertianReflection (in vec3 theInput, in vec3 theOutput)\n"
"float EvalLambertianReflection (in vec3 theWi, in vec3 theWo)\n"
"{\n"
" return (theInput.z <= 0.f || theOutput.z <= 0.f) ? 0.f : theInput.z * (1.f / M_PI);\n"
" return (theWi.z <= 0.f || theWo.z <= 0.f) ? 0.f : theWi.z * (1.f / M_PI);\n"
"}\n"
"\n"
"//=======================================================================\n"
@ -288,13 +288,13 @@ static const char Shaders_PathtraceBase_fs[] =
"}\n"
"\n"
"//=======================================================================\n"
"// function : HandleBlinnReflection\n"
"// purpose : Handles Blinn glossy BRDF, with cos(N, PSI)\n"
"// function : EvalBlinnReflection\n"
"// purpose : Evaluates Blinn glossy BRDF, with cos(N, PSI)\n"
"//=======================================================================\n"
"vec3 HandleBlinnReflection (in vec3 theInput, in vec3 theOutput, in vec3 theFresnel, in float theRoughness)\n"
"vec3 EvalBlinnReflection (in vec3 theWi, in vec3 theWo, in vec3 theFresnel, in float theRoughness)\n"
"{\n"
" // calculate the reflection half-vec\n"
" vec3 aH = normalize (theInput + theOutput);\n"
" vec3 aH = normalize (theWi + theWo);\n"
"\n"
" // roughness value -> Blinn exponent\n"
" float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\n"
@ -303,41 +303,55 @@ static const char Shaders_PathtraceBase_fs[] =
" float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);\n"
"\n"
" // calculate shadow-masking function\n"
" float aG = SmithG1 (theOutput, aH, theRoughness) * SmithG1 (theInput, aH, theRoughness);\n"
" float aG = SmithG1 (theWo, aH, theRoughness) *\n"
" SmithG1 (theWi, aH, theRoughness);\n"
"\n"
" // return total amount of reflection\n"
" return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :\n"
" aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);\n"
" return (theWi.z <= 0.f || theWo.z <= 0.f) ? ZERO :\n"
" aD * aG / (4.f * theWo.z) * fresnelMedia (dot (theWo, aH), theFresnel);\n"
"}\n"
"\n"
"//=======================================================================\n"
"// function : HandleMaterial\n"
"// purpose : Returns BSDF value for specified material, with cos(N, PSI)\n"
"// function : EvalMaterial\n"
"// purpose : Evaluates BSDF for specified material, with cos(N, PSI)\n"
"//=======================================================================\n"
"vec3 HandleMaterial (in SMaterial theBSDF, in vec3 theInput, in vec3 theOutput)\n"
"vec3 EvalMaterial (in SMaterial theBSDF, in vec3 theWi, in vec3 theWo)\n"
"{\n"
" return theBSDF.Kd.rgb * HandleLambertianReflection (theInput, theOutput) +\n"
" theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);\n"
"#ifdef TWO_SIDED_BXDF\n"
" theWi.z *= sign (theWi.z);\n"
" theWo.z *= sign (theWo.z);\n"
"#endif\n"
"\n"
" return theBSDF.Kd.rgb * EvalLambertianReflection (theWi, theWo) +\n"
" theBSDF.Ks.rgb * EvalBlinnReflection (theWi, theWo, theBSDF.Fresnel, theBSDF.Ks.w);\n"
"}\n"
"\n"
"//=======================================================================\n"
"// function : SampleLambertianReflection\n"
"// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
"//=======================================================================\n"
"vec3 SampleLambertianReflection (in vec3 theOutput, out vec3 theInput, inout float thePDF)\n"
"vec3 SampleLambertianReflection (in vec3 theWo, out vec3 theWi, inout float thePDF)\n"
"{\n"
" float aKsi1 = RandFloat();\n"
" float aKsi2 = RandFloat();\n"
"\n"
" float aTemp = sqrt (aKsi2);\n"
" theWi = vec3 (cos (M_2_PI * aKsi1),\n"
" sin (M_2_PI * aKsi1),\n"
" sqrt (1.f - aKsi2));\n"
"\n"
" theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),\n"
" aTemp * sin (M_2_PI * aKsi1),\n"
" sqrt (1.f - aKsi2));\n"
" theWi.xy *= sqrt (aKsi2);\n"
"\n"
" thePDF *= abs (theInput.z) * (1.f / M_PI);\n"
"#ifdef TWO_SIDED_BXDF\n"
" theWi.z *= sign (theWo.z);\n"
"#endif\n"
"\n"
" return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;\n"
" thePDF *= theWi.z * (1.f / M_PI);\n"
"\n"
"#ifdef TWO_SIDED_BXDF\n"
" return UNIT;\n"
"#else\n"
" return mix (UNIT, ZERO, theWo.z <= 0.f);\n"
"#endif\n"
"}\n"
"\n"
"//=======================================================================\n"
@ -350,7 +364,7 @@ static const char Shaders_PathtraceBase_fs[] =
"// terms would be complex, and it is the D term that accounts\n"
"// for most of the variation.\n"
"//=======================================================================\n"
"vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel, in float theRoughness, inout float thePDF)\n"
"vec3 SampleBlinnReflection (in vec3 theWo, out vec3 theWi, in vec3 theFresnel, in float theRoughness, inout float thePDF)\n"
"{\n"
" float aKsi1 = RandFloat();\n"
" float aKsi2 = RandFloat();\n"
@ -370,56 +384,72 @@ static const char Shaders_PathtraceBase_fs[] =
" // calculate PDF of sampled direction\n"
" thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);\n"
"\n"
" float aCosDelta = dot (theOutput, aM);\n"
"#ifdef TWO_SIDED_BXDF\n"
" bool toFlip = theWo.z < 0.f;\n"
"\n"
" if (toFlip)\n"
" theWo.z = -theWo.z;\n"
"#endif\n"
"\n"
" float aCosDelta = dot (theWo, aM);\n"
"\n"
" // pick input based on half direction\n"
" theInput = -theOutput + 2.f * aCosDelta * aM;\n"
" theWi = -theWo + 2.f * aCosDelta * aM;\n"
"\n"
" if (theInput.z <= 0.f || theOutput.z <= 0.f)\n"
" if (theWi.z <= 0.f || theWo.z <= 0.f)\n"
" {\n"
" return ZERO;\n"
" }\n"
"\n"
" // Jacobian of half-direction mapping\n"
" thePDF /= 4.f * dot (theInput, aM);\n"
" thePDF /= 4.f * dot (theWi, aM);\n"
"\n"
" // compute shadow-masking coefficient\n"
" float aG = SmithG1 (theOutput, aM, theRoughness) * SmithG1 (theInput, aM, theRoughness);\n"
" float aG = SmithG1 (theWo, aM, theRoughness) *\n"
" SmithG1 (theWi, aM, theRoughness);\n"
"\n"
" return aG * aCosDelta / (theOutput.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);\n"
"#ifdef TWO_SIDED_BXDF\n"
" if (toFlip)\n"
" theWi.z = -theWi.z;\n"
"#endif\n"
"\n"
" return (aG * aCosDelta) / (theWo.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);\n"
"}\n"
"\n"
"//=======================================================================\n"
"// function : SampleSpecularReflection\n"
"// purpose : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
"//=======================================================================\n"
"vec3 SampleSpecularReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFresnel)\n"
"vec3 SampleSpecularReflection (in vec3 theWo, out vec3 theWi, in vec3 theFresnel)\n"
"{\n"
" // Sample input direction\n"
" theInput = vec3 (-theOutput.x,\n"
" -theOutput.y,\n"
" theOutput.z);\n"
" theWi = vec3 (-theWo.x,\n"
" -theWo.y,\n"
" theWo.z);\n"
"\n"
" return fresnelMedia (theOutput.z, theFresnel);\n"
"#ifdef TWO_SIDED_BXDF\n"
" return fresnelMedia (theWo.z, theFresnel);\n"
"#else\n"
" return fresnelMedia (theWo.z, theFresnel) * step (0.f, theWo.z);\n"
"#endif\n"
"}\n"
"\n"
"//=======================================================================\n"
"// function : SampleSpecularTransmission\n"
"// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
"//=======================================================================\n"
"vec3 SampleSpecularTransmission (in vec3 theOutput,\n"
" out vec3 theInput, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)\n"
"vec3 SampleSpecularTransmission (in vec3 theWo, out vec3 theWi, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)\n"
"{\n"
" vec3 aFactor = fresnelMedia (theOutput.z, theFresnel);\n"
" vec3 aFactor = fresnelMedia (theWo.z, theFresnel);\n"
"\n"
" float aReflection = convolve (aFactor, theWeight);\n"
"\n"
" // sample specular BRDF/BTDF\n"
" if (RandFloat() <= aReflection)\n"
" {\n"
" theInput = vec3 (-theOutput.x,\n"
" -theOutput.y,\n"
" theOutput.z);\n"
" theWi = vec3 (-theWo.x,\n"
" -theWo.y,\n"
" theWo.z);\n"
"\n"
" theWeight = aFactor * (1.f / aReflection);\n"
" }\n"
@ -427,7 +457,7 @@ static const char Shaders_PathtraceBase_fs[] =
" {\n"
" theInside = !theInside;\n"
"\n"
" transmitted (theFresnel.y, theOutput, theInput);\n"
" transmitted (theFresnel.y, theWo, theWi);\n"
"\n"
" theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));\n"
" }\n"
@ -441,10 +471,7 @@ static const char Shaders_PathtraceBase_fs[] =
"// function : BsdfPdf\n"
"// purpose : Calculates BSDF of sampling input knowing output\n"
"//=======================================================================\n"
"float BsdfPdf (in SMaterial theBSDF,\n"
" in vec3 theOutput,\n"
" in vec3 theInput,\n"
" in vec3 theWeight)\n"
"float BsdfPdf (in SMaterial theBSDF, in vec3 theWo, in vec3 theWi, in vec3 theWeight)\n"
"{\n"
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
" float aPs = convolve (theBSDF.Ks.rgb, theWeight);\n"
@ -455,15 +482,15 @@ static const char Shaders_PathtraceBase_fs[] =
"\n"
" float aPDF = 0.f; // PDF of sampling input direction\n"
"\n"
" if (theInput.z * theOutput.z > 0.f)\n"
" if (theWi.z * theWo.z > 0.f)\n"
" {\n"
" vec3 aHalf = normalize (theInput + theOutput);\n"
" vec3 aH = normalize (theWi + theWo);\n"
"\n"
" // roughness value --> Blinn exponent\n"
" float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);\n"
"\n"
" aPDF = aPd * abs (theInput.z / M_PI) +\n"
" aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (aHalf.z, aPower + 1.f) / (4.f * dot (theInput, aHalf));\n"
" aPDF = aPd * abs (theWi.z / M_PI) +\n"
" aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / (4.f * dot (theWi, aH));\n"
" }\n"
"\n"
" return aPDF / aReflection;\n"
@ -476,11 +503,7 @@ static const char Shaders_PathtraceBase_fs[] =
"// function : SampleBsdf\n"
"// purpose : Samples specified composite material (BSDF)\n"
"//=======================================================================\n"
"float SampleBsdf (in SMaterial theBSDF,\n"
" in vec3 theOutput,\n"
" out vec3 theInput,\n"
" inout vec3 theWeight,\n"
" inout bool theInside)\n"
"float SampleBsdf (in SMaterial theBSDF, in vec3 theWo, out vec3 theWi, inout vec3 theWeight, inout bool theInside)\n"
"{\n"
" // compute probability of each reflection type (BxDF)\n"
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
@ -500,13 +523,13 @@ static const char Shaders_PathtraceBase_fs[] =
" {\n"
" PICK_BXDF (aPd, theBSDF.Kd.rgb);\n"
"\n"
" theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);\n"
" theWeight *= SampleLambertianReflection (theWo, theWi, aPDF);\n"
" }\n"
" else if (aKsi < aPd + aPs) // glossy reflection\n"
" {\n"
" PICK_BXDF (aPs, theBSDF.Ks.rgb);\n"
"\n"
" theWeight *= SampleBlinnReflection (theOutput, theInput, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);\n"
" theWeight *= SampleBlinnReflection (theWo, theWi, theBSDF.Fresnel, theBSDF.Ks.w, aPDF);\n"
" }\n"
" else if (aKsi < aPd + aPs + aPr) // specular reflection\n"
" {\n"
@ -514,7 +537,7 @@ static const char Shaders_PathtraceBase_fs[] =
"\n"
" aPDF = MAXFLOAT;\n"
"\n"
" theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);\n"
" theWeight *= SampleSpecularReflection (theWo, theWi, theBSDF.Fresnel);\n"
" }\n"
" else if (aKsi < aReflection) // specular transmission\n"
" {\n"
@ -522,7 +545,7 @@ static const char Shaders_PathtraceBase_fs[] =
"\n"
" aPDF = MAXFLOAT;\n"
"\n"
" theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);\n"
" theWeight *= SampleSpecularTransmission (theWo, theWi, theWeight, theBSDF.Fresnel, theInside);\n"
" }\n"
"\n"
" // path termination for extra small weights\n"
@ -813,7 +836,7 @@ static const char Shaders_PathtraceBase_fs[] =
" // MIS weight including division by explicit PDF\n"
" float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
"\n"
" vec3 aContrib = aMIS * aParam.rgb /* Le */ * HandleMaterial (\n"
" vec3 aContrib = aMIS * aParam.rgb /* Le */ * EvalMaterial (\n"
" aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));\n"
"\n"
" if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important\n"

View File

@ -9077,16 +9077,17 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
case Graphic3d_RM_RAYTRACING: theDI << "raytrace "; break;
}
theDI << "\n";
theDI << "msaa: " << aParams.NbMsaaSamples << "\n";
theDI << "rayDepth: " << aParams.RaytracingDepth << "\n";
theDI << "fsaa: " << (aParams.IsAntialiasingEnabled ? "on" : "off") << "\n";
theDI << "shadows: " << (aParams.IsShadowEnabled ? "on" : "off") << "\n";
theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n";
theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
theDI << "iss: " << (aParams.AdaptiveScreenSampling ? "on" : "off") << "\n";
theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
theDI << "msaa: " << aParams.NbMsaaSamples << "\n";
theDI << "rayDepth: " << aParams.RaytracingDepth << "\n";
theDI << "fsaa: " << (aParams.IsAntialiasingEnabled ? "on" : "off") << "\n";
theDI << "shadows: " << (aParams.IsShadowEnabled ? "on" : "off") << "\n";
theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n";
theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
theDI << "iss: " << (aParams.AdaptiveScreenSampling ? "on" : "off") << "\n";
theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels ? "on" : "off") << "\n";
theDI << "shadingModel: ";
switch (aView->ShadingModel())
{
@ -9360,6 +9361,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
}
aParams.UseEnvironmentMapBackground = toEnable;
}
else if (aFlag == "-twoside")
{
if (toPrint)
{
theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
continue;
}
Standard_Boolean toEnable = Standard_True;
if (++anArgIter < theArgNb
&& !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
{
--anArgIter;
}
aParams.TwoSidedBsdfModels = toEnable;
}
else if (aFlag == "-shademodel"
|| aFlag == "-shadingmodel"
|| aFlag == "-shading")
@ -10633,6 +10650,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n '-gi on|off' Enables/disables global illumination effects"
"\n '-brng on|off' Enables/disables blocked RNG (fast coherent PT)"
"\n '-env on|off' Enables/disables environment map background"
"\n '-twoside on|off' Enables/disables two-sided BSDF models (PT mode)"
"\n '-iss on|off' Enables/disables adaptive screen sampling (PT mode)"
"\n '-issd on|off' Shows screen sampling distribution in ISS mode"
"\n '-rebuildGlsl on|off' Rebuild Ray-Tracing GLSL programs (for debugging)"

View File

@ -0,0 +1,19 @@
puts "============"
puts "Visualization - Path Tracing, Cube sample"
puts "============"
puts ""
source $env(CSF_OCCTSamplesPath)/tcl/pathtrace_cube.tcl
vaxo
vfit
vfps 100
# Dump image produced with one-sided BSDFs
vdump $imagedir/${casename}_onesided.png
vrenderparams -twoside
vfps 100
# Dump image produced with two-sided BSDFs
vdump $imagedir/${casename}_twosided.png