0032083: Visualization, TKOpenGl - PBR rendering is unavailable on Apple A12 Bionic...
[occt.git] / src / Shaders / Shaders_PBREnvBaking_fs.pxx
index bc995ac..183773b 100644 (file)
@@ -3,13 +3,23 @@
 static const char Shaders_PBREnvBaking_fs[] =
   "THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap\n"
   "\n"
+  "#if (__VERSION__ >= 120)\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"
+  "#else\n"
+  "const int uSamplesNum = 256;\n"
+  "#endif\n"
   "uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)\n"
   "\n"
+  "#ifdef THE_TO_BAKE_DIFFUSE\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"
+  "#endif\n"
+  "\n"
+  "#ifdef THE_TO_BAKE_SPECULAR\n"
+  "uniform int   uCurrentLevel;        //!< current level of specular IBL map (ignored in case of diffuse map's processing)\n"
+  "uniform float uEnvSolidAngleSource; //!< source solid angle sample computed from one edge's size of source environment map's zero mipmap level\n"
+  "#endif\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"
@@ -21,7 +31,7 @@ static const char Shaders_PBREnvBaking_fs[] =
   "  {\n"
   "    if (aNumber > 0)\n"
   "    {\n"
-  "      aVanDerCorput += float(aNumber % 2) / float(aDenominator);\n"
+  "      aVanDerCorput += mod(float(aNumber), 2.0) / float(aDenominator);\n"
   "      aNumber /= 2;\n"
   "      aDenominator *= 2;\n"
   "    }\n"
@@ -65,6 +75,8 @@ static const char Shaders_PBREnvBaking_fs[] =
   "  return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;\n"
   "}\n"
   "\n"
+  "#ifdef THE_TO_BAKE_DIFFUSE\n"
+  "#if (__VERSION__ >= 120)\n"
   "const float aSHBasisFuncCoeffs[9] = float[9]\n"
   "(\n"
   "  0.282095 * 0.282095,\n"
@@ -77,7 +89,6 @@ static const char Shaders_PBREnvBaking_fs[] =
   "  0.315392 * 0.315392,\n"
   "  0.546274 * 0.546274\n"
   ");\n"
-  "\n"
   "const float aSHCosCoeffs[9] = float[9]\n"
   "(\n"
   "  3.141593,\n"
@@ -90,76 +101,129 @@ static const char Shaders_PBREnvBaking_fs[] =
   "  0.785398,\n"
   "  0.785398\n"
   ");\n"
+  "#else\n"
+  "uniform float aSHBasisFuncCoeffs[9];\n"
+  "uniform float aSHCosCoeffs[9];\n"
+  "#endif\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"
+  "  int anId = int(gl_FragCoord.x);\n"
+  "  float aCoef;\n"
+  "#if (__VERSION__ >= 120)\n"
+  "  aCoef = aSHCosCoeffs[anId] * aSHBasisFuncCoeffs[anId];\n"
+  "#else\n"
+  "  if      (anId == 0) { aCoef = aSHCosCoeffs[0] * aSHBasisFuncCoeffs[0]; }\n"
+  "  else if (anId == 1) { aCoef = aSHCosCoeffs[1] * aSHBasisFuncCoeffs[1]; }\n"
+  "  else if (anId == 2) { aCoef = aSHCosCoeffs[2] * aSHBasisFuncCoeffs[2]; }\n"
+  "  else if (anId == 3) { aCoef = aSHCosCoeffs[3] * aSHBasisFuncCoeffs[3]; }\n"
+  "  else if (anId == 4) { aCoef = aSHCosCoeffs[4] * aSHBasisFuncCoeffs[4]; }\n"
+  "  else if (anId == 5) { aCoef = aSHCosCoeffs[5] * aSHBasisFuncCoeffs[5]; }\n"
+  "  else if (anId == 6) { aCoef = aSHCosCoeffs[6] * aSHBasisFuncCoeffs[6]; }\n"
+  "  else if (anId == 7) { aCoef = aSHCosCoeffs[7] * aSHBasisFuncCoeffs[7]; }\n"
+  "  else                { aCoef = aSHCosCoeffs[8] * aSHBasisFuncCoeffs[8]; }\n"
+  "#endif\n"
+  "  vec3 aRes = 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"
+  "    vec3 aDir = sphereUniformSample (aHammersleyPoint);\n"
+  "\n"
+  "    vec3 aVal = occTextureCube (uEnvMap, cubemapVectorTransform (aDir, uYCoeff, uZCoeff)).rgb;\n"
+  "  #if (__VERSION__ >= 120)\n"
+  "    float aFunc[9];\n"
+  "    aFunc[0] = 1.0;\n"
+  "\n"
+  "    aFunc[1] = aDir.x;\n"
+  "    aFunc[2] = aDir.y;\n"
+  "    aFunc[3] = aDir.z;\n"
+  "\n"
+  "    aFunc[4] = aDir.x * aDir.z;\n"
+  "    aFunc[5] = aDir.y * aDir.z;\n"
+  "    aFunc[6] = aDir.x * aDir.y;\n"
+  "\n"
+  "    aFunc[7] = 3.0 * aDir.z * aDir.z - 1.0;\n"
+  "    aFunc[8] = aDir.x * aDir.x - aDir.y * aDir.y;\n"
+  "\n"
+  "    aRes += aVal * aFunc[anId];\n"
+  "  #else\n"
+  "    if      (anId == 0) { aRes += aVal * 1.0; }\n"
+  "    else if (anId == 1) { aRes += aVal * aDir.x; }\n"
+  "    else if (anId == 2) { aRes += aVal * aDir.y; }\n"
+  "    else if (anId == 3) { aRes += aVal * aDir.z; }\n"
+  "    else if (anId == 4) { aRes += aVal * (aDir.x * aDir.z); }\n"
+  "    else if (anId == 5) { aRes += aVal * (aDir.y * aDir.z); }\n"
+  "    else if (anId == 6) { aRes += aVal * (aDir.x * aDir.y); }\n"
+  "    else if (anId == 7) { aRes += aVal * (3.0 * aDir.z * aDir.z - 1.0); }\n"
+  "    else                { aRes += aVal * (aDir.x * aDir.x - aDir.y * aDir.y); }\n"
+  "  #endif\n"
   "  }\n"
   "\n"
