67312b79 |
1 | // This file has been automatically generated from resource file src/Shaders/PBREnvBaking.fs |
2 | |
3 | static const char Shaders_PBREnvBaking_fs[] = |
4 | "THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap\n" |
5 | "\n" |
6 | "uniform int uSamplesNum; //!< number of samples in Monte-Carlo integration\n" |
7 | "uniform int uCurrentLevel; //!< current level of specular IBL map (ignored in case of diffuse map's processing)\n" |
8 | "uniform int uEnvMapSize; //!< one edge's size of source environtment map's zero mipmap level\n" |
9 | "uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap\n" |
10 | "uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap\n" |
11 | "uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)\n" |
12 | "\n" |
13 | "//! Returns coordinates of point theNumber from Hammersley point set having size theSize.\n" |
14 | "vec2 hammersley (in int theNumber,\n" |
15 | " in int theSize)\n" |
16 | "{\n" |
17 | " int aDenominator = 2;\n" |
18 | " int aNumber = theNumber;\n" |
19 | " float aVanDerCorput = 0.0;\n" |
20 | " for (int i = 0; i < 32; ++i)\n" |
21 | " {\n" |
22 | " if (aNumber > 0)\n" |
23 | " {\n" |
24 | " aVanDerCorput += float(aNumber % 2) / float(aDenominator);\n" |
25 | " aNumber /= 2;\n" |
26 | " aDenominator *= 2;\n" |
27 | " }\n" |
28 | " }\n" |
29 | " return vec2(float(theNumber) / float(theSize), aVanDerCorput);\n" |
30 | "}\n" |
31 | "\n" |
32 | "//! This function does importance sampling on hemisphere surface using GGX normal distribution function\n" |
33 | "//! in tangent space (positive z axis is surface normal direction).\n" |
34 | "vec3 importanceSample (in vec2 theHammersleyPoint,\n" |
35 | " in float theRoughness)\n" |
36 | "{\n" |
37 | " float aPhi = PI_2 * theHammersleyPoint.x;\n" |
38 | " theRoughness *= theRoughness;\n" |
39 | " theRoughness *= theRoughness;\n" |
40 | " float aCosTheta = sqrt((1.0 - theHammersleyPoint.y) / (1.0 + (theRoughness - 1.0) * theHammersleyPoint.y));\n" |
41 | " float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n" |
42 | " return vec3(aSinTheta * cos(aPhi),\n" |
43 | " aSinTheta * sin(aPhi),\n" |
44 | " aCosTheta);\n" |
45 | "}\n" |
46 | "\n" |
47 | "//! This function uniformly generates samples on whole sphere.\n" |
48 | "vec3 sphereUniformSample (in vec2 theHammersleyPoint)\n" |
49 | "{\n" |
50 | " float aPhi = PI_2 * theHammersleyPoint.x;\n" |
51 | " float aCosTheta = 2.0 * theHammersleyPoint.y - 1.0;\n" |
52 | " float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n" |
53 | " return vec3(aSinTheta * cos(aPhi),\n" |
54 | " aSinTheta * sin(aPhi),\n" |
55 | " aCosTheta);\n" |
56 | "}\n" |
57 | "\n" |
58 | "//! Transforms resulted sampled direction from tangent space to world space considering the surface normal.\n" |
59 | "vec3 fromTangentSpace (in vec3 theVector,\n" |
60 | " in vec3 theNormal)\n" |
61 | "{\n" |
62 | " vec3 anUp = (abs(theNormal.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n" |
63 | " vec3 anX = normalize(cross(anUp, theNormal));\n" |
64 | " vec3 anY = cross(theNormal, anX);\n" |
65 | " return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;\n" |
66 | "}\n" |
67 | "\n" |
68 | "const float aSHBasisFuncCoeffs[9] = float[9]\n" |
69 | "(\n" |
70 | " 0.282095 * 0.282095,\n" |
71 | " 0.488603 * 0.488603,\n" |
72 | " 0.488603 * 0.488603,\n" |
73 | " 0.488603 * 0.488603,\n" |
74 | " 1.092548 * 1.092548,\n" |
75 | " 1.092548 * 1.092548,\n" |
76 | " 1.092548 * 1.092548,\n" |
77 | " 0.315392 * 0.315392,\n" |
78 | " 0.546274 * 0.546274\n" |
79 | ");\n" |
80 | "\n" |
81 | "const float aSHCosCoeffs[9] = float[9]\n" |
82 | "(\n" |
83 | " 3.141593,\n" |
84 | " 2.094395,\n" |
85 | " 2.094395,\n" |
86 | " 2.094395,\n" |
87 | " 0.785398,\n" |
88 | " 0.785398,\n" |
89 | " 0.785398,\n" |
90 | " 0.785398,\n" |
91 | " 0.785398\n" |
92 | ");\n" |
93 | "\n" |
94 | "//! Bakes diffuse IBL map's spherical harmonics coefficients.\n" |
95 | "vec3 bakeDiffuseSH()\n" |
96 | "{\n" |
97 | " int anIndex = int(gl_FragCoord.x);\n" |
98 | " vec3 aResult = vec3 (0.0);\n" |
99 | " for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)\n" |
100 | " {\n" |
101 | " vec2 aHammersleyPoint = hammersley (aSampleIter, uSamplesNum);\n" |
102 | " vec3 aDirection = sphereUniformSample (aHammersleyPoint);\n" |
103 | "\n" |
104 | " vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;\n" |
105 | "\n" |
106 | " float aBasisFunc[9];\n" |
107 | " aBasisFunc[0] = 1.0;\n" |
108 | "\n" |
109 | " aBasisFunc[1] = aDirection.x;\n" |
110 | " aBasisFunc[2] = aDirection.y;\n" |
111 | " aBasisFunc[3] = aDirection.z;\n" |
112 | "\n" |
113 | " aBasisFunc[4] = aDirection.x * aDirection.z;\n" |
114 | " aBasisFunc[5] = aDirection.y * aDirection.z;\n" |
115 | " aBasisFunc[6] = aDirection.x * aDirection.y;\n" |
116 | "\n" |
117 | " aBasisFunc[7] = 3.0 * aDirection.z * aDirection.z - 1.0;\n" |
118 | " aBasisFunc[8] = aDirection.x * aDirection.x - aDirection.y * aDirection.y;\n" |
119 | "\n" |
120 | " aResult += aValue * aBasisFunc[anIndex];\n" |
121 | " }\n" |
122 | "\n" |
123 | " aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);\n" |
124 | " return aResult;\n" |
125 | "}\n" |
126 | "\n" |
127 | "//! Bakes specular IBL map.\n" |
128 | "vec3 bakeSpecularMap (in vec3 theNormal,\n" |
129 | " in float theRoughness)\n" |
130 | "{\n" |
131 | " vec3 aResult = vec3(0.0);\n" |
132 | " float aWeightSum = 0.0;\n" |
133 | " int aSamplesNum = (theRoughness == 0.0) ? 1 : uSamplesNum;\n" |
134 | " float aSolidAngleSource = 4.0 * PI / (6.0 * float(uEnvMapSize * uEnvMapSize));\n" |
135 | " for (int aSampleIter = 0; aSampleIter < aSamplesNum; ++aSampleIter)\n" |
136 | " {\n" |
137 | " vec2 aHammersleyPoint = hammersley (aSampleIter, aSamplesNum);\n" |
138 | " vec3 aHalf = importanceSample (aHammersleyPoint, occRoughness (theRoughness));\n" |
139 | " float aHdotV = aHalf.z;\n" |
140 | " aHalf = fromTangentSpace (aHalf, theNormal);\n" |
141 | " vec3 aLight = -reflect (theNormal, aHalf);\n" |
142 | " float aNdotL = dot (aLight, theNormal);\n" |
143 | " if (aNdotL > 0.0)\n" |
144 | " {\n" |
145 | " float aSolidAngleSample = 1.0 / (float(aSamplesNum) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);\n" |
146 | " float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / aSolidAngleSource);\n" |
147 | " aResult += occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL;\n" |
148 | " aWeightSum += aNdotL;\n" |
149 | " }\n" |
150 | " }\n" |
151 | " return aResult / aWeightSum;\n" |
152 | "}\n" |
153 | "\n" |
154 | "void main()\n" |
155 | "{\n" |
156 | " vec3 aViewDirection = normalize (ViewDirection);\n" |
157 | " if (occNbSpecIBLLevels == 0)\n" |
158 | " {\n" |
159 | " occSetFragColor (vec4 (bakeDiffuseSH (), 1.0));\n" |
160 | " }\n" |
161 | " else\n" |
162 | " {\n" |
163 | " occSetFragColor (vec4 (bakeSpecularMap (aViewDirection, float(uCurrentLevel) / float(occNbSpecIBLLevels - 1)), 1.0));\n" |
164 | " }\n" |
165 | "}\n"; |