mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-03 14:10:33 +03:00
0032083: Visualization, TKOpenGl - PBR rendering is unavailable on Apple A12 Bionic (iPad)
Added "#define occLight_Index(theId) 0" workaround allowing to compile a single light source PBR shading program on OpenGL ES 2.0, as it disallows non-constant index expressions (even trivially deducable at compile-time). PBR lookup table is now automatically resized to RGBA format when RG texture format is unsupported (OpenGL ES 2.0). OpenGl_ShaderManager now allows compiling PBR shaders using WebGL 1.0 + GL_EXT_shader_texture_lod extension. PBR IBL baking GLSL program has been redisigned to use if/else to avoid non-constant index expressions. Diffuse baking implements packing float values into a temporary RGBA8 texture as a fallback solution on WebGL 1.0 implementations supporting float textures but not as FBO render targets. OpenGl_PBREnvironment now uses GL_FRAMEBUFFER instead of GL_DRAW_FRAMEBUFFER for compatibility with OpenGL ES 2.0.
This commit is contained in:
@@ -143,44 +143,49 @@ const int OccLightType_Spot = 3; //!< spot light source
|
||||
// Light sources
|
||||
uniform vec4 occLightAmbient; //!< Cumulative ambient color
|
||||
#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)
|
||||
#if (THE_MAX_LIGHTS > 1)
|
||||
#define occLight_Index(theId) theId
|
||||
#else
|
||||
#define occLight_Index(theId) 0
|
||||
#endif
|
||||
uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sources
|
||||
|
||||
//! Type of light source, int (see OccLightType enum).
|
||||
#define occLight_Type(theId) occLightSourcesTypes[theId]
|
||||
#define occLight_Type(theId) occLightSourcesTypes[occLight_Index(theId)]
|
||||
|
||||
//! Specular intensity (equals to diffuse), vec3.
|
||||
#define occLight_Specular(theId) occLightSources[theId * 4 + 0].rgb
|
||||
#define occLight_Specular(theId) occLightSources[occLight_Index(theId) * 4 + 0].rgb
|
||||
|
||||
//! Intensity of light source (>= 0), float.
|
||||
#define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a
|
||||
#define occLight_Intensity(theId) occLightSources[occLight_Index(theId) * 4 + 0].a
|
||||
|
||||
//! Is light a headlight, bool? DEPRECATED method.
|
||||
#define occLight_IsHeadlight(theId) false
|
||||
|
||||
//! Position of specified light source or direction of directional light source, vec3.
|
||||
#define occLight_Position(theId) occLightSources[theId * 4 + 1].xyz
|
||||
#define occLight_Position(theId) occLightSources[occLight_Index(theId) * 4 + 1].xyz
|
||||
|
||||
//! Direction of specified spot light source, vec3.
|
||||
#define occLight_SpotDirection(theId) occLightSources[theId * 4 + 2].xyz
|
||||
#define occLight_SpotDirection(theId) occLightSources[occLight_Index(theId) * 4 + 2].xyz
|
||||
|
||||
//! Range on which point light source (positional or spot) can affect (>= 0), float.
|
||||
#define occLight_Range(theId) occLightSources[theId * 4 + 2].w
|
||||
#define occLight_Range(theId) occLightSources[occLight_Index(theId) * 4 + 2].w
|
||||
|
||||
//! Maximum spread angle of the spot light (in radians), float.
|
||||
#define occLight_SpotCutOff(theId) occLightSources[theId * 4 + 3].z
|
||||
#define occLight_SpotCutOff(theId) occLightSources[occLight_Index(theId) * 4 + 3].z
|
||||
|
||||
//! Attenuation of the spot light intensity (from 0 to 1), float.
|
||||
#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w
|
||||
#define occLight_SpotExponent(theId) occLightSources[occLight_Index(theId) * 4 + 3].w
|
||||
|
||||
#if !defined(THE_IS_PBR)
|
||||
//! Diffuse intensity (equals to Specular), vec3.
|
||||
#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0].rgb
|
||||
#define occLight_Diffuse(theId) occLightSources[occLight_Index(theId) * 4 + 0].rgb
|
||||
|
||||
//! Const attenuation factor of positional light source, float.
|
||||
#define occLight_ConstAttenuation(theId) occLightSources[theId * 4 + 3].x
|
||||
#define occLight_ConstAttenuation(theId) occLightSources[occLight_Index(theId) * 4 + 3].x
|
||||
|
||||
//! Linear attenuation factor of positional light source, float.
|
||||
#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y
|
||||
#define occLight_LinearAttenuation(theId) occLightSources[occLight_Index(theId) * 4 + 3].y
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@@ -14,7 +14,7 @@ float occDirectionalLightShadow (in sampler2D theShadow,
|
||||
in int theId,
|
||||
in vec3 theNormal)
|
||||
{
|
||||
vec4 aPosLightSpace = PosLightSpace[theId];
|
||||
vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];
|
||||
vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));
|
||||
vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5);
|
||||
float aCurrentDepth = aProjCoords.z;
|
||||
|
@@ -1,12 +1,22 @@
|
||||
THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap
|
||||
|
||||
#if (__VERSION__ >= 120)
|
||||
uniform int uSamplesNum; //!< number of samples in Monte-Carlo integration
|
||||
uniform int uCurrentLevel; //!< current level of specular IBL map (ignored in case of diffuse map's processing)
|
||||
uniform int uEnvMapSize; //!< one edge's size of source environtment map's zero mipmap level
|
||||
uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap
|
||||
uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap
|
||||
#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)
|
||||
@@ -18,7 +28,7 @@ vec2 hammersley (in int theNumber,
|
||||
{
|
||||
if (aNumber > 0)
|
||||
{
|
||||
aVanDerCorput += float(aNumber % 2) / float(aDenominator);
|
||||
aVanDerCorput += mod(float(aNumber), 2.0) / float(aDenominator);
|
||||
aNumber /= 2;
|
||||
aDenominator *= 2;
|
||||
}
|
||||
@@ -62,6 +72,8 @@ vec3 fromTangentSpace (in vec3 theVector,
|
||||
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,
|
||||
@@ -74,7 +86,6 @@ const float aSHBasisFuncCoeffs[9] = float[9]
|
||||
0.315392 * 0.315392,
|
||||
0.546274 * 0.546274
|
||||
);
|
||||
|
||||
const float aSHCosCoeffs[9] = float[9]
|
||||
(
|
||||
3.141593,
|
||||
@@ -87,76 +98,129 @@ const float aSHCosCoeffs[9] = float[9]
|
||||
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 anIndex = int(gl_FragCoord.x);
|
||||
vec3 aResult = vec3 (0.0);
|
||||
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 aDirection = sphereUniformSample (aHammersleyPoint);
|
||||
vec3 aDir = sphereUniformSample (aHammersleyPoint);
|
||||
|
||||
vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;
|
||||
vec3 aVal = occTextureCube (uEnvMap, cubemapVectorTransform (aDir, uYCoeff, uZCoeff)).rgb;
|
||||
#if (__VERSION__ >= 120)
|
||||
float aFunc[9];
|
||||
aFunc[0] = 1.0;
|
||||
|
||||
float aBasisFunc[9];
|
||||
aBasisFunc[0] = 1.0;
|
||||
aFunc[1] = aDir.x;
|
||||
aFunc[2] = aDir.y;
|
||||
aFunc[3] = aDir.z;
|
||||
|
||||
aBasisFunc[1] = aDirection.x;
|
||||
aBasisFunc[2] = aDirection.y;
|
||||
aBasisFunc[3] = aDirection.z;
|
||||
aFunc[4] = aDir.x * aDir.z;
|
||||
aFunc[5] = aDir.y * aDir.z;
|
||||
aFunc[6] = aDir.x * aDir.y;
|
||||
|
||||
aBasisFunc[4] = aDirection.x * aDirection.z;
|
||||
aBasisFunc[5] = aDirection.y * aDirection.z;
|
||||
aBasisFunc[6] = aDirection.x * aDirection.y;
|
||||
aFunc[7] = 3.0 * aDir.z * aDir.z - 1.0;
|
||||
aFunc[8] = aDir.x * aDir.x - aDir.y * aDir.y;
|
||||
|
||||
aBasisFunc[7] = 3.0 * aDirection.z * aDirection.z - 1.0;
|
||||
aBasisFunc[8] = aDirection.x * aDirection.x - aDirection.y * aDirection.y;
|
||||
|
||||
aResult += aValue * aBasisFunc[anIndex];
|
||||
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
|
||||
}
|
||||
|
||||
aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);
|
||||
return aResult;
|
||||
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)
|
||||
{
|
||||
vec3 aResult = vec3(0.0);
|
||||
float aWeightSum = 0.0;
|
||||
int aSamplesNum = (theRoughness == 0.0) ? 1 : uSamplesNum;
|
||||
float aSolidAngleSource = 4.0 * PI / (6.0 * float(uEnvMapSize * uEnvMapSize));
|
||||
for (int aSampleIter = 0; aSampleIter < aSamplesNum; ++aSampleIter)
|
||||
vec4 aResult = vec4(0.0);
|
||||
if (theRoughness == 0.0)
|
||||
{
|
||||
vec2 aHammersleyPoint = hammersley (aSampleIter, aSamplesNum);
|
||||
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)
|
||||
aResult = specularMapSample (theNormal, theRoughness, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)
|
||||
{
|
||||
float aSolidAngleSample = 1.0 / (float(aSamplesNum) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);
|
||||
float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / aSolidAngleSource);
|
||||
aResult += occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL;
|
||||
aWeightSum += aNdotL;
|
||||
aResult += specularMapSample (theNormal, theRoughness, aSampleIter, uSamplesNum);
|
||||
}
|
||||
}
|
||||
return aResult / aWeightSum;
|
||||
return aResult.xyz / aResult.w;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 aViewDirection = normalize (ViewDirection);
|
||||
if (occNbSpecIBLLevels == 0)
|
||||
{
|
||||
occSetFragColor (vec4 (bakeDiffuseSH (), 1.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
occSetFragColor (vec4 (bakeSpecularMap (aViewDirection, float(uCurrentLevel) / float(occNbSpecIBLLevels - 1)), 1.0));
|
||||
}
|
||||
#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
|
||||
}
|
||||
|
@@ -4,32 +4,52 @@ uniform int uCurrentSide; //!< current side of cubemap
|
||||
uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap
|
||||
uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap
|
||||
|
||||
const mat2 cubemapDirectionMatrices[6] = mat2[]
|
||||
(
|
||||
mat2 ( 0, -1, -1, 0),
|
||||
mat2 ( 0, 1, -1, 0),
|
||||
mat2 ( 0, 1, 1, 0),
|
||||
mat2 ( 0, 1, -1, 0),
|
||||
mat2 ( 1, 0, 0, -1),
|
||||
mat2 (-1, 0, 0, -1)
|
||||
);
|
||||
|
||||
//! Generates environment map fetching direction considering current index of side.
|
||||
vec3 cubemapBakingViewDirection (in int theSide,
|
||||
in vec2 theScreenCoord)
|
||||
{
|
||||
int anAxis = theSide / 2;
|
||||
vec3 aDirection = vec3(0.0);
|
||||
aDirection[anAxis] = float(-(int(theSide) % 2) * 2 + 1);
|
||||
theScreenCoord = cubemapDirectionMatrices[theSide] * theScreenCoord;
|
||||
aDirection[(anAxis + 1) % 3] = theScreenCoord.x;
|
||||
aDirection[(anAxis + 2) % 3] = theScreenCoord.y;
|
||||
return aDirection;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ViewDirection = cubemapBakingViewDirection (uCurrentSide, occVertex.xy);
|
||||
ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);
|
||||
vec3 aDir;
|
||||
vec2 aCoord;
|
||||
if (uCurrentSide == 0)
|
||||
{
|
||||
aCoord = mat2( 0,-1,-1, 0) * occVertex.xy;
|
||||
aDir.x = 1.0;
|
||||
aDir.y = aCoord.x;
|
||||
aDir.z = aCoord.y;
|
||||
}
|
||||
else if (uCurrentSide == 1)
|
||||
{
|
||||
aCoord = mat2( 0, 1,-1, 0) * occVertex.xy;
|
||||
aDir.x = -1.0;
|
||||
aDir.y = aCoord.x;
|
||||
aDir.z = aCoord.y;
|
||||
}
|
||||
else if (uCurrentSide == 2)
|
||||
{
|
||||
aCoord = mat2( 0, 1, 1, 0) * occVertex.xy;
|
||||
aDir.x = aCoord.y;
|
||||
aDir.y = 1.0;
|
||||
aDir.z = aCoord.x;
|
||||
}
|
||||
else if (uCurrentSide == 3)
|
||||
{
|
||||
aCoord = mat2( 0, 1,-1, 0) * occVertex.xy;
|
||||
aDir.x = aCoord.y;
|
||||
aDir.y = -1.0;
|
||||
aDir.z = aCoord.x;
|
||||
}
|
||||
else if (uCurrentSide == 4)
|
||||
{
|
||||
aCoord = mat2( 1, 0, 0,-1) * occVertex.xy;
|
||||
aDir.x = aCoord.x;
|
||||
aDir.y = aCoord.y;
|
||||
aDir.z = 1.0;
|
||||
}
|
||||
else //if (uCurrentSide == 5)
|
||||
{
|
||||
aCoord = mat2(-1, 0, 0,-1) * occVertex.xy;
|
||||
aDir.x = aCoord.x;
|
||||
aDir.y = aCoord.y;
|
||||
aDir.z = -1.0;
|
||||
}
|
||||
ViewDirection = cubemapVectorTransform (aDir, uYCoeff, uZCoeff);
|
||||
gl_Position = vec4 (occVertex.xy, 0.0, 1.0);
|
||||
}
|
||||
|
@@ -146,44 +146,49 @@ static const char Shaders_Declarations_glsl[] =
|
||||
"// Light sources\n"
|
||||
"uniform vec4 occLightAmbient; //!< Cumulative ambient color\n"
|
||||
"#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n"
|
||||
"#if (THE_MAX_LIGHTS > 1)\n"
|
||||
" #define occLight_Index(theId) theId\n"
|
||||
"#else\n"
|
||||
" #define occLight_Index(theId) 0\n"
|
||||
"#endif\n"
|
||||
"uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sources\n"
|
||||
"\n"
|
||||
"//! Type of light source, int (see OccLightType enum).\n"
|
||||
"#define occLight_Type(theId) occLightSourcesTypes[theId]\n"
|
||||
"#define occLight_Type(theId) occLightSourcesTypes[occLight_Index(theId)]\n"
|
||||
"\n"
|
||||
"//! Specular intensity (equals to diffuse), vec3.\n"
|
||||
"#define occLight_Specular(theId) occLightSources[theId * 4 + 0].rgb\n"
|
||||
"#define occLight_Specular(theId) occLightSources[occLight_Index(theId) * 4 + 0].rgb\n"
|
||||
"\n"
|
||||
"//! Intensity of light source (>= 0), float.\n"
|
||||
"#define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a\n"
|
||||
"#define occLight_Intensity(theId) occLightSources[occLight_Index(theId) * 4 + 0].a\n"
|
||||
"\n"
|
||||
"//! Is light a headlight, bool? DEPRECATED method.\n"
|
||||
"#define occLight_IsHeadlight(theId) false\n"
|
||||
"\n"
|
||||
"//! Position of specified light source or direction of directional light source, vec3.\n"
|
||||
"#define occLight_Position(theId) occLightSources[theId * 4 + 1].xyz\n"
|
||||
"#define occLight_Position(theId) occLightSources[occLight_Index(theId) * 4 + 1].xyz\n"
|
||||
"\n"
|
||||
"//! Direction of specified spot light source, vec3.\n"
|
||||
"#define occLight_SpotDirection(theId) occLightSources[theId * 4 + 2].xyz\n"
|
||||
"#define occLight_SpotDirection(theId) occLightSources[occLight_Index(theId) * 4 + 2].xyz\n"
|
||||
"\n"
|
||||
"//! Range on which point light source (positional or spot) can affect (>= 0), float.\n"
|
||||
"#define occLight_Range(theId) occLightSources[theId * 4 + 2].w\n"
|
||||
"#define occLight_Range(theId) occLightSources[occLight_Index(theId) * 4 + 2].w\n"
|
||||
"\n"
|
||||
"//! Maximum spread angle of the spot light (in radians), float.\n"
|
||||
"#define occLight_SpotCutOff(theId) occLightSources[theId * 4 + 3].z\n"
|
||||
"#define occLight_SpotCutOff(theId) occLightSources[occLight_Index(theId) * 4 + 3].z\n"
|
||||
"\n"
|
||||
"//! Attenuation of the spot light intensity (from 0 to 1), float.\n"
|
||||
"#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w\n"
|
||||
"#define occLight_SpotExponent(theId) occLightSources[occLight_Index(theId) * 4 + 3].w\n"
|
||||
"\n"
|
||||
"#if !defined(THE_IS_PBR)\n"
|
||||
"//! Diffuse intensity (equals to Specular), vec3.\n"
|
||||
"#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0].rgb\n"
|
||||
"#define occLight_Diffuse(theId) occLightSources[occLight_Index(theId) * 4 + 0].rgb\n"
|
||||
"\n"
|
||||
"//! Const attenuation factor of positional light source, float.\n"
|
||||
"#define occLight_ConstAttenuation(theId) occLightSources[theId * 4 + 3].x\n"
|
||||
"#define occLight_ConstAttenuation(theId) occLightSources[occLight_Index(theId) * 4 + 3].x\n"
|
||||
"\n"
|
||||
"//! Linear attenuation factor of positional light source, float.\n"
|
||||
"#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y\n"
|
||||
"#define occLight_LinearAttenuation(theId) occLightSources[occLight_Index(theId) * 4 + 3].y\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
|
@@ -17,7 +17,7 @@ static const char Shaders_DirectionalLightShadow_glsl[] =
|
||||
" in int theId,\n"
|
||||
" in vec3 theNormal)\n"
|
||||
"{\n"
|
||||
" vec4 aPosLightSpace = PosLightSpace[theId];\n"
|
||||
" vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];\n"
|
||||
" vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));\n"
|
||||
" vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5);\n"
|
||||
" float aCurrentDepth = aProjCoords.z;\n"
|
||||
|
@@ -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"
|
||||
" vec3 aDir = sphereUniformSample (aHammersleyPoint);\n"
|
||||
"\n"
|
||||
" vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;\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"
|
||||
" float aBasisFunc[9];\n"
|
||||
" aBasisFunc[0] = 1.0;\n"
|
||||
" aFunc[1] = aDir.x;\n"
|
||||
" aFunc[2] = aDir.y;\n"
|
||||
" aFunc[3] = aDir.z;\n"
|
||||
"\n"
|
||||
" aBasisFunc[1] = aDirection.x;\n"
|
||||
" aBasisFunc[2] = aDirection.y;\n"
|
||||
" aBasisFunc[3] = aDirection.z;\n"
|
||||
" aFunc[4] = aDir.x * aDir.z;\n"
|
||||
" aFunc[5] = aDir.y * aDir.z;\n"
|
||||
" aFunc[6] = aDir.x * aDir.y;\n"
|
||||
"\n"
|
||||
" aBasisFunc[4] = aDirection.x * aDirection.z;\n"
|
||||
" aBasisFunc[5] = aDirection.y * aDirection.z;\n"
|
||||
" aBasisFunc[6] = aDirection.x * aDirection.y;\n"
|
||||
" aFunc[7] = 3.0 * aDir.z * aDir.z - 1.0;\n"
|
||||
" aFunc[8] = aDir.x * aDir.x - aDir.y * aDir.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"
|
||||
" 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"
|
||||
" 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"
|
||||
" aResult = specularMapSample (theNormal, theRoughness, 0, 1);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\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";
|
||||
|
@@ -7,32 +7,52 @@ static const char Shaders_PBREnvBaking_vs[] =
|
||||
"uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap\n"
|
||||
"uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap\n"
|
||||
"\n"
|
||||
"const mat2 cubemapDirectionMatrices[6] = mat2[]\n"
|
||||
"(\n"
|
||||
" mat2 ( 0, -1, -1, 0),\n"
|
||||
" mat2 ( 0, 1, -1, 0),\n"
|
||||
" mat2 ( 0, 1, 1, 0),\n"
|
||||
" mat2 ( 0, 1, -1, 0),\n"
|
||||
" mat2 ( 1, 0, 0, -1),\n"
|
||||
" mat2 (-1, 0, 0, -1)\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"//! Generates environment map fetching direction considering current index of side.\n"
|
||||
"vec3 cubemapBakingViewDirection (in int theSide,\n"
|
||||
" in vec2 theScreenCoord)\n"
|
||||
"{\n"
|
||||
" int anAxis = theSide / 2;\n"
|
||||
" vec3 aDirection = vec3(0.0);\n"
|
||||
" aDirection[anAxis] = float(-(int(theSide) % 2) * 2 + 1);\n"
|
||||
" theScreenCoord = cubemapDirectionMatrices[theSide] * theScreenCoord;\n"
|
||||
" aDirection[(anAxis + 1) % 3] = theScreenCoord.x;\n"
|
||||
" aDirection[(anAxis + 2) % 3] = theScreenCoord.y;\n"
|
||||
" return aDirection;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ViewDirection = cubemapBakingViewDirection (uCurrentSide, occVertex.xy);\n"
|
||||
" ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);\n"
|
||||
" vec3 aDir;\n"
|
||||
" vec2 aCoord;\n"
|
||||
" if (uCurrentSide == 0)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2( 0,-1,-1, 0) * occVertex.xy;\n"
|
||||
" aDir.x = 1.0;\n"
|
||||
" aDir.y = aCoord.x;\n"
|
||||
" aDir.z = aCoord.y;\n"
|
||||
" }\n"
|
||||
" else if (uCurrentSide == 1)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2( 0, 1,-1, 0) * occVertex.xy;\n"
|
||||
" aDir.x = -1.0;\n"
|
||||
" aDir.y = aCoord.x;\n"
|
||||
" aDir.z = aCoord.y;\n"
|
||||
" }\n"
|
||||
" else if (uCurrentSide == 2)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2( 0, 1, 1, 0) * occVertex.xy;\n"
|
||||
" aDir.x = aCoord.y;\n"
|
||||
" aDir.y = 1.0;\n"
|
||||
" aDir.z = aCoord.x;\n"
|
||||
" }\n"
|
||||
" else if (uCurrentSide == 3)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2( 0, 1,-1, 0) * occVertex.xy;\n"
|
||||
" aDir.x = aCoord.y;\n"
|
||||
" aDir.y = -1.0;\n"
|
||||
" aDir.z = aCoord.x;\n"
|
||||
" }\n"
|
||||
" else if (uCurrentSide == 4)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2( 1, 0, 0,-1) * occVertex.xy;\n"
|
||||
" aDir.x = aCoord.x;\n"
|
||||
" aDir.y = aCoord.y;\n"
|
||||
" aDir.z = 1.0;\n"
|
||||
" }\n"
|
||||
" else //if (uCurrentSide == 5)\n"
|
||||
" {\n"
|
||||
" aCoord = mat2(-1, 0, 0,-1) * occVertex.xy;\n"
|
||||
" aDir.x = aCoord.x;\n"
|
||||
" aDir.y = aCoord.y;\n"
|
||||
" aDir.z = -1.0;\n"
|
||||
" }\n"
|
||||
" ViewDirection = cubemapVectorTransform (aDir, uYCoeff, uZCoeff);\n"
|
||||
" gl_Position = vec4 (occVertex.xy, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
Reference in New Issue
Block a user