0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model
[occt.git] / src / Shaders / Shaders_PBREnvBaking_fs.pxx
diff --git a/src/Shaders/Shaders_PBREnvBaking_fs.pxx b/src/Shaders/Shaders_PBREnvBaking_fs.pxx
new file mode 100644 (file)
index 0000000..bc995ac
--- /dev/null
@@ -0,0 +1,165 @@
+// This file has been automatically generated from resource file src/Shaders/PBREnvBaking.fs
+
+static const char Shaders_PBREnvBaking_fs[] =
+  "THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap\n"
+  "\n"
+  "uniform int uSamplesNum;     //!< number of samples in Monte-Carlo integration\n"
+  "uniform int uCurrentLevel;   //!< current level of specular IBL map (ignored in case of diffuse map's processing)\n"
+  "uniform int uEnvMapSize;     //!< one edge's size of source environtment map's zero mipmap level\n"
+  "uniform int uYCoeff;         //!< coefficient of Y controlling horizontal flip of cubemap\n"
+  "uniform int uZCoeff;         //!< coefficient of Z controlling vertical flip of cubemap\n"
+  "uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)\n"
+  "\n"
+  "//! Returns coordinates of point theNumber from Hammersley point set having size theSize.\n"
+  "vec2 hammersley (in int theNumber,\n"
+  "                 in int theSize)\n"
+  "{\n"
+  "  int aDenominator = 2;\n"
+  "  int aNumber = theNumber;\n"
+  "  float aVanDerCorput = 0.0;\n"
+  "  for (int i = 0; i < 32; ++i)\n"
+  "  {\n"
+  "    if (aNumber > 0)\n"
+  "    {\n"
+  "      aVanDerCorput += float(aNumber % 2) / float(aDenominator);\n"
+  "      aNumber /= 2;\n"
+  "      aDenominator *= 2;\n"
+  "    }\n"
+  "  }\n"
+  "  return vec2(float(theNumber) / float(theSize), aVanDerCorput);\n"
+  "}\n"
+  "\n"
+  "//! This function does importance sampling on hemisphere surface using GGX normal distribution function\n"
+  "//! in tangent space (positive z axis is surface normal direction).\n"
+  "vec3 importanceSample (in vec2  theHammersleyPoint,\n"
+  "                       in float theRoughness)\n"
+  "{\n"
+  "  float aPhi = PI_2 * theHammersleyPoint.x;\n"
+  "  theRoughness *= theRoughness;\n"
+  "  theRoughness *= theRoughness;\n"
+  "  float aCosTheta = sqrt((1.0 - theHammersleyPoint.y) / (1.0 + (theRoughness - 1.0) * theHammersleyPoint.y));\n"
+  "  float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n"
+  "  return vec3(aSinTheta * cos(aPhi),\n"
+  "              aSinTheta * sin(aPhi),\n"
+  "              aCosTheta);\n"
+  "}\n"
+  "\n"
+  "//! This function uniformly generates samples on whole sphere.\n"
+  "vec3 sphereUniformSample (in vec2 theHammersleyPoint)\n"
+  "{\n"
+  "  float aPhi = PI_2 * theHammersleyPoint.x;\n"
+  "  float aCosTheta = 2.0 * theHammersleyPoint.y - 1.0;\n"
+  "  float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n"
+  "  return vec3(aSinTheta * cos(aPhi),\n"
+  "              aSinTheta * sin(aPhi),\n"
+  "              aCosTheta);\n"
+  "}\n"
+  "\n"
+  "//! Transforms resulted sampled direction from tangent space to world space considering the surface normal.\n"
+  "vec3 fromTangentSpace (in vec3 theVector,\n"
+  "                       in vec3 theNormal)\n"
+  "{\n"
+  "  vec3 anUp = (abs(theNormal.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n"
+  "  vec3 anX = normalize(cross(anUp, theNormal));\n"
+  "  vec3 anY = cross(theNormal, anX);\n"
+  "  return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;\n"
+  "}\n"
+  "\n"
+  "const float aSHBasisFuncCoeffs[9] = float[9]\n"
+  "(\n"
+  "  0.282095 * 0.282095,\n"
+  "  0.488603 * 0.488603,\n"
+  "  0.488603 * 0.488603,\n"
+  "  0.488603 * 0.488603,\n"
+  "  1.092548 * 1.092548,\n"
+  "  1.092548 * 1.092548,\n"
+  "  1.092548 * 1.092548,\n"
+  "  0.315392 * 0.315392,\n"
+  "  0.546274 * 0.546274\n"
+  ");\n"
+  "\n"
+  "const float aSHCosCoeffs[9] = float[9]\n"
+  "(\n"
+  "  3.141593,\n"
+  "  2.094395,\n"
+  "  2.094395,\n"
+  "  2.094395,\n"
+  "  0.785398,\n"
+  "  0.785398,\n"
+  "  0.785398,\n"
+  "  0.785398,\n"
+  "  0.785398\n"
+  ");\n"
+  "\n"
+  "//! Bakes diffuse IBL map's spherical harmonics coefficients.\n"
+  "vec3 bakeDiffuseSH()\n"
+  "{\n"
+  "  int anIndex = int(gl_FragCoord.x);\n"
+  "  vec3 aResult = vec3 (0.0);\n"
+  "  for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)\n"
+  "  {\n"
+  "    vec2 aHammersleyPoint = hammersley (aSampleIter, uSamplesNum);\n"
+  "    vec3 aDirection = sphereUniformSample (aHammersleyPoint);\n"
+  "\n"
+  "    vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;\n"
+  "\n"
+  "    float aBasisFunc[9];\n"
+  "    aBasisFunc[0] = 1.0;\n"
+  "\n"
+  "    aBasisFunc[1] = aDirection.x;\n"
+  "    aBasisFunc[2] = aDirection.y;\n"
+  "    aBasisFunc[3] = aDirection.z;\n"
+  "\n"
+  "    aBasisFunc[4] = aDirection.x * aDirection.z;\n"
+  "    aBasisFunc[5] = aDirection.y * aDirection.z;\n"
+  "    aBasisFunc[6] = aDirection.x * aDirection.y;\n"
+  "\n"
+  "    aBasisFunc[7] = 3.0 * aDirection.z * aDirection.z - 1.0;\n"
+  "    aBasisFunc[8] = aDirection.x * aDirection.x - aDirection.y * aDirection.y;\n"
+  "\n"
+  "    aResult += aValue * aBasisFunc[anIndex];\n"
+  "  }\n"
+  "\n"
+  "  aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);\n"
+  "  return aResult;\n"
+  "}\n"
+  "\n"
+  "//! Bakes specular IBL map.\n"
+  "vec3 bakeSpecularMap (in vec3  theNormal,\n"
+  "                      in float theRoughness)\n"
+  "{\n"
+  "  vec3 aResult = vec3(0.0);\n"
+  "  float aWeightSum = 0.0;\n"
+  "  int aSamplesNum = (theRoughness == 0.0) ? 1 : uSamplesNum;\n"
+  "  float aSolidAngleSource = 4.0 * PI / (6.0 * float(uEnvMapSize * uEnvMapSize));\n"
+  "  for (int aSampleIter = 0; aSampleIter < aSamplesNum; ++aSampleIter)\n"
+  "  {\n"
+  "    vec2 aHammersleyPoint = hammersley (aSampleIter, aSamplesNum);\n"
+  "    vec3 aHalf = importanceSample (aHammersleyPoint, occRoughness (theRoughness));\n"
+  "    float aHdotV = aHalf.z;\n"
+  "    aHalf = fromTangentSpace (aHalf, theNormal);\n"
+  "    vec3  aLight = -reflect (theNormal, aHalf);\n"
+  "    float aNdotL = dot (aLight, theNormal);\n"
+  "    if (aNdotL > 0.0)\n"
+  "    {\n"
+  "      float aSolidAngleSample = 1.0 / (float(aSamplesNum) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);\n"
+  "      float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / aSolidAngleSource);\n"
+  "      aResult += occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL;\n"
+  "      aWeightSum += aNdotL;\n"
+  "    }\n"
+  "  }\n"
+  "  return aResult / aWeightSum;\n"
+  "}\n"
+  "\n"
+  "void main()\n"
+  "{\n"
+  "  vec3 aViewDirection = normalize (ViewDirection);\n"
+  "  if (occNbSpecIBLLevels == 0)\n"
+  "  {\n"
+  "    occSetFragColor (vec4 (bakeDiffuseSH (), 1.0));\n"
+  "  }\n"
+  "  else\n"
+  "  {\n"
+  "    occSetFragColor (vec4 (bakeSpecularMap (aViewDirection, float(uCurrentLevel) / float(occNbSpecIBLLevels - 1)), 1.0));\n"
+  "  }\n"
+  "}\n";