mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-01 17:36:21 +03:00
Reorganized resources to keep source part in src and real-time scripts in resource folder. For the installation result no changes, still installed to src for windows.
227 lines
7.5 KiB
GLSL
227 lines
7.5 KiB
GLSL
THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap
|
|
|
|
#if (__VERSION__ >= 120)
|
|
uniform int uSamplesNum; //!< number of samples in Monte-Carlo integration
|
|
#else
|
|
const int uSamplesNum = 256;
|
|
#endif
|
|
uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)
|
|
|
|
#ifdef THE_TO_BAKE_DIFFUSE
|
|
uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap
|
|
uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap
|
|
#endif
|
|
|
|
#ifdef THE_TO_BAKE_SPECULAR
|
|
uniform int uCurrentLevel; //!< current level of specular IBL map (ignored in case of diffuse map's processing)
|
|
uniform float uEnvSolidAngleSource; //!< source solid angle sample computed from one edge's size of source environment map's zero mipmap level
|
|
#endif
|
|
|
|
//! Returns coordinates of point theNumber from Hammersley point set having size theSize.
|
|
vec2 hammersley (in int theNumber,
|
|
in int theSize)
|
|
{
|
|
int aDenominator = 2;
|
|
int aNumber = theNumber;
|
|
float aVanDerCorput = 0.0;
|
|
for (int i = 0; i < 32; ++i)
|
|
{
|
|
if (aNumber > 0)
|
|
{
|
|
aVanDerCorput += mod(float(aNumber), 2.0) / float(aDenominator);
|
|
aNumber /= 2;
|
|
aDenominator *= 2;
|
|
}
|
|
}
|
|
return vec2(float(theNumber) / float(theSize), aVanDerCorput);
|
|
}
|
|
|
|
//! This function does importance sampling on hemisphere surface using GGX normal distribution function
|
|
//! in tangent space (positive z axis is surface normal direction).
|
|
vec3 importanceSample (in vec2 theHammersleyPoint,
|
|
in float theRoughness)
|
|
{
|
|
float aPhi = PI_2 * theHammersleyPoint.x;
|
|
theRoughness *= theRoughness;
|
|
theRoughness *= theRoughness;
|
|
float aCosTheta = sqrt((1.0 - theHammersleyPoint.y) / (1.0 + (theRoughness - 1.0) * theHammersleyPoint.y));
|
|
float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);
|
|
return vec3(aSinTheta * cos(aPhi),
|
|
aSinTheta * sin(aPhi),
|
|
aCosTheta);
|
|
}
|
|
|
|
//! This function uniformly generates samples on whole sphere.
|
|
vec3 sphereUniformSample (in vec2 theHammersleyPoint)
|
|
{
|
|
float aPhi = PI_2 * theHammersleyPoint.x;
|
|
float aCosTheta = 2.0 * theHammersleyPoint.y - 1.0;
|
|
float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);
|
|
return vec3(aSinTheta * cos(aPhi),
|
|
aSinTheta * sin(aPhi),
|
|
aCosTheta);
|
|
}
|
|
|
|
//! Transforms resulted sampled direction from tangent space to world space considering the surface normal.
|
|
vec3 fromTangentSpace (in vec3 theVector,
|
|
in vec3 theNormal)
|
|
{
|
|
vec3 anUp = (abs(theNormal.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
vec3 anX = normalize(cross(anUp, theNormal));
|
|
vec3 anY = cross(theNormal, anX);
|
|
return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;
|
|
}
|
|
|
|
#ifdef THE_TO_BAKE_DIFFUSE
|
|
#if (__VERSION__ >= 120)
|
|
const float aSHBasisFuncCoeffs[9] = float[9]
|
|
(
|
|
0.282095 * 0.282095,
|
|
0.488603 * 0.488603,
|
|
0.488603 * 0.488603,
|
|
0.488603 * 0.488603,
|
|
1.092548 * 1.092548,
|
|
1.092548 * 1.092548,
|
|
1.092548 * 1.092548,
|
|
0.315392 * 0.315392,
|
|
0.546274 * 0.546274
|
|
);
|
|
const float aSHCosCoeffs[9] = float[9]
|
|
(
|
|
3.141593,
|
|
2.094395,
|
|
2.094395,
|
|
2.094395,
|
|
0.785398,
|
|
0.785398,
|
|
0.785398,
|
|
0.785398,
|
|
0.785398
|
|
);
|
|
#else
|
|
uniform float aSHBasisFuncCoeffs[9];
|
|
uniform float aSHCosCoeffs[9];
|
|
#endif
|
|
|
|
//! Bakes diffuse IBL map's spherical harmonics coefficients.
|
|
vec3 bakeDiffuseSH()
|
|
{
|
|
int anId = int(gl_FragCoord.x);
|
|
float aCoef;
|
|
#if (__VERSION__ >= 120)
|
|
aCoef = aSHCosCoeffs[anId] * aSHBasisFuncCoeffs[anId];
|
|
#else
|
|
if (anId == 0) { aCoef = aSHCosCoeffs[0] * aSHBasisFuncCoeffs[0]; }
|
|
else if (anId == 1) { aCoef = aSHCosCoeffs[1] * aSHBasisFuncCoeffs[1]; }
|
|
else if (anId == 2) { aCoef = aSHCosCoeffs[2] * aSHBasisFuncCoeffs[2]; }
|
|
else if (anId == 3) { aCoef = aSHCosCoeffs[3] * aSHBasisFuncCoeffs[3]; }
|
|
else if (anId == 4) { aCoef = aSHCosCoeffs[4] * aSHBasisFuncCoeffs[4]; }
|
|
else if (anId == 5) { aCoef = aSHCosCoeffs[5] * aSHBasisFuncCoeffs[5]; }
|
|
else if (anId == 6) { aCoef = aSHCosCoeffs[6] * aSHBasisFuncCoeffs[6]; }
|
|
else if (anId == 7) { aCoef = aSHCosCoeffs[7] * aSHBasisFuncCoeffs[7]; }
|
|
else { aCoef = aSHCosCoeffs[8] * aSHBasisFuncCoeffs[8]; }
|
|
#endif
|
|
vec3 aRes = vec3 (0.0);
|
|
for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)
|
|
{
|
|
vec2 aHammersleyPoint = hammersley (aSampleIter, uSamplesNum);
|
|
vec3 aDir = sphereUniformSample (aHammersleyPoint);
|
|
|
|
vec3 aVal = occTextureCube (uEnvMap, cubemapVectorTransform (aDir, uYCoeff, uZCoeff)).rgb;
|
|
#if (__VERSION__ >= 120)
|
|
float aFunc[9];
|
|
aFunc[0] = 1.0;
|
|
|
|
aFunc[1] = aDir.x;
|
|
aFunc[2] = aDir.y;
|
|
aFunc[3] = aDir.z;
|
|
|
|
aFunc[4] = aDir.x * aDir.z;
|
|
aFunc[5] = aDir.y * aDir.z;
|
|
aFunc[6] = aDir.x * aDir.y;
|
|
|
|
aFunc[7] = 3.0 * aDir.z * aDir.z - 1.0;
|
|
aFunc[8] = aDir.x * aDir.x - aDir.y * aDir.y;
|
|
|
|
aRes += aVal * aFunc[anId];
|
|
#else
|
|
if (anId == 0) { aRes += aVal * 1.0; }
|
|
else if (anId == 1) { aRes += aVal * aDir.x; }
|
|
else if (anId == 2) { aRes += aVal * aDir.y; }
|
|
else if (anId == 3) { aRes += aVal * aDir.z; }
|
|
else if (anId == 4) { aRes += aVal * (aDir.x * aDir.z); }
|
|
else if (anId == 5) { aRes += aVal * (aDir.y * aDir.z); }
|
|
else if (anId == 6) { aRes += aVal * (aDir.x * aDir.y); }
|
|
else if (anId == 7) { aRes += aVal * (3.0 * aDir.z * aDir.z - 1.0); }
|
|
else { aRes += aVal * (aDir.x * aDir.x - aDir.y * aDir.y); }
|
|
#endif
|
|
}
|
|
|
|
return 4.0 * aRes * aCoef / float(uSamplesNum);
|
|
}
|
|
#endif
|
|
|
|
#ifdef THE_TO_BAKE_SPECULAR
|
|
//! Computes a single sample for specular IBL map.
|
|
vec4 specularMapSample (in vec3 theNormal,
|
|
in float theRoughness,
|
|
in int theNumber,
|
|
in int theSize)
|
|
{
|
|
vec2 aHammersleyPoint = hammersley (theNumber, theSize);
|
|
vec3 aHalf = importanceSample (aHammersleyPoint, occRoughness (theRoughness));
|
|
float aHdotV = aHalf.z;
|
|
aHalf = fromTangentSpace (aHalf, theNormal);
|
|
vec3 aLight = -reflect (theNormal, aHalf);
|
|
float aNdotL = dot (aLight, theNormal);
|
|
if (aNdotL > 0.0)
|
|
{
|
|
float aSolidAngleSample = 1.0 / (float(theSize) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);
|
|
float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / uEnvSolidAngleSource);
|
|
return vec4 (occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL, aNdotL);
|
|
}
|
|
return vec4 (0.0);
|
|
}
|
|
|
|
//! Bakes specular IBL map.
|
|
vec3 bakeSpecularMap (in vec3 theNormal,
|
|
in float theRoughness)
|
|
{
|
|
vec4 aResult = vec4(0.0);
|
|
if (theRoughness == 0.0)
|
|
{
|
|
aResult = specularMapSample (theNormal, theRoughness, 0, 1);
|
|
}
|
|
else
|
|
{
|
|
for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)
|
|
{
|
|
aResult += specularMapSample (theNormal, theRoughness, aSampleIter, uSamplesNum);
|
|
}
|
|
}
|
|
return aResult.xyz / aResult.w;
|
|
}
|
|
#endif
|
|
|
|
void main()
|
|
{
|
|
vec3 aViewDirection = normalize (ViewDirection);
|
|
#ifdef THE_TO_BAKE_DIFFUSE
|
|
vec4 aRes = vec4 (bakeDiffuseSH(), 1.0);
|
|
#ifdef THE_TO_PACK_FLOAT
|
|
int aCompIndex = int(gl_FragCoord.y);
|
|
float aComp = aCompIndex == 0 ? aRes.x : (aCompIndex == 1 ? aRes.y : aRes.z);
|
|
int aFixedPrec = int(aComp * 2147483647.0);
|
|
int aFixedDiv1 = aFixedPrec / 256;
|
|
int aFixedDiv2 = aFixedDiv1 / 256;
|
|
int aFixedDiv3 = aFixedDiv2 / 256;
|
|
vec4 aPacked = vec4(float(aFixedPrec), float(aFixedDiv1), float(aFixedDiv2), float(aFixedDiv3));
|
|
aRes = fract (aPacked * (1.0 / 256.0));
|
|
#endif
|
|
occFragColor = aRes;
|
|
#else
|
|
float aRoughness = float(uCurrentLevel) / float(occNbSpecIBLLevels - 1);
|
|
occFragColor = vec4 (bakeSpecularMap (aViewDirection, aRoughness), 1.0);
|
|
#endif
|
|
}
|