[dali_2.3.0] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / graphics / shaders / default-physically-based-shader.frag
1 #version 300 es
2
3 // Original Code
4 // https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/glTF-WebGL-PBR/shaders/pbr-frag.glsl
5 // Commit dc84b5e374fb3d23153d2248a338ef88173f9eb6
6 //
7 // This fragment shader defines a reference implementation for Physically Based Shading of
8 // a microfacet surface material defined by a glTF model.For the DamagedHelmet.gltf and its Assets
9 //
10 // References:
11 // [1] Real Shading in Unreal Engine 4
12 //     http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
13 // [2] Physically Based Shading at Disney
14 //     http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf
15 // [3] README.md - Environment Maps
16 //     https://github.com/KhronosGroup/glTF-Sample-Viewer/#environment-maps
17 // [4] \"An Inexpensive BRDF Model for Physically based Rendering\" by Christophe Schlick
18 //     https://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf
19
20 #ifdef HIGHP
21 precision highp float;
22 #else
23 precision mediump float;
24 #endif
25
26 #ifdef GLTF_CHANNELS
27 #define METALLIC b
28 #define ROUGHNESS g
29 #else //GLTF_CHANNELS
30 #define METALLIC r
31 #define ROUGHNESS a
32 #endif //GLTF_CHANNELS
33
34 uniform lowp vec4 uColor; // Color from SceneGraph
35 uniform lowp vec4 uColorFactor; // Color from material
36 uniform lowp float uMetallicFactor;
37 uniform lowp float uRoughnessFactor;
38 uniform lowp float uDielectricSpecular;
39
40 #ifdef THREE_TEX
41 #ifdef BASECOLOR_TEX
42 uniform sampler2D sAlbedoAlpha;
43 uniform float uBaseColorTextureTransformAvailable;
44 uniform mat3 uBaseColorTextureTransform;
45 #endif // BASECOLOR_TEX
46 #ifdef METALLIC_ROUGHNESS_TEX
47 uniform sampler2D sMetalRoughness;
48 uniform float uMetalRoughnessTextureTransformAvailable;
49 uniform mat3 uMetalRoughnessTextureTransform;
50 #endif // METALLIC_ROUGHNESS_TEX
51 #ifdef NORMAL_TEX
52 uniform sampler2D sNormal;
53 uniform float uNormalTextureTransformAvailable;
54 uniform mat3 uNormalTextureTransform;
55 uniform float uNormalScale;
56 #endif // NORMAL_TEX
57 #else // THREE_TEX
58 uniform sampler2D sAlbedoMetal;
59 uniform float uBaseColorTextureTransformAvailable;
60 uniform mat3 uBaseColorTextureTransform;
61 uniform sampler2D sNormalRoughness;
62 uniform float uNormalRoughnessTextureTransformAvailable;
63 uniform mat3 uNormalRoughnessTextureTransform;
64 #endif
65
66
67
68 #ifdef OCCLUSION
69 uniform sampler2D sOcclusion;
70 uniform float uOcclusionTextureTransformAvailable;
71 uniform mat3 uOcclusionTextureTransform;
72 uniform float uOcclusionStrength;
73 #endif
74
75 #ifdef EMISSIVE_TEXTURE
76 uniform sampler2D sEmissive;
77 uniform float uEmissiveTextureTransformAvailable;
78 uniform mat3 uEmissiveTextureTransform;
79 #endif
80 uniform vec3 uEmissiveFactor;
81
82 uniform float uSpecularFactor;
83 uniform vec3  uSpecularColorFactor;
84 #ifdef MATERIAL_SPECULAR_TEXTURE
85 uniform sampler2D sSpecular;
86 #endif
87 #ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
88 uniform sampler2D sSpecularColor;
89 #endif
90
91 // For Light (Currently Directional Only)
92 #define MAX_LIGHTS 5
93 uniform mediump int uLightCount;
94 uniform mediump vec3 uLightDirection[MAX_LIGHTS];
95 uniform mediump vec3 uLightColor[MAX_LIGHTS];
96
97 // For Shadow Map
98 uniform lowp int uIsShadowEnabled;
99 uniform sampler2D sShadowMap;
100 in highp vec3 positionFromLightView;
101
102 //// For IBL
103 uniform sampler2D sbrdfLUT;
104 uniform samplerCube sDiffuseEnvSampler;
105 uniform samplerCube sSpecularEnvSampler;
106 uniform float uIblIntensity;
107 uniform mediump vec3 uYDirection;
108 uniform float uMaxLOD;
109
110 // For Alpha Mode.
111 uniform lowp float uOpaque;
112 uniform lowp float uMask;
113 uniform lowp float uAlphaThreshold;
114
115 // TODO: Multiple texture coordinate will be supported.
116 in mediump vec2 vUV;
117 in lowp mat3 vTBN;
118 in lowp vec4 vColor;
119 in highp vec3 vPositionToCamera;
120
121 out vec4 FragColor;
122
123 const float c_MinRoughness = 0.04;
124 const float M_PI = 3.141592653589793;
125
126 // These properties can be used for circular sampling for PCF
127
128 // Percentage Closer Filtering to mitigate the banding artifacts.
129 const int kPcfSampleCount = 9;
130
131 const float kPi = 3.141592653589f;
132 const float kInvSampleCount = 1.0 / float(kPcfSampleCount);
133 const float kPcfTheta = 2.f * kPi * kInvSampleCount;
134 const float kSinPcfTheta = sin(kPcfTheta);
135 const float kCosPcfTheta = cos(kPcfTheta);
136
137 uniform lowp int uEnableShadowSoftFiltering;
138 uniform mediump float uShadowIntensity;
139 uniform mediump float uShadowBias;
140
141 vec3 linear(vec3 color)
142 {
143   return pow(color, vec3(2.2));
144 }
145
146 vec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform)
147 {
148     return vec2(textureTransform * vec3(texCoord, 1.0));
149 }
150
151 void main()
152 {
153   // Metallic and Roughness material properties are packed together
154   // In glTF, these factors can be specified by fixed scalar values
155   // or from a metallic-roughness map
156   // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
157   // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
158   lowp float metallic = uMetallicFactor;
159   lowp float perceptualRoughness = uRoughnessFactor;
160   // If there isn't normal texture, use surface normal
161   highp vec3 n = normalize(vTBN[2].xyz);
162
163 #ifdef THREE_TEX
164   // The albedo may be defined from a base texture or a flat color
165 #ifdef BASECOLOR_TEX
166   mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
167   lowp vec4 baseColor = texture(sAlbedoAlpha, baseColorTexCoords);
168   baseColor = vColor * vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
169 #else // BASECOLOR_TEX
170   lowp vec4 baseColor = vColor * uColorFactor;
171 #endif // BASECOLOR_TEX
172
173 #ifdef METALLIC_ROUGHNESS_TEX
174   mediump vec2 metalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uMetalRoughnessTextureTransform), uMetalRoughnessTextureTransformAvailable);
175   lowp vec4 metrou = texture(sMetalRoughness, metalRoughnessTexCoords);
176   metallic = metrou.METALLIC * metallic;
177   perceptualRoughness = metrou.ROUGHNESS * perceptualRoughness;
178 #endif // METALLIC_ROUGHNESS_TEX
179
180 #ifdef NORMAL_TEX
181   mediump vec2 normalTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalTextureTransform), uNormalTextureTransformAvailable);
182   n = texture(sNormal, normalTexCoords).rgb;
183   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
184 #endif // NORMAL_TEX
185 #else // THREE_TEX
186   mediump vec2 baseColorTexCoords = mix(vUV, computeTextureTransform(vUV, uBaseColorTextureTransform), uBaseColorTextureTransformAvailable);
187   vec4 albedoMetal = texture(sAlbedoMetal, baseColorTexCoords);
188   lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
189
190   metallic = albedoMetal.METALLIC * metallic;
191
192   mediump vec2 normalRoughnessTexCoords = mix(vUV, computeTextureTransform(vUV, uNormalRoughnessTextureTransform), uNormalRoughnessTextureTransformAvailable);
193   vec4 normalRoughness = texture(sNormalRoughness, normalRoughnessTexCoords);
194   perceptualRoughness = normalRoughness.ROUGHNESS * perceptualRoughness;
195
196   n = normalRoughness.rgb;
197   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
198 #endif // THREE_TEX
199
200   // The value of uOpaque and uMask can be 0.0 or 1.0.
201   // If uMask is 1.0, a Pixel that has bigger alpha than uAlphaThreashold becomes fully opaque,
202   // and, a pixel that has smaller alpha than uAlphaThreashold becomes fully transparent.
203   // If uOpaque is 1.0, alpha value of final color is 1.0;
204   // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode
205   if(uMask > 0.5 && baseColor.a < uAlphaThreshold)
206   {
207     discard;
208   }
209   baseColor.a = mix(baseColor.a, 1.0, uOpaque);
210
211   metallic = clamp(metallic, 0.0, 1.0);
212   // Roughness is authored as perceptual roughness; as is convention,
213   // convert to material roughness by squaring the perceptual roughness [2].
214   perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
215
216   // Material ior
217   lowp vec3 f0 = vec3(uDielectricSpecular);
218
219   // Material Specular
220   float specularWeight = 1.0;
221   vec4 materialSpecularTexture = vec4(1.0);
222 #ifdef MATERIAL_SPECULAR_TEXTURE
223   materialSpecularTexture.a = texture(sSpecular, vUV).a;
224 #endif
225 #ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
226   materialSpecularTexture.rgb = texture(sSpecularColor, vUV).rgb;
227 #endif
228   specularWeight = uSpecularFactor * materialSpecularTexture.a;
229   f0 = min(f0 * uSpecularColorFactor * materialSpecularTexture.rgb, vec3(1.0));
230   f0 = mix(f0, baseColor.rgb, metallic);
231
232   mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
233   mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
234   mediump vec3 reflection = -normalize(reflect(v, n));
235   lowp vec3 brdf = texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb;
236   vec3 Fr = max(vec3(1.0 - perceptualRoughness), f0) - f0;
237   vec3 k_S = f0 + Fr * pow(1.0 - NdotV, 5.0);
238   vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
239
240   // Specular Light
241   // uMaxLOD that means mipmap level of specular texture is used for bluring of reflection of specular following roughness.
242   float lod = perceptualRoughness * (uMaxLOD - 1.0);
243   lowp vec3 specularLight = linear(textureLod(sSpecularEnvSampler, reflection * uYDirection, lod).rgb);
244   lowp vec3 specular = specularLight * FssEss;
245
246   // Diffuse Light
247   lowp vec3 diffuseColor = mix(baseColor.rgb, vec3(0), metallic);
248   lowp vec3 irradiance = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
249   float Ems = (1.0 - (brdf.x + brdf.y));
250   vec3 F_avg = specularWeight * (f0 + (1.0 - f0) / 21.0);
251   vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
252   vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms);
253   lowp vec3 diffuse = (FmsEms + k_D) * irradiance;
254
255   lowp vec3 color = (diffuse + specular) * uIblIntensity;
256
257   // Punctual Light
258   if(uLightCount > 0)
259   {
260     // Compute reflectance.
261     lowp float reflectance = max(max(f0.r, f0.g), f0.b);
262     lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
263     lowp float r = perceptualRoughness * perceptualRoughness;
264     lowp float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
265     mediump float roughnessSq = r * r;
266     lowp vec3 diffuseColorPunctual = baseColor.rgb * (vec3(1.0) - f0);
267     diffuseColorPunctual *= ( 1.0 - metallic );
268
269     for(int i = 0; i < uLightCount; ++i)
270     {
271       highp vec3 l = normalize(-uLightDirection[i]); // Vector from surface point to light
272       mediump vec3 h = normalize(l+v);               // Half vector between both l and v
273       mediump float VdotH = dot(v, h);
274       lowp vec3 specularReflection = f0 + (reflectance90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
275
276       mediump float NdotL = clamp(dot(n, l), 0.001, 1.0);
277       lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
278       lowp float geometricOcclusion = attenuationL * attenuationV;
279
280       highp float NdotH = dot(n, h);
281       highp float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0;
282       lowp float microfacetDistribution = roughnessSq / (M_PI * f * f);;
283
284       // Calculation of analytical lighting contribution
285       lowp vec3 diffuseContrib = ( 1.0 - specularReflection ) * ( diffuseColorPunctual / M_PI );
286       lowp vec3 specContrib = specularReflection * geometricOcclusion * microfacetDistribution / ( 4.0 * NdotL * NdotV );
287
288       // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
289       color += NdotL * uLightColor[i] * (diffuseContrib + specContrib);
290     }
291   }
292
293   if(float(uIsShadowEnabled) * uShadowIntensity > 0.0)
294   {
295     mediump float exposureFactor = 0.0;
296     if(uEnableShadowSoftFiltering > 0)
297     {
298       ivec2 texSize = textureSize(sShadowMap, 0);
299       mediump vec2 texelSize = vec2(1.0) / vec2(texSize.x, texSize.y);
300       mediump vec2 pcfSample = vec2(1.f, 0.f);
301       for (int i = 0; i < kPcfSampleCount; ++i)
302       {
303         pcfSample = vec2(kCosPcfTheta * pcfSample.x - kSinPcfTheta * pcfSample.y,
304                          kSinPcfTheta * pcfSample.x + kCosPcfTheta * pcfSample.y);
305         lowp float depthValue = texture(sShadowMap, positionFromLightView.xy + pcfSample * texelSize).r;
306         exposureFactor += (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0;
307       }
308       exposureFactor *= kInvSampleCount;
309     }
310     else
311     {
312       mediump float depthValue = texture(sShadowMap, positionFromLightView.xy).r;
313       exposureFactor           = (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0;
314     }
315     color *= (1.0 - (1.0 - exposureFactor) * uShadowIntensity);
316   }
317
318 #ifdef OCCLUSION
319   mediump vec2 occlusionTexCoords = mix(vUV, computeTextureTransform(vUV, uOcclusionTextureTransform), uOcclusionTextureTransformAvailable);
320   lowp float ao = texture(sOcclusion, occlusionTexCoords).r;
321   color = mix(color, color * ao, uOcclusionStrength);
322 #endif // OCCLUSION
323
324 #ifdef EMISSIVE_TEXTURE
325   mediump vec2 emissiveTexCoords = mix(vUV, computeTextureTransform(vUV, uEmissiveTextureTransform), uEmissiveTextureTransformAvailable);
326   lowp vec3 emissive = linear(texture(sEmissive, emissiveTexCoords).rgb) * uEmissiveFactor;
327 #else
328   lowp vec3 emissive = uEmissiveFactor;
329 #endif // EMISSIVE_TEXTURE
330   color += emissive;
331
332   FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
333 }