Add BUILD_EXAMPLE_NAME option explain for README.md
[platform/core/uifw/dali-demo.git] / resources / shaders / dli_pbr.fsh
1 #version 300 es
2
3 #ifdef HIGHP
4   precision highp float;
5 #else
6   precision mediump float;
7 #endif
8
9 #ifdef THREE_TEX
10 #ifdef GLTF_CHANNELS
11 // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#pbrmetallicroughnessmetallicroughnesstexture
12 #define METALLIC b
13 #define ROUGHNESS g
14 #else //GLTF_CHANNELS
15 #define METALLIC r
16 #define ROUGHNESS a
17 #endif //GLTF_CHANNELS
18 #endif //THREE_TEX
19
20 #ifdef THREE_TEX
21   uniform sampler2D sAlbedoAlpha;
22   uniform sampler2D sMetalRoughness;
23   uniform sampler2D sNormal;
24
25 #ifdef ALPHA_TEST
26   uniform float uAlphaThreshold;
27 #endif  //ALPHA_TEST
28
29 #else
30   uniform sampler2D sAlbedoMetal;
31   uniform sampler2D sNormalRoughness;
32 #endif
33
34 uniform samplerCube sDiffuse;
35 uniform samplerCube sSpecular;
36
37 // Number of mip map levels in the texture
38 uniform float uMaxLOD;
39
40 // Transformation matrix of the cubemap texture
41 uniform mat4 uCubeMatrix;
42
43 uniform vec4 uColor;
44 uniform float uMetallicFactor;
45 uniform float uRoughnessFactor;
46
47 //IBL Light intensity
48 uniform float uIblIntensity;
49
50 in vec2 vUV;
51 in vec3 vNormal;
52 in vec3 vTangent;
53 in vec3 vViewVec;
54
55 out vec4 FragColor;
56
57 // Functions for BRDF calculation come from
58 // https://www.unrealengine.com/blog/physically-based-shading-on-mobile
59 // Based on the paper by Dimitar Lazarov
60 // http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
61 vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
62 {
63   const vec4 c0 = vec4( -1.0, -0.0275, -0.572, 0.022 );
64   const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04 );
65   vec4 r = Roughness * c0 + c1;
66   float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
67   vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
68
69   return SpecularColor * AB.x + AB.y;
70 }
71
72 void main()
73 {
74   // We get information from the maps (albedo, normal map, roughness, metalness
75   // I access the maps in the order they will be used
76 #ifdef THREE_TEX
77   vec4 albedoAlpha = texture(sAlbedoAlpha, vUV.st);
78   float alpha = albedoAlpha.a;
79 #ifdef ALPHA_TEST
80   if (alpha <= uAlphaThreshold)
81   {
82     discard;
83   }
84 #endif  //ALPHA_TEST
85   vec3 albedoColor = albedoAlpha.rgb * uColor.rgb;
86
87   vec4 metalRoughness = texture(sMetalRoughness, vUV.st);
88   float metallic = metalRoughness.METALLIC * uMetallicFactor;
89   float roughness = metalRoughness.ROUGHNESS * uRoughnessFactor;
90
91   vec3 normalMap = texture(sNormal, vUV.st).rgb;
92 #else  //THREE_TEX
93   vec4 albedoMetal = texture(sAlbedoMetal, vUV.st);
94   vec3 albedoColor = albedoMetal.rgb * uColor.rgb;
95   float metallic = albedoMetal.a * uMetallicFactor;
96
97   vec4 normalRoughness = texture(sNormalRoughness, vUV.st);
98   vec3 normalMap = normalRoughness.rgb;
99   float roughness = normalRoughness.a * uRoughnessFactor;
100 #endif
101   //Normalize vectors
102   vec3 normal = normalize(vNormal);
103   vec3 tangent = normalize(vTangent);
104
105   // NOTE: normal and tangent have to be orthogonal for the result of the cross()
106   // product to be a unit vector. We might find that we need to normalize().
107   vec3 bitangent = cross(normal, tangent);
108
109   vec3 viewVec = normalize(vViewVec);
110
111   // Create Inverse Local to world matrix
112   mat3 vInvTBN = mat3(tangent, bitangent, normal);
113
114   // Get normal map info in world space
115   normalMap = normalize(normalMap - 0.5);
116   vec3 newNormal = vInvTBN * normalMap.rgb;
117
118   // Calculate normal dot view vector
119   float NoV = max(dot(newNormal, -viewVec), 0.0);
120
121   // Reflect vector
122   vec3 reflectionVec = reflect(viewVec, newNormal);
123
124   //transform it now to environment coordinates (used when the environment rotates)
125   vec3 reflecCube = (uCubeMatrix * vec4( reflectionVec, 0.0 ) ).xyz;
126   reflecCube = normalize( reflecCube );
127
128   //transform it now to environment coordinates
129   vec3 normalCube = ( uCubeMatrix * vec4( newNormal, 0.0 ) ).xyz;
130   normalCube = normalize( normalCube );
131
132   // Get irradiance from diffuse cubemap
133   vec3 irradiance = texture( sDiffuse, normalCube ).rgb;
134
135   // Access reflection color using roughness value
136   float finalLod = mix( 0.0, uMaxLOD - 2.0, roughness);
137   vec3 reflectionColor = textureLod(sSpecular, reflecCube, finalLod).rgb;
138
139   // We are supposed to be using DielectricColor (0.04) of a plastic (almost everything)
140   // http://blog.selfshadow.com/publications/s2014-shading-course/hoffman/s2014_pbs_physics_math_slides.pdf
141   // however that seems to prevent achieving very dark tones (i.e. get dark gray blacks).
142   vec3 DiffuseColor = albedoColor - albedoColor * metallic;  // 1 mad
143   vec3 SpecularColor = mix( vec3(0.04), albedoColor, metallic); // 2 mad
144
145   // Calculate specular color using Magic Function (takes original roughness and normal dot view).
146   vec3 specColor =  reflectionColor.rgb * EnvBRDFApprox(SpecularColor, roughness, NoV );
147
148   // Multiply the result by albedo texture and do energy conservation
149   vec3 diffuseColor = irradiance * DiffuseColor;
150
151   // Final color is the sum of the diffuse and specular term
152   vec3 finalColor = diffuseColor + specColor;
153
154   finalColor = sqrt( finalColor ) * uIblIntensity;
155 #ifdef THREE_TEX
156   FragColor = vec4( finalColor, alpha );
157 #else //THREE_TEX
158   FragColor = vec4( finalColor, 1.0 );
159 #endif //THREE_TEX
160 }