mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0028126: Visualization, Path tracing - Provide ability to use two-sided scattering models
This commit is contained in:
@@ -28,9 +28,6 @@ public:
|
|||||||
//! Default pixels density.
|
//! Default pixels density.
|
||||||
static const unsigned int THE_DEFAULT_RESOLUTION = 72u;
|
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.
|
//! Default ray-tracing depth.
|
||||||
static const Standard_Integer THE_DEFAULT_DEPTH = 3;
|
static const Standard_Integer THE_DEFAULT_DEPTH = 3;
|
||||||
|
|
||||||
@@ -53,7 +50,6 @@ public:
|
|||||||
NbMsaaSamples (0),
|
NbMsaaSamples (0),
|
||||||
// ray tracing parameters
|
// ray tracing parameters
|
||||||
IsGlobalIlluminationEnabled (Standard_False),
|
IsGlobalIlluminationEnabled (Standard_False),
|
||||||
SamplesPerPixel (THE_DEFAULT_SPP),
|
|
||||||
RaytracingDepth (THE_DEFAULT_DEPTH),
|
RaytracingDepth (THE_DEFAULT_DEPTH),
|
||||||
IsShadowEnabled (Standard_True),
|
IsShadowEnabled (Standard_True),
|
||||||
IsReflectionEnabled (Standard_False),
|
IsReflectionEnabled (Standard_False),
|
||||||
@@ -63,6 +59,7 @@ public:
|
|||||||
CoherentPathTracingMode (Standard_False),
|
CoherentPathTracingMode (Standard_False),
|
||||||
AdaptiveScreenSampling (Standard_False),
|
AdaptiveScreenSampling (Standard_False),
|
||||||
ShowSamplingTiles (Standard_False),
|
ShowSamplingTiles (Standard_False),
|
||||||
|
TwoSidedBsdfModels (Standard_False),
|
||||||
RebuildRayTracingShaders (Standard_False),
|
RebuildRayTracingShaders (Standard_False),
|
||||||
// stereoscopic parameters
|
// stereoscopic parameters
|
||||||
StereoMode (Graphic3d_StereoMode_QuadBuffer),
|
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 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 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 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
|
Standard_Boolean RebuildRayTracingShaders; //!< forces rebuilding ray tracing shaders at the next frame
|
||||||
|
|
||||||
Graphic3d_StereoMode StereoMode; //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
|
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.
|
//! Enables/disables the use of OpenGL bindless textures.
|
||||||
Standard_Boolean UseBindlessTextures;
|
Standard_Boolean UseBindlessTextures;
|
||||||
|
|
||||||
|
//! Enables/disables two-sided BSDF models instead of one-sided.
|
||||||
|
Standard_Boolean TwoSidedBsdfModels;
|
||||||
|
|
||||||
//! Enables/disables adaptive screen sampling for path tracing.
|
//! Enables/disables adaptive screen sampling for path tracing.
|
||||||
Standard_Boolean AdaptiveScreenSampling;
|
Standard_Boolean AdaptiveScreenSampling;
|
||||||
|
|
||||||
@@ -706,10 +709,8 @@ protected: //! @name data types related to ray-tracing
|
|||||||
TransparentShadows (Standard_False),
|
TransparentShadows (Standard_False),
|
||||||
GlobalIllumination (Standard_False),
|
GlobalIllumination (Standard_False),
|
||||||
UseBindlessTextures (Standard_False),
|
UseBindlessTextures (Standard_False),
|
||||||
AdaptiveScreenSampling (Standard_False)
|
TwoSidedBsdfModels (Standard_False),
|
||||||
{
|
AdaptiveScreenSampling (Standard_False) { }
|
||||||
//
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Describes state of OpenGL structure.
|
//! 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());
|
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;
|
return aPrefixString;
|
||||||
@@ -1354,27 +1359,18 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces)
|
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.NbBounces = myRenderParams.RaytracingDepth;
|
||||||
aToRebuildShaders = Standard_True;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures)
|
|
||||||
{
|
|
||||||
myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
|
|
||||||
aToRebuildShaders = Standard_True;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows)
|
|
||||||
{
|
|
||||||
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
|
myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled;
|
||||||
aToRebuildShaders = Standard_True;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination)
|
|
||||||
{
|
|
||||||
myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
|
myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled;
|
||||||
|
myRaytraceParameters.TwoSidedBsdfModels = myRenderParams.TwoSidedBsdfModels;
|
||||||
|
myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
|
||||||
|
|
||||||
aToRebuildShaders = Standard_True;
|
aToRebuildShaders = Standard_True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -244,12 +244,12 @@ void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
// function : HandleLambertianReflection
|
// function : EvalLambertianReflection
|
||||||
// purpose : Handles Lambertian BRDF, with cos(N, PSI)
|
// 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
|
// function : EvalBlinnReflection
|
||||||
// purpose : Handles Blinn glossy BRDF, with cos(N, PSI)
|
// 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
|
// calculate the reflection half-vec
|
||||||
vec3 aH = normalize (theInput + theOutput);
|
vec3 aH = normalize (theWi + theWo);
|
||||||
|
|
||||||
// roughness value -> Blinn exponent
|
// roughness value -> Blinn exponent
|
||||||
float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);
|
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);
|
float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);
|
||||||
|
|
||||||
// calculate shadow-masking function
|
// 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 total amount of reflection
|
||||||
return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :
|
return (theWi.z <= 0.f || theWo.z <= 0.f) ? ZERO :
|
||||||
aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);
|
aD * aG / (4.f * theWo.z) * fresnelMedia (dot (theWo, aH), theFresnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
// function : HandleMaterial
|
// function : EvalMaterial
|
||||||
// purpose : Returns BSDF value for specified material, with cos(N, PSI)
|
// 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) +
|
#ifdef TWO_SIDED_BXDF
|
||||||
theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);
|
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
|
// function : SampleLambertianReflection
|
||||||
// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
|
// 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 aKsi1 = RandFloat();
|
||||||
float aKsi2 = RandFloat();
|
float aKsi2 = RandFloat();
|
||||||
|
|
||||||
float aTemp = sqrt (aKsi2);
|
theWi = vec3 (cos (M_2_PI * aKsi1),
|
||||||
|
sin (M_2_PI * aKsi1),
|
||||||
theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),
|
|
||||||
aTemp * sin (M_2_PI * aKsi1),
|
|
||||||
sqrt (1.f - aKsi2));
|
sqrt (1.f - aKsi2));
|
||||||
|
|
||||||
thePDF *= abs (theInput.z) * (1.f / M_PI);
|
theWi.xy *= sqrt (aKsi2);
|
||||||
|
|
||||||
return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;
|
#ifdef TWO_SIDED_BXDF
|
||||||
|
theWi.z *= sign (theWo.z);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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
|
// terms would be complex, and it is the D term that accounts
|
||||||
// for most of the variation.
|
// 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 aKsi1 = RandFloat();
|
||||||
float aKsi2 = RandFloat();
|
float aKsi2 = RandFloat();
|
||||||
@@ -367,56 +381,72 @@ vec3 SampleBlinnReflection (in vec3 theOutput, out vec3 theInput, in vec3 theFre
|
|||||||
// calculate PDF of sampled direction
|
// calculate PDF of sampled direction
|
||||||
thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);
|
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
|
// 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;
|
return ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jacobian of half-direction mapping
|
// Jacobian of half-direction mapping
|
||||||
thePDF /= 4.f * dot (theInput, aM);
|
thePDF /= 4.f * dot (theWi, aM);
|
||||||
|
|
||||||
// compute shadow-masking coefficient
|
// 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
|
// function : SampleSpecularReflection
|
||||||
// purpose : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)
|
// 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
|
// Sample input direction
|
||||||
theInput = vec3 (-theOutput.x,
|
theWi = vec3 (-theWo.x,
|
||||||
-theOutput.y,
|
-theWo.y,
|
||||||
theOutput.z);
|
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
|
// function : SampleSpecularTransmission
|
||||||
// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)
|
// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
vec3 SampleSpecularTransmission (in vec3 theOutput,
|
vec3 SampleSpecularTransmission (in vec3 theWo, out vec3 theWi, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)
|
||||||
out vec3 theInput, 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);
|
float aReflection = convolve (aFactor, theWeight);
|
||||||
|
|
||||||
// sample specular BRDF/BTDF
|
// sample specular BRDF/BTDF
|
||||||
if (RandFloat() <= aReflection)
|
if (RandFloat() <= aReflection)
|
||||||
{
|
{
|
||||||
theInput = vec3 (-theOutput.x,
|
theWi = vec3 (-theWo.x,
|
||||||
-theOutput.y,
|
-theWo.y,
|
||||||
theOutput.z);
|
theWo.z);
|
||||||
|
|
||||||
theWeight = aFactor * (1.f / aReflection);
|
theWeight = aFactor * (1.f / aReflection);
|
||||||
}
|
}
|
||||||
@@ -424,7 +454,7 @@ vec3 SampleSpecularTransmission (in vec3 theOutput,
|
|||||||
{
|
{
|
||||||
theInside = !theInside;
|
theInside = !theInside;
|
||||||
|
|
||||||
transmitted (theFresnel.y, theOutput, theInput);
|
transmitted (theFresnel.y, theWo, theWi);
|
||||||
|
|
||||||
theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));
|
theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));
|
||||||
}
|
}
|
||||||
@@ -438,10 +468,7 @@ vec3 SampleSpecularTransmission (in vec3 theOutput,
|
|||||||
// function : BsdfPdf
|
// function : BsdfPdf
|
||||||
// purpose : Calculates BSDF of sampling input knowing output
|
// purpose : Calculates BSDF of sampling input knowing output
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
float BsdfPdf (in SMaterial theBSDF,
|
float BsdfPdf (in SMaterial theBSDF, in vec3 theWo, in vec3 theWi, in vec3 theWeight)
|
||||||
in vec3 theOutput,
|
|
||||||
in vec3 theInput,
|
|
||||||
in vec3 theWeight)
|
|
||||||
{
|
{
|
||||||
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
|
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
|
||||||
float aPs = convolve (theBSDF.Ks.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
|
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
|
// roughness value --> Blinn exponent
|
||||||
float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);
|
float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);
|
||||||
|
|
||||||
aPDF = aPd * abs (theInput.z / M_PI) +
|
aPDF = aPd * abs (theWi.z / M_PI) +
|
||||||
aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (aHalf.z, aPower + 1.f) / (4.f * dot (theInput, aHalf));
|
aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / (4.f * dot (theWi, aH));
|
||||||
}
|
}
|
||||||
|
|
||||||
return aPDF / aReflection;
|
return aPDF / aReflection;
|
||||||
@@ -473,11 +500,7 @@ float BsdfPdf (in SMaterial theBSDF,
|
|||||||
// function : SampleBsdf
|
// function : SampleBsdf
|
||||||
// purpose : Samples specified composite material (BSDF)
|
// purpose : Samples specified composite material (BSDF)
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
float SampleBsdf (in SMaterial theBSDF,
|
float SampleBsdf (in SMaterial theBSDF, in vec3 theWo, out vec3 theWi, inout vec3 theWeight, inout bool theInside)
|
||||||
in vec3 theOutput,
|
|
||||||
out vec3 theInput,
|
|
||||||
inout vec3 theWeight,
|
|
||||||
inout bool theInside)
|
|
||||||
{
|
{
|
||||||
// compute probability of each reflection type (BxDF)
|
// compute probability of each reflection type (BxDF)
|
||||||
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
|
float aPd = convolve (theBSDF.Kd.rgb, theWeight);
|
||||||
@@ -497,13 +520,13 @@ float SampleBsdf (in SMaterial theBSDF,
|
|||||||
{
|
{
|
||||||
PICK_BXDF (aPd, theBSDF.Kd.rgb);
|
PICK_BXDF (aPd, theBSDF.Kd.rgb);
|
||||||
|
|
||||||
theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);
|
theWeight *= SampleLambertianReflection (theWo, theWi, aPDF);
|
||||||
}
|
}
|
||||||
else if (aKsi < aPd + aPs) // glossy reflection
|
else if (aKsi < aPd + aPs) // glossy reflection
|
||||||
{
|
{
|
||||||
PICK_BXDF (aPs, theBSDF.Ks.rgb);
|
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
|
else if (aKsi < aPd + aPs + aPr) // specular reflection
|
||||||
{
|
{
|
||||||
@@ -511,7 +534,7 @@ float SampleBsdf (in SMaterial theBSDF,
|
|||||||
|
|
||||||
aPDF = MAXFLOAT;
|
aPDF = MAXFLOAT;
|
||||||
|
|
||||||
theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);
|
theWeight *= SampleSpecularReflection (theWo, theWi, theBSDF.Fresnel);
|
||||||
}
|
}
|
||||||
else if (aKsi < aReflection) // specular transmission
|
else if (aKsi < aReflection) // specular transmission
|
||||||
{
|
{
|
||||||
@@ -519,7 +542,7 @@ float SampleBsdf (in SMaterial theBSDF,
|
|||||||
|
|
||||||
aPDF = MAXFLOAT;
|
aPDF = MAXFLOAT;
|
||||||
|
|
||||||
theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);
|
theWeight *= SampleSpecularTransmission (theWo, theWi, theWeight, theBSDF.Fresnel, theInside);
|
||||||
}
|
}
|
||||||
|
|
||||||
// path termination for extra small weights
|
// 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
|
// MIS weight including division by explicit PDF
|
||||||
float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);
|
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));
|
aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));
|
||||||
|
|
||||||
if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important
|
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"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : HandleLambertianReflection\n"
|
"// function : EvalLambertianReflection\n"
|
||||||
"// purpose : Handles Lambertian BRDF, with cos(N, PSI)\n"
|
"// purpose : Evaluates Lambertian BRDF, with cos(N, PSI)\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"float HandleLambertianReflection (in vec3 theInput, in vec3 theOutput)\n"
|
"float EvalLambertianReflection (in vec3 theWi, in vec3 theWo)\n"
|
||||||
"{\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"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
@@ -288,13 +288,13 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : HandleBlinnReflection\n"
|
"// function : EvalBlinnReflection\n"
|
||||||
"// purpose : Handles Blinn glossy BRDF, with cos(N, PSI)\n"
|
"// purpose : Evaluates Blinn glossy BRDF, with cos(N, PSI)\n"
|
||||||
"//=======================================================================\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"
|
"{\n"
|
||||||
" // calculate the reflection half-vec\n"
|
" // calculate the reflection half-vec\n"
|
||||||
" vec3 aH = normalize (theInput + theOutput);\n"
|
" vec3 aH = normalize (theWi + theWo);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // roughness value -> Blinn exponent\n"
|
" // roughness value -> Blinn exponent\n"
|
||||||
" float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\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"
|
" float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // calculate shadow-masking function\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"
|
"\n"
|
||||||
" // return total amount of reflection\n"
|
" // return total amount of reflection\n"
|
||||||
" return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO :\n"
|
" return (theWi.z <= 0.f || theWo.z <= 0.f) ? ZERO :\n"
|
||||||
" aD * aG / (4.f * theOutput.z) * fresnelMedia (dot (theOutput, aH), theFresnel);\n"
|
" aD * aG / (4.f * theWo.z) * fresnelMedia (dot (theWo, aH), theFresnel);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : HandleMaterial\n"
|
"// function : EvalMaterial\n"
|
||||||
"// purpose : Returns BSDF value for specified material, with cos(N, PSI)\n"
|
"// purpose : Evaluates BSDF for specified material, with cos(N, PSI)\n"
|
||||||
"//=======================================================================\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"
|
"{\n"
|
||||||
" return theBSDF.Kd.rgb * HandleLambertianReflection (theInput, theOutput) +\n"
|
"#ifdef TWO_SIDED_BXDF\n"
|
||||||
" theBSDF.Ks.rgb * HandleBlinnReflection (theInput, theOutput, theBSDF.Fresnel, theBSDF.Ks.w);\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"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : SampleLambertianReflection\n"
|
"// function : SampleLambertianReflection\n"
|
||||||
"// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
"// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
||||||
"//=======================================================================\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"
|
"{\n"
|
||||||
" float aKsi1 = RandFloat();\n"
|
" float aKsi1 = RandFloat();\n"
|
||||||
" float aKsi2 = RandFloat();\n"
|
" float aKsi2 = RandFloat();\n"
|
||||||
"\n"
|
"\n"
|
||||||
" float aTemp = sqrt (aKsi2);\n"
|
" theWi = vec3 (cos (M_2_PI * aKsi1),\n"
|
||||||
"\n"
|
" sin (M_2_PI * aKsi1),\n"
|
||||||
" theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),\n"
|
|
||||||
" aTemp * sin (M_2_PI * aKsi1),\n"
|
|
||||||
" sqrt (1.f - aKsi2));\n"
|
" sqrt (1.f - aKsi2));\n"
|
||||||
"\n"
|
"\n"
|
||||||
" thePDF *= abs (theInput.z) * (1.f / M_PI);\n"
|
" theWi.xy *= sqrt (aKsi2);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;\n"
|
"#ifdef TWO_SIDED_BXDF\n"
|
||||||
|
" theWi.z *= sign (theWo.z);\n"
|
||||||
|
"#endif\n"
|
||||||
|
"\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"
|
"\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"
|
"// terms would be complex, and it is the D term that accounts\n"
|
||||||
"// for most of the variation.\n"
|
"// for most of the variation.\n"
|
||||||
"//=======================================================================\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"
|
"{\n"
|
||||||
" float aKsi1 = RandFloat();\n"
|
" float aKsi1 = RandFloat();\n"
|
||||||
" float aKsi2 = RandFloat();\n"
|
" float aKsi2 = RandFloat();\n"
|
||||||
@@ -370,56 +384,72 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
" // calculate PDF of sampled direction\n"
|
" // calculate PDF of sampled direction\n"
|
||||||
" thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);\n"
|
" thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);\n"
|
||||||
"\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"
|
"\n"
|
||||||
" // pick input based on half direction\n"
|
" // pick input based on half direction\n"
|
||||||
" theInput = -theOutput + 2.f * aCosDelta * aM;\n"
|
" theWi = -theWo + 2.f * aCosDelta * aM;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (theInput.z <= 0.f || theOutput.z <= 0.f)\n"
|
" if (theWi.z <= 0.f || theWo.z <= 0.f)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" return ZERO;\n"
|
" return ZERO;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // Jacobian of half-direction mapping\n"
|
" // Jacobian of half-direction mapping\n"
|
||||||
" thePDF /= 4.f * dot (theInput, aM);\n"
|
" thePDF /= 4.f * dot (theWi, aM);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // compute shadow-masking coefficient\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"
|
"\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"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : SampleSpecularReflection\n"
|
"// function : SampleSpecularReflection\n"
|
||||||
"// purpose : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
"// purpose : Samples specular BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
||||||
"//=======================================================================\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"
|
"{\n"
|
||||||
" // Sample input direction\n"
|
" // Sample input direction\n"
|
||||||
" theInput = vec3 (-theOutput.x,\n"
|
" theWi = vec3 (-theWo.x,\n"
|
||||||
" -theOutput.y,\n"
|
" -theWo.y,\n"
|
||||||
" theOutput.z);\n"
|
" theWo.z);\n"
|
||||||
"\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"
|
"\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"// function : SampleSpecularTransmission\n"
|
"// function : SampleSpecularTransmission\n"
|
||||||
"// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
"// purpose : Samples specular BTDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"vec3 SampleSpecularTransmission (in vec3 theOutput,\n"
|
"vec3 SampleSpecularTransmission (in vec3 theWo, out vec3 theWi, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)\n"
|
||||||
" out vec3 theInput, in vec3 theWeight, in vec3 theFresnel, inout bool theInside)\n"
|
|
||||||
"{\n"
|
"{\n"
|
||||||
" vec3 aFactor = fresnelMedia (theOutput.z, theFresnel);\n"
|
" vec3 aFactor = fresnelMedia (theWo.z, theFresnel);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" float aReflection = convolve (aFactor, theWeight);\n"
|
" float aReflection = convolve (aFactor, theWeight);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // sample specular BRDF/BTDF\n"
|
" // sample specular BRDF/BTDF\n"
|
||||||
" if (RandFloat() <= aReflection)\n"
|
" if (RandFloat() <= aReflection)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" theInput = vec3 (-theOutput.x,\n"
|
" theWi = vec3 (-theWo.x,\n"
|
||||||
" -theOutput.y,\n"
|
" -theWo.y,\n"
|
||||||
" theOutput.z);\n"
|
" theWo.z);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" theWeight = aFactor * (1.f / aReflection);\n"
|
" theWeight = aFactor * (1.f / aReflection);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
@@ -427,7 +457,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
" {\n"
|
" {\n"
|
||||||
" theInside = !theInside;\n"
|
" theInside = !theInside;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" transmitted (theFresnel.y, theOutput, theInput);\n"
|
" transmitted (theFresnel.y, theWo, theWi);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));\n"
|
" theWeight = (UNIT - aFactor) * (1.f / (1.f - aReflection));\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
@@ -441,10 +471,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"// function : BsdfPdf\n"
|
"// function : BsdfPdf\n"
|
||||||
"// purpose : Calculates BSDF of sampling input knowing output\n"
|
"// purpose : Calculates BSDF of sampling input knowing output\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"float BsdfPdf (in SMaterial theBSDF,\n"
|
"float BsdfPdf (in SMaterial theBSDF, in vec3 theWo, in vec3 theWi, in vec3 theWeight)\n"
|
||||||
" in vec3 theOutput,\n"
|
|
||||||
" in vec3 theInput,\n"
|
|
||||||
" in vec3 theWeight)\n"
|
|
||||||
"{\n"
|
"{\n"
|
||||||
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
|
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
|
||||||
" float aPs = convolve (theBSDF.Ks.rgb, theWeight);\n"
|
" float aPs = convolve (theBSDF.Ks.rgb, theWeight);\n"
|
||||||
@@ -455,15 +482,15 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"\n"
|
"\n"
|
||||||
" float aPDF = 0.f; // PDF of sampling input direction\n"
|
" float aPDF = 0.f; // PDF of sampling input direction\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (theInput.z * theOutput.z > 0.f)\n"
|
" if (theWi.z * theWo.z > 0.f)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" vec3 aHalf = normalize (theInput + theOutput);\n"
|
" vec3 aH = normalize (theWi + theWo);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // roughness value --> Blinn exponent\n"
|
" // roughness value --> Blinn exponent\n"
|
||||||
" float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);\n"
|
" float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" aPDF = aPd * abs (theInput.z / M_PI) +\n"
|
" aPDF = aPd * abs (theWi.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"
|
" aPs * (aPower + 2.f) * (1.f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / (4.f * dot (theWi, aH));\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" return aPDF / aReflection;\n"
|
" return aPDF / aReflection;\n"
|
||||||
@@ -476,11 +503,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"// function : SampleBsdf\n"
|
"// function : SampleBsdf\n"
|
||||||
"// purpose : Samples specified composite material (BSDF)\n"
|
"// purpose : Samples specified composite material (BSDF)\n"
|
||||||
"//=======================================================================\n"
|
"//=======================================================================\n"
|
||||||
"float SampleBsdf (in SMaterial theBSDF,\n"
|
"float SampleBsdf (in SMaterial theBSDF, in vec3 theWo, out vec3 theWi, inout vec3 theWeight, inout bool theInside)\n"
|
||||||
" in vec3 theOutput,\n"
|
|
||||||
" out vec3 theInput,\n"
|
|
||||||
" inout vec3 theWeight,\n"
|
|
||||||
" inout bool theInside)\n"
|
|
||||||
"{\n"
|
"{\n"
|
||||||
" // compute probability of each reflection type (BxDF)\n"
|
" // compute probability of each reflection type (BxDF)\n"
|
||||||
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
|
" float aPd = convolve (theBSDF.Kd.rgb, theWeight);\n"
|
||||||
@@ -500,13 +523,13 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
" {\n"
|
" {\n"
|
||||||
" PICK_BXDF (aPd, theBSDF.Kd.rgb);\n"
|
" PICK_BXDF (aPd, theBSDF.Kd.rgb);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" theWeight *= SampleLambertianReflection (theOutput, theInput, aPDF);\n"
|
" theWeight *= SampleLambertianReflection (theWo, theWi, aPDF);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else if (aKsi < aPd + aPs) // glossy reflection\n"
|
" else if (aKsi < aPd + aPs) // glossy reflection\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" PICK_BXDF (aPs, theBSDF.Ks.rgb);\n"
|
" PICK_BXDF (aPs, theBSDF.Ks.rgb);\n"
|
||||||
"\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"
|
" }\n"
|
||||||
" else if (aKsi < aPd + aPs + aPr) // specular reflection\n"
|
" else if (aKsi < aPd + aPs + aPr) // specular reflection\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@@ -514,7 +537,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"\n"
|
"\n"
|
||||||
" aPDF = MAXFLOAT;\n"
|
" aPDF = MAXFLOAT;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" theWeight *= SampleSpecularReflection (theOutput, theInput, theBSDF.Fresnel);\n"
|
" theWeight *= SampleSpecularReflection (theWo, theWi, theBSDF.Fresnel);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else if (aKsi < aReflection) // specular transmission\n"
|
" else if (aKsi < aReflection) // specular transmission\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@@ -522,7 +545,7 @@ static const char Shaders_PathtraceBase_fs[] =
|
|||||||
"\n"
|
"\n"
|
||||||
" aPDF = MAXFLOAT;\n"
|
" aPDF = MAXFLOAT;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" theWeight *= SampleSpecularTransmission (theOutput, theInput, theWeight, theBSDF.Fresnel, theInside);\n"
|
" theWeight *= SampleSpecularTransmission (theWo, theWi, theWeight, theBSDF.Fresnel, theInside);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // path termination for extra small weights\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"
|
" // MIS weight including division by explicit PDF\n"
|
||||||
" float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
|
" float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
|
||||||
"\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"
|
" aMaterial, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important\n"
|
" if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important\n"
|
||||||
|
@@ -9087,6 +9087,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
|||||||
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
|
theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
|
||||||
theDI << "iss: " << (aParams.AdaptiveScreenSampling ? "on" : "off") << "\n";
|
theDI << "iss: " << (aParams.AdaptiveScreenSampling ? "on" : "off") << "\n";
|
||||||
theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
|
theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
|
||||||
|
theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels ? "on" : "off") << "\n";
|
||||||
theDI << "shadingModel: ";
|
theDI << "shadingModel: ";
|
||||||
switch (aView->ShadingModel())
|
switch (aView->ShadingModel())
|
||||||
{
|
{
|
||||||
@@ -9360,6 +9361,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
|||||||
}
|
}
|
||||||
aParams.UseEnvironmentMapBackground = toEnable;
|
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"
|
else if (aFlag == "-shademodel"
|
||||||
|| aFlag == "-shadingmodel"
|
|| aFlag == "-shadingmodel"
|
||||||
|| aFlag == "-shading")
|
|| aFlag == "-shading")
|
||||||
@@ -10633,6 +10650,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
|||||||
"\n '-gi on|off' Enables/disables global illumination effects"
|
"\n '-gi on|off' Enables/disables global illumination effects"
|
||||||
"\n '-brng on|off' Enables/disables blocked RNG (fast coherent PT)"
|
"\n '-brng on|off' Enables/disables blocked RNG (fast coherent PT)"
|
||||||
"\n '-env on|off' Enables/disables environment map background"
|
"\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 '-iss on|off' Enables/disables adaptive screen sampling (PT mode)"
|
||||||
"\n '-issd on|off' Shows screen sampling distribution in ISS mode"
|
"\n '-issd on|off' Shows screen sampling distribution in ISS mode"
|
||||||
"\n '-rebuildGlsl on|off' Rebuild Ray-Tracing GLSL programs (for debugging)"
|
"\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
|
Reference in New Issue
Block a user