-  "  aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);\n"
-  "  return aResult;\n"
+  "  return 4.0 * aRes * aCoef / float(uSamplesNum);\n"
+  "}\n"
+  "#endif\n"
+  "\n"
+  "#ifdef THE_TO_BAKE_SPECULAR\n"
+  "//! Computes a single sample for specular IBL map.\n"
+  "vec4 specularMapSample (in vec3  theNormal,\n"
+  "                        in float theRoughness,\n"
+  "                        in int   theNumber,\n"
+  "                        in int   theSize)\n"
+  "{\n"
+  "  vec2 aHammersleyPoint = hammersley (theNumber, theSize);\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(theSize) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);\n"
+  "    float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / uEnvSolidAngleSource);\n"
+  "    return vec4 (occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL, aNdotL);\n"
+  "  }\n"
+  "  return vec4 (0.0);\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"
+  "  vec4 aResult = vec4(0.0);\n"
+  "  if (theRoughness == 0.0)\n"
+  "  {\n"
+  "    aResult = specularMapSample (theNormal, theRoughness, 0, 1);\n"
+  "  }\n"
+  "  else\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"
+  "    for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)\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"
+  "      aResult += specularMapSample (theNormal, theRoughness, aSampleIter, uSamplesNum);\n"
   "    }\n"
   "  }\n"
-  "  return aResult / aWeightSum;\n"
+  "  return aResult.xyz / aResult.w;\n"
   "}\n"
+  "#endif\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"
+  "#ifdef THE_TO_BAKE_DIFFUSE\n"
+  "  vec4 aRes = vec4 (bakeDiffuseSH(), 1.0);\n"
+  "#ifdef THE_TO_PACK_FLOAT\n"
+  "  int aCompIndex = int(gl_FragCoord.y);\n"
+  "  float aComp = aCompIndex == 0 ? aRes.x : (aCompIndex == 1 ? aRes.y : aRes.z);\n"
+  "  int aFixedPrec = int(aComp * 2147483647.0);\n"
+  "  int aFixedDiv1 = aFixedPrec / 256;\n"
+  "  int aFixedDiv2 = aFixedDiv1 / 256;\n"
+  "  int aFixedDiv3 = aFixedDiv2 / 256;\n"
+  "  vec4 aPacked = vec4(float(aFixedPrec), float(aFixedDiv1), float(aFixedDiv2), float(aFixedDiv3));\n"
+  "  aRes = fract (aPacked * (1.0 / 256.0));\n"
+  "#endif\n"
+  "  occFragColor = aRes;\n"
+  "#else\n"
+  "  float aRoughness = float(uCurrentLevel) / float(occNbSpecIBLLevels - 1);\n"
+  "  occFragColor = vec4 (bakeSpecularMap (aViewDirection, aRoughness), 1.0);\n"
+  "#endif\n"
   "}\n";