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:
@@ -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"
|
||||
|
Reference in New Issue
Block a user