DALi Version 1.3.45
[platform/core/uifw/dali-demo.git] / resources / shaders / pbr_shader.fsh
1 #version 300 es
2
3 precision highp float;
4
5 uniform sampler2D sAlbedoMetal;
6 uniform sampler2D sNormalRoughness;
7 uniform samplerCube sDiffuse;
8 uniform samplerCube sSpecular;
9
10 // Transformation matrix of the cubemap texture
11
12 // Number of mip map levels in the texture
13 uniform float uMaxLOD;
14
15 // Number of mip map levels in the texture
16 uniform float uRoughness;
17
18 // Number of mip map levels in the texture
19 uniform float uMetallic;
20
21 in vec2 vUV;
22 in vec3 vNormal;
23 in vec3 vTangent;
24 in vec3 vBitangent;
25 in vec3 vViewVec;
26 in mat4 uCubeMatrix;
27
28 out vec4 FragColor;
29
30 // Functions for BRDF calculation come from
31 // https://www.unrealengine.com/blog/physically-based-shading-on-mobile
32 // Based on the paper by Dimitar Lazarov
33 // http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
34 vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
35 {
36   const vec4 c0 = vec4( -1.0, -0.0275, -0.572, 0.022 );
37   const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04 );
38   vec4 r = Roughness * c0 + c1;
39   float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
40   vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
41
42   return SpecularColor * AB.x + AB.y;
43 }
44
45 void main()
46 {
47   // We get information from the maps (albedo, normal map, roughness, metalness
48   // I access the maps in the order they will be used
49   vec4 normalRoughness = texture(sNormalRoughness, vUV.st);
50   vec3 normalMap = normalRoughness.rgb;
51   float roughness = normalRoughness.a * uRoughness;
52
53   vec4 albedoMetal = texture(sAlbedoMetal, vUV.st);
54   vec3 albedoColor = albedoMetal.rgb;
55   float metallic = albedoMetal.a * uMetallic;
56
57   //Normalize vectors
58   vec3 normal = normalize(vNormal);
59   vec3 tangent = normalize(vTangent);
60   vec3 bitangent = normalize(vBitangent);
61
62   vec3 viewVec = normalize(vViewVec);
63
64   // Create Inverse Local to world matrix
65   mat3 vInvTBN = mat3(tangent, bitangent, normal);
66
67   // Get normal map info in world space
68   normalMap = normalize((normalMap - 0.5) * 2.0);
69   vec3 newNormal = vInvTBN * normalMap.rgb;
70
71   // Calculate normal dot view vector
72   float NoV = clamp(dot(newNormal, -viewVec), 0.0, 1.0);
73
74   // Reflect vector
75   vec3 reflectionVec = reflect(viewVec, newNormal);
76
77   //transform it now to environment coordinates (used when the environment rotates)
78   vec3 reflecCube = (uCubeMatrix * vec4(reflectionVec,0)).xyz;
79   reflecCube = normalize(reflecCube);
80
81   //transform it now to environment coordinates
82   vec3 normalCube = (uCubeMatrix * vec4(newNormal,0)).xyz;
83   normalCube = normalize(normalCube);
84
85   // Get irradiance from diffuse cubemap
86   vec3 irradiance = texture(sDiffuse, normalCube).rgb;
87
88   // Way to access the mip map level - copied from UE
89   const float REFLECTION_CAPTURE_ROUGHEST_MIP = 1.;
90   const float REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE = 1.2;
91   float LevelFrom1x1 = REFLECTION_CAPTURE_ROUGHEST_MIP - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(roughness);
92   // Note: must match GReflectionCaptureSize
93   // We need to subtract 2 levels from the uMaxLOD because we don't have the smallest mipmaps
94   // (and because these levels are very small 1x1, 2x2, etc.)
95   float finalLod = (uMaxLOD - 2.0) - 1.0 - LevelFrom1x1;
96
97   // calculate the convexity and increase the reflectance lobe
98   float convexity = length(fwidth(newNormal));
99   finalLod += convexity * (uMaxLOD - 2.0);
100
101   // Access reflection color using roughness value
102   vec3 reflectionColor = textureLod(sSpecular, reflecCube, finalLod).rgb;
103
104   // For increasing contrast a little bit - It should be Gamma correction (2.2) but it gets to dark
105   albedoColor = pow(albedoColor,vec3(1.2));
106
107   // We use DielectricColor of a plastic (almost everything)
108   // http://blog.selfshadow.com/publications/s2014-shading-course/hoffman/s2014_pbs_physics_math_slides.pdf
109   vec3 DielectricSpecular = vec3(0.04);
110   vec3 DiffuseColor = albedoColor - albedoColor * metallic;  // 1 mad
111   vec3 SpecularColor = (DielectricSpecular - DielectricSpecular * metallic) + albedoColor * metallic; //2 mad
112
113   // Calculate specular color using Magic Function (takes original rougness and normal dot view
114   vec3 specColor =  reflectionColor.rgb * EnvBRDFApprox(SpecularColor, roughness, NoV);// * irradiance;
115
116   // Multiply the result by albedo texture and do energy conservation
117   vec3 diffuseColor = irradiance * DiffuseColor;
118
119   // Final color is the sum of the diffuse and specular term
120   vec3 finalColor = diffuseColor + specColor;
121   //FragColor = vec4(1.0, 1.0, 1.0, 1.0);
122   finalColor = finalColor / (finalColor + vec3(1));
123   FragColor = vec4(finalColor,1.0);
124 }