0028126: Visualization, Path tracing - Provide ability to use two-sided scattering...
[occt.git] / src / Shaders / Shaders_PathtraceBase_fs.pxx
index 187e127..59b0fb3 100644 (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"
+  "  theWi.xy *= sqrt (aKsi2);\n"
   "\n"
-  "  theInput = vec3 (aTemp * cos (M_2_PI * aKsi1),\n"
-  "                   aTemp * sin (M_2_PI * aKsi1),\n"
-  "                   sqrt (1.f - aKsi2));\n"
+  "#ifdef TWO_SIDED_BXDF\n"
+  "  theWi.z *= sign (theWo.z);\n"
+  "#endif\n"
   "\n"
-  "  thePDF *= abs (theInput.z) * (1.f / M_PI);\n"
+  "  thePDF *= theWi.z * (1.f / M_PI);\n"
   "\n"
-  "  return (theInput.z <= 0.f || theOutput.z <= 0.f) ? ZERO : UNIT;\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"
+  "#ifdef TWO_SIDED_BXDF\n"
+  "  if (toFlip)\n"
+  "    theWi.z = -theWi.z;\n"
+  "#endif\n"
   "\n"
-  "  return aG * aCosDelta / (theOutput.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);\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"
-  "\n"
-  "  return fresnelMedia (theOutput.z, theFresnel);\n"
+  "  theWi = vec3 (-theWo.x,\n"
+  "                -theWo.y,\n"
+  "                 theWo.z);\n"
+  "\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"