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:
parent
a148c938b0
commit
b4327ba8df
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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)"
|
||||
|
19
tests/v3d/raytrace/sample_cube_twosided
Normal file
19
tests/v3d/raytrace/sample_cube_twosided
Normal 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
|
Loading…
x
Reference in New Issue
Block a user