Support KHR_materials_specular and KHR_materials_ior extension of glTF
[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 THREE_TEX
27 #ifdef GLTF_CHANNELS
28 #define METALLIC b
29 #define ROUGHNESS g
30 #else //GLTF_CHANNELS
31 #define METALLIC r
32 #define ROUGHNESS a
33 #endif //GLTF_CHANNELS
34 #endif //THREE_TEX
35
36 uniform lowp vec4 uColor; // Color from SceneGraph
37 uniform lowp vec4 uColorFactor; // Color from material
38 uniform lowp float uMetallicFactor;
39 uniform lowp float uRoughnessFactor;
40 uniform lowp float uDielectricSpecular;
41
42 #ifdef THREE_TEX
43 #ifdef BASECOLOR_TEX
44 uniform sampler2D sAlbedoAlpha;
45 #endif // BASECOLOR_TEX
46 #ifdef METALLIC_ROUGHNESS_TEX
47 uniform sampler2D sMetalRoughness;
48 #endif // METALLIC_ROUGHNESS_TEX
49 #ifdef NORMAL_TEX
50 uniform sampler2D sNormal;
51 uniform float uNormalScale;
52 #endif // NORMAL_TEX
53 #else // THREE_TEX
54 uniform sampler2D sAlbedoMetal;
55 uniform sampler2D sNormalRoughness;
56 #endif
57
58 uniform float uSpecularFactor;
59 uniform vec3  uSpecularColorFactor;
60 #ifdef MATERIAL_SPECULAR_TEXTURE
61 uniform sampler2D sSpecular;
62 #endif
63 #ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
64 uniform sampler2D sSpecularColor;
65 #endif
66
67 #ifdef OCCLUSION
68 uniform sampler2D sOcclusion;
69 uniform float uOcclusionStrength;
70 #endif
71
72 #ifdef EMISSIVE
73 uniform sampler2D sEmissive;
74 uniform vec3 uEmissiveFactor;
75 #endif
76
77 //// For IBL
78 uniform sampler2D sbrdfLUT;
79 uniform samplerCube sDiffuseEnvSampler;
80 uniform samplerCube sSpecularEnvSampler;
81 uniform float uIblIntensity;
82 uniform vec3 uYDirection;
83
84 // For Alpha Mode.
85 uniform lowp float uOpaque;
86 uniform lowp float uMask;
87 uniform lowp float uAlphaThreshold;
88
89 // TODO: Multiple texture coordinate will be supported.
90 in lowp vec2 vUV;
91 in lowp mat3 vTBN;
92 in lowp vec4 vColor;
93 in highp vec3 vPositionToCamera;
94
95 out vec4 FragColor;
96
97 const float c_MinRoughness = 0.04;
98
99 vec3 linear(vec3 color)
100 {
101   return pow(color, vec3(2.2));
102 }
103
104 void main()
105 {
106   // Metallic and Roughness material properties are packed together
107   // In glTF, these factors can be specified by fixed scalar values
108   // or from a metallic-roughness map
109   // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
110   // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
111   lowp float metallic = uMetallicFactor;
112   lowp float perceptualRoughness = uRoughnessFactor;
113   // If there isn't normal texture, use surface normal
114   mediump vec3 n = normalize(vTBN[2].xyz);
115
116 #ifdef THREE_TEX
117   // The albedo may be defined from a base texture or a flat color
118 #ifdef BASECOLOR_TEX
119   lowp vec4 baseColor = texture(sAlbedoAlpha, vUV);
120   baseColor = vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor;
121 #else // BASECOLOR_TEX
122   lowp vec4 baseColor = vColor * uColorFactor;
123 #endif // BASECOLOR_TEX
124
125 #ifdef METALLIC_ROUGHNESS_TEX
126   lowp vec4 metrou = texture(sMetalRoughness, vUV);
127   metallic = metrou.METALLIC * metallic;
128   perceptualRoughness = metrou.ROUGHNESS * perceptualRoughness;
129 #endif // METALLIC_ROUGHNESS_TEX
130
131 #ifdef NORMAL_TEX
132   n = texture(sNormal, vUV).rgb;
133   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
134 #endif // NORMAL_TEX
135 #else // THREE_TEX
136   vec4 albedoMetal = texture(sAlbedoMetal, vUV);
137   lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor;
138
139   metallic = albedoMetal.METALLIC * metallic;
140
141   vec4 normalRoughness = texture(sNormalRoughness, vUV);
142   perceptualRoughness = normalRoughness.ROUGHNESS * perceptualRoughness;
143
144   n = normalRoughness.rgb;
145   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
146 #endif // THREE_TEX
147
148   // The value of uOpaque and uMask can be 0.0 or 1.0.
149   // If uOpaque is 1.0, alpha value of final color is 1.0;
150   // If uOpaque is 0.0 and uMask is 1.0, alpha value of final color is 0.0 when input alpha is lower than uAlphaThreshold or
151   // 1.0 when input alpha is larger than uAlphaThreshold.
152   // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode
153   baseColor.a = mix(baseColor.a, 1.0, uOpaque);
154   baseColor.a = min(mix(baseColor.a, floor(baseColor.a - uAlphaThreshold + 1.0), uMask), 1.0);
155
156   metallic = clamp(metallic, 0.0, 1.0);
157   // Roughness is authored as perceptual roughness; as is convention,
158   // convert to material roughness by squaring the perceptual roughness [2].
159   perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
160
161   // Material ior
162   lowp vec3 f0 = vec3(uDielectricSpecular);
163
164   // Material Specular
165   float specularWeight = 1.0;
166   vec4 materialSpecularTexture = vec4(1.0);
167 #ifdef MATERIAL_SPECULAR_TEXTURE
168   materialSpecularTexture.a = texture(sSpecular, vUV).a;
169 #endif
170 #ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
171   materialSpecularTexture.rgb = texture(sSpecularColor, vUV).rgb;
172 #endif
173   specularWeight = uSpecularFactor * materialSpecularTexture.a;
174   f0 = min(f0 * uSpecularColorFactor * materialSpecularTexture.rgb, vec3(1.0));
175   f0 = mix(f0, baseColor.rgb, metallic);
176
177   mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
178   mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
179   mediump vec3 reflection = -normalize(reflect(v, n));
180   lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
181   vec3 Fr = max(vec3(1.0 - perceptualRoughness), f0) - f0;
182   vec3 k_S = f0 + Fr * pow(1.0 - NdotV, 5.0);
183   vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
184
185   // Specular Light
186   lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
187   lowp vec3 specular = specularLight * FssEss;
188
189   // Diffuse Light
190   lowp vec3 diffuseColor = mix(baseColor.rgb, vec3(0), metallic);
191   lowp vec3 irradiance = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
192   float Ems = (1.0 - (brdf.x + brdf.y));
193   vec3 F_avg = specularWeight * (f0 + (1.0 - f0) / 21.0);
194   vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
195   vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms);
196   lowp vec3 diffuse = (FmsEms + k_D) * irradiance;
197
198   lowp vec3 color = (diffuse + specular) * uIblIntensity;
199
200 #ifdef OCCLUSION
201   lowp float ao = texture(sOcclusion, vUV).r;
202   color = mix(color, color * ao, uOcclusionStrength);
203 #endif // OCCLUSION
204
205 #ifdef EMISSIVE
206   lowp vec3 emissive = linear(texture(sEmissive, vUV).rgb) * uEmissiveFactor;
207   color += emissive;
208 #endif // EMISSIVE
209
210   FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
211 }