1
0
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:
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

@@ -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"