[dali_2.3.20] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / graphics / shaders / gltf-physically-based-shader.frag
1 uniform lowp vec3 uLightColor;
2 uniform lowp vec4 uBaseColorFactor;
3 uniform lowp vec2 uMetallicRoughnessFactors;
4 uniform lowp float alphaCutoff;
5 uniform lowp float uAlphaMode;
6 uniform lowp float uHasLightSource;
7
8 in lowp vec2 vUV[2];
9 in lowp mat3 vTBN;
10 in lowp vec4 vColor;
11 in highp vec3 vLightDirection;
12 in highp vec3 vPositionToCamera;
13
14 out vec4 FragColor;
15
16 struct PBRInfo
17 {
18   mediump float NdotL;                  // cos angle between normal and light direction
19   mediump float NdotV;                  // cos angle between normal and view direction
20   mediump float NdotH;                  // cos angle between normal and half vector
21   mediump float VdotH;                  // cos angle between view direction and half vector
22   mediump vec3 reflectance0;            // full reflectance color (normal incidence angle)
23   mediump vec3 reflectance90;           // reflectance color at grazing angle
24   lowp float alphaRoughness;            // roughness mapped to a more linear change in the roughness (proposed by [2])
25 };
26
27 const float M_PI = 3.141592653589793;
28 const float c_MinRoughness = 0.04;
29
30 vec3 getNormal()
31 {
32 #ifdef TEXTURE_NORMAL
33   lowp vec3 n = texture(uNormalSampler, vUV[uNormalTexCoordIndex]).rgb;
34   n = normalize(vTBN * ((2.0 * n - 1.0) * vec3(uNormalScale, uNormalScale, 1.0)));
35 #else
36   lowp vec3 n = normalize( vTBN[2].xyz );
37 #endif
38   return n;
39 }
40
41 vec3 specularReflection(PBRInfo pbrInputs)
42 {
43   return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
44 }
45
46 float geometricOcclusion(PBRInfo pbrInputs)
47 {
48   mediump float NdotL = pbrInputs.NdotL;
49   mediump float NdotV = pbrInputs.NdotV;
50   lowp float r = pbrInputs.alphaRoughness;
51
52   lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
53   lowp float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
54   return attenuationL * attenuationV;
55 }
56
57 float microfacetDistribution(PBRInfo pbrInputs)
58 {
59   mediump float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
60   lowp float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
61   return roughnessSq / (M_PI * f * f);
62 }
63
64 vec3 linear(vec3 color)
65 {
66   return pow(color,vec3(2.2));
67 }
68
69 void main()
70 {
71   // Metallic and Roughness material properties are packed together
72   // In glTF, these factors can be specified by fixed scalar values
73   // or from a metallic-roughness map
74   lowp float metallic = uMetallicRoughnessFactors.x;
75   lowp float perceptualRoughness = uMetallicRoughnessFactors.y;
76
77   // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
78   // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
79 #ifdef TEXTURE_METALLICROUGHNESS
80   lowp vec4 metrou = texture(uMetallicRoughnessSampler, vUV[uMetallicRoughnessTexCoordIndex]);
81   metallic = metrou.b * metallic;
82   perceptualRoughness = metrou.g * perceptualRoughness;
83 #endif
84
85   metallic = clamp(metallic, 0.0, 1.0);
86   perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
87   // Roughness is authored as perceptual roughness; as is convention,
88   // convert to material roughness by squaring the perceptual roughness [2].
89   lowp float alphaRoughness = perceptualRoughness * perceptualRoughness;
90
91 #ifdef TEXTURE_BASECOLOR
92   // The albedo may be defined from a base texture or a flat color
93   lowp vec4 baseColor = texture(uBaseColorSampler, vUV[uBaseColorTexCoordIndex]) * uBaseColorFactor;
94   baseColor = vec4(linear(baseColor.rgb), baseColor.w);
95 #else
96   lowp vec4 baseColor = vColor * uBaseColorFactor;
97 #endif
98
99   if(uAlphaMode < 0.5f)
100   {
101     baseColor.w = 1.0;
102   }
103   else if(uAlphaMode < 1.5f)
104   {
105     if(baseColor.w >= alphaCutoff)
106     {
107       baseColor.w = 1.0;
108     }
109     else
110     {
111       baseColor.w = 0.0;
112     }
113   }
114
115   lowp vec3 f0 = vec3(0.04);
116   lowp vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
117   diffuseColor *= ( 1.0 - metallic );
118   lowp vec3 specularColor = mix(f0, baseColor.rgb, metallic);
119
120   // Compute reflectance.
121   lowp float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
122
123   // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
124   // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
125   lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
126   lowp vec3 specularEnvironmentR0 = specularColor.rgb;
127   lowp vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
128
129   mediump vec3 n = getNormal();                            // normal at surface point
130   mediump vec3 v = normalize(vPositionToCamera);           // Vector from surface point to camera
131   mediump vec3 l = normalize(vLightDirection);             // Vector from light to surface point
132   mediump vec3 h = normalize(l+v);                         // Half vector between both l and v
133   mediump vec3 reflection = -normalize(reflect(v, n));
134
135   mediump float NdotL = clamp(dot(n, l), 0.001, 1.0);
136   mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
137   mediump float NdotH = dot(n, h);
138   mediump float LdotH = dot(l, h);
139   mediump float VdotH = dot(v, h);
140
141   PBRInfo pbrInputs = PBRInfo(
142     NdotL,
143     NdotV,
144     NdotH,
145     VdotH,
146     specularEnvironmentR0,
147     specularEnvironmentR90,
148     alphaRoughness
149   );
150
151   // Calculate the shading terms for the microfacet specular shading model
152   lowp vec3 color = vec3(0.0);
153   if( uHasLightSource > 0.5f )
154   {
155     lowp vec3 F = specularReflection( pbrInputs );
156     lowp float G = geometricOcclusion( pbrInputs );
157     lowp float D = microfacetDistribution( pbrInputs );
158
159   // Calculation of analytical lighting contribution
160     lowp vec3 diffuseContrib = ( 1.0 - F ) * ( diffuseColor / M_PI );
161     lowp vec3 specContrib = F * G * D / ( 4.0 * NdotL * NdotV );
162   // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
163     color = NdotL * uLightColor * (diffuseContrib + specContrib);
164   }
165
166 #ifdef TEXTURE_IBL
167   lowp float lod = ( perceptualRoughness * uMipmapLevel );
168   // retrieve a scale and bias to F0. See [1], Figure 3
169   lowp vec3 brdf = linear( texture( ubrdfLUT, vec2( NdotV, 1.0 - perceptualRoughness ) ).rgb );
170   lowp vec3 diffuseLight = linear( texture( uDiffuseEnvSampler, n ).rgb );
171   lowp vec3 specularLight = linear( textureLod( uSpecularEnvSampler, reflection, lod ).rgb );
172
173   lowp vec3 diffuse = diffuseLight * diffuseColor * uScaleIBLAmbient.x;
174   lowp vec3 specular = specularLight * ( specularColor * brdf.x + brdf.y ) * uScaleIBLAmbient.y;
175   color += ( diffuse + specular );
176 #endif
177
178 #ifdef TEXTURE_OCCLUSION
179   lowp float ao = texture( uOcclusionSampler, vUV[uOcclusionTexCoordIndex] ).r;
180   color = mix( color, color * ao, uOcclusionStrength );
181 #endif
182
183 #ifdef TEXTURE_EMIT
184   lowp vec3 emissive = linear( texture( uEmissiveSampler, vUV[uEmissiveTexCoordIndex] ).rgb ) * uEmissiveFactor;
185   color += emissive;
186 #endif
187
188   FragColor = vec4( pow( color,vec3( 1.0 / 2.2 ) ), baseColor.a );
189 }