normals_optimized.frag 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #version 430
  2. #pragma debug(on)
  3. #extension GL_NV_shadow_samplers_cube : enable
  4. out layout(location = 0) vec4 a_outColor;
  5. in vec3 v_normals;
  6. in vec3 v_position; //world space
  7. in vec2 v_texCoord;
  8. uniform vec3 u_eyePosition;
  9. uniform sampler2D u_albedoSampler;
  10. uniform sampler2D u_normalSampler;
  11. uniform samplerCube u_skybox;
  12. uniform float u_gama;
  13. uniform sampler2D u_RMASampler;
  14. uniform int u_materialIndex;
  15. struct Pointlight
  16. {
  17. vec3 positions; // w component not used
  18. float dist;
  19. vec3 color; // w component not used
  20. float strength;
  21. };
  22. readonly layout(std140) buffer u_pointLights
  23. {
  24. Pointlight light[];
  25. };
  26. uniform int u_pointLightCount;
  27. //uniform Pointlight u_pointLights;
  28. struct MaterialStruct
  29. {
  30. vec4 kd;
  31. vec4 rma;
  32. //float kdr; //= 1;
  33. //float kdg; //= 1;
  34. //float kdb; //= 1;
  35. //float roughness;
  36. //float metallic;
  37. //float ao; //one means full light
  38. };
  39. readonly layout(std140) buffer u_material
  40. {
  41. MaterialStruct mat[];
  42. };
  43. //todo move some of this from global for implementing multi lights
  44. vec3 normal; //the normal of the object (can be normal mapped or not)
  45. vec3 noMappedNorals; //this is the original non normal mapped normal
  46. vec3 viewDir;
  47. float difuseTest; // used to check if object is in the light
  48. vec4 color; //texture color
  49. float PI = 3.14159265359;
  50. //https://gamedev.stackexchange.com/questions/22204/from-normal-to-rotation-matrix#:~:text=Therefore%2C%20if%20you%20want%20to,the%20first%20and%20second%20columns.
  51. mat3x3 NormalToRotation(in vec3 normal)
  52. {
  53. // Find a vector in the plane
  54. vec3 tangent0 = cross(normal, vec3(1, 0, 0));
  55. if (dot(tangent0, tangent0) < 0.001)
  56. tangent0 = cross(normal, vec3(0, 1, 0));
  57. tangent0 = normalize(tangent0);
  58. // Find another vector in the plane
  59. vec3 tangent1 = normalize(cross(normal, tangent0));
  60. // Construct a 3x3 matrix by storing three vectors in the columns of the matrix
  61. return mat3x3(tangent0,tangent1,normal);
  62. //return ColumnVectorsToMatrix(tangent0, tangent1, normal);
  63. }
  64. subroutine vec3 GetNormalMapFunc(vec3);
  65. subroutine (GetNormalMapFunc) vec3 normalMapped(vec3 v)
  66. {
  67. vec3 normal = texture2D(u_normalSampler, v_texCoord).rgb;
  68. normal = normalize(2*normal - 1.f);
  69. mat3 rotMat = NormalToRotation(v);
  70. normal = rotMat * normal;
  71. normal = normalize(normal);
  72. return normal;
  73. }
  74. subroutine (GetNormalMapFunc) vec3 noNormalMapped(vec3 v)
  75. {
  76. return v;
  77. }
  78. subroutine uniform GetNormalMapFunc getNormalMapFunc;
  79. //albedo
  80. subroutine vec4 GetAlbedoFunc();
  81. subroutine (GetAlbedoFunc) vec4 sampledAlbedo()
  82. {
  83. color = texture2D(u_albedoSampler, v_texCoord).xyzw;
  84. if(color.w <= 0.1)
  85. discard;
  86. color.rgb = pow(color.rgb, vec3(2.2,2.2,2.2)).rgb; //gamma corection
  87. color *= vec4(mat[u_materialIndex].kd.r, mat[u_materialIndex].kd.g, mat[u_materialIndex].kd.b, 1); //(option) multiply texture by kd
  88. return color;
  89. }
  90. subroutine (GetAlbedoFunc) vec4 notSampledAlbedo()
  91. {
  92. return vec4(mat[u_materialIndex].kd.r, mat[u_materialIndex].kd.g, mat[u_materialIndex].kd.b, 1);
  93. }
  94. subroutine uniform GetAlbedoFunc u_getAlbedo;
  95. subroutine vec3 GetMaterialMapped();
  96. subroutine (GetMaterialMapped) vec3 materialNone()
  97. {
  98. return vec3(mat[u_materialIndex].rma.x, mat[u_materialIndex].rma.y, mat[u_materialIndex].rma.z);
  99. }
  100. subroutine (GetMaterialMapped) vec3 materialR()
  101. {
  102. float r = texture2D(u_RMASampler, v_texCoord).r;
  103. return vec3(r, mat[u_materialIndex].rma.y, mat[u_materialIndex].rma.z);
  104. }
  105. subroutine (GetMaterialMapped) vec3 materialM()
  106. {
  107. float m = texture2D(u_RMASampler, v_texCoord).r;
  108. return vec3(mat[u_materialIndex].rma.x, m, mat[u_materialIndex].rma.z);
  109. }
  110. subroutine (GetMaterialMapped) vec3 materialA()
  111. {
  112. float a = texture2D(u_RMASampler, v_texCoord).r;
  113. return vec3(mat[u_materialIndex].rma.x, mat[u_materialIndex].rma.y, a);
  114. }
  115. subroutine (GetMaterialMapped) vec3 materialRM()
  116. {
  117. vec2 v = texture2D(u_RMASampler, v_texCoord).rg;
  118. return vec3(v.x, v.y, mat[u_materialIndex].rma.z);
  119. }
  120. subroutine (GetMaterialMapped) vec3 materialRA()
  121. {
  122. vec2 v = texture2D(u_RMASampler, v_texCoord).rb;
  123. return vec3(v.x, mat[u_materialIndex].rma.y, v.y);
  124. }
  125. subroutine (GetMaterialMapped) vec3 materialMA()
  126. {
  127. vec2 v = texture2D(u_RMASampler, v_texCoord).gb;
  128. return vec3(mat[u_materialIndex].rma.x, v.x, v.y);
  129. }
  130. subroutine (GetMaterialMapped) vec3 materialRMA()
  131. {
  132. return texture2D(u_RMASampler, v_texCoord).rgb;
  133. }
  134. subroutine uniform GetMaterialMapped u_getMaterialMapped;
  135. //n normal
  136. //h halfway vector
  137. //a roughness (1 rough, 0 glossy)
  138. //this gets the amount of specular light reflected
  139. float DistributionGGX(vec3 N, vec3 H, float roughness)
  140. {
  141. float a = roughness*roughness;
  142. float a2 = a*a;
  143. float NdotH = max(dot(N, H), 0.0);
  144. float NdotH2 = NdotH*NdotH;
  145. float denom = (NdotH2 * (a2 - 1.0) + 1.0);
  146. denom = PI * denom * denom;
  147. return a2 / max(denom, 0.0000001);
  148. }
  149. float GeometrySchlickGGX(float NdotV, float roughness)
  150. {
  151. float r = (roughness + 1.0);
  152. float k = (r*r) / 8.0;
  153. float num = NdotV;
  154. float denom = NdotV * (1.0 - k) + k;
  155. return num / denom;
  156. }
  157. //oclude light that is hidded begind small geometry roughnesses
  158. float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
  159. {
  160. float NdotV = max(dot(N, V), 0.0);
  161. float NdotL = max(dot(N, L), 0.0);
  162. float ggx2 = GeometrySchlickGGX(NdotV, roughness);
  163. float ggx1 = GeometrySchlickGGX(NdotL, roughness);
  164. return ggx1 * ggx2;
  165. }
  166. //cosTheta is the dot between the normal and halfway
  167. //ratio between specular and diffuse reflection
  168. vec3 fresnelSchlick(float cosTheta, vec3 F0)
  169. {
  170. return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
  171. }
  172. vec3 computePointLightSource(vec3 lightPosition, float metallic, float roughness, in vec3 lightColor)
  173. {
  174. vec3 lightDirection = normalize(lightPosition - v_position);
  175. vec3 halfwayVec = normalize(lightDirection + viewDir);
  176. float dist = length(lightPosition - v_position);
  177. float attenuation = 1.0 / pow(dist,2);
  178. attenuation = 1; //(option) remove light attenuation
  179. vec3 radiance = lightColor * attenuation; //here the first component is the light color
  180. vec3 F0 = vec3(0.04);
  181. F0 = mix(F0, color.rgb, metallic); //here color is albedo, metalic surfaces use albdeo
  182. vec3 F = fresnelSchlick(max(dot(halfwayVec, viewDir), 0.0), F0);
  183. float NDF = DistributionGGX(normal, halfwayVec, roughness);
  184. float G = GeometrySmith(normal, viewDir, lightDirection, roughness);
  185. float denominator = 4.0 * max(dot(normal, viewDir), 0.0)
  186. * max(dot(normal, lightDirection), 0.0);
  187. vec3 specular = (NDF * G * F) / max(denominator, 0.001);
  188. vec3 kS = F; //this is the specular contribution
  189. vec3 kD = vec3(1.0) - kS; //the difuse is the remaining specular
  190. kD *= 1.0 - metallic; //metallic surfaces are darker
  191. // scale light by NdotL
  192. float NdotL = max(dot(normal, lightDirection), 0.0);
  193. vec3 Lo = (kD * color.rgb / PI + specular) * radiance * NdotL;
  194. return Lo;
  195. }
  196. void main()
  197. {
  198. //vec3 sampledMaterial = texture2D(u_RMASampler, v_texCoord).rgb;
  199. vec3 sampledMaterial = u_getMaterialMapped();
  200. float roughnessSampled = sampledMaterial.r;
  201. roughnessSampled = max(0.50,roughnessSampled);
  202. float metallicSampled = sampledMaterial.g;
  203. float sampledAo = sampledMaterial.b;
  204. { //general data
  205. color = u_getAlbedo();
  206. noMappedNorals = normalize(v_normals);
  207. normal = getNormalMapFunc(noMappedNorals);
  208. //normal = noMappedNorals; //(option) remove normal mapping
  209. viewDir = u_eyePosition - v_position;
  210. viewDir = normalize(viewDir); //v
  211. //difuseTest = dot(noMappedNorals, lightDirection); // used to check if object is in the light
  212. }
  213. vec3 I = normalize(v_position - u_eyePosition); //looking direction (towards eye)
  214. vec3 R = reflect(I, normal); //reflected vector
  215. vec3 skyBoxSpecular = textureCube(u_skybox, R).rgb; //this is the reflected color
  216. vec3 skyBoxDiffuse = textureCube(u_skybox, normal).rgb; //this color is coming directly to the object
  217. vec3 Lo = vec3(0,0,0); //this is the accumulated light
  218. //foreach point light
  219. for(int i=0; i<u_pointLightCount;i++)
  220. {
  221. vec3 lightPosition = light[i].positions.xyz;
  222. vec3 lightColor = light[i].color.rgb;
  223. Lo += computePointLightSource(lightPosition, metallicSampled, roughnessSampled, lightColor);
  224. }
  225. vec3 ambient = vec3(0.03) * color.rgb * sampledAo; //this value is made up
  226. vec3 color = Lo + ambient;
  227. //HDR
  228. //color = color / (color + vec3(1.0));
  229. float exposure = 1;
  230. color = vec3(1.0) - exp(-color * exposure);
  231. //gamma correction
  232. color = pow(color, vec3(1.0/2.2));
  233. //color = clamp(color, 0, 1);
  234. //specularVec *= skyBoxSpecular;
  235. //ambientVec *= mix(skyBoxSpecular.rgb, skyBoxIntensity.rgb, 0.5);
  236. //ambientVec = mix(ambientVec, skyBoxSpecular, 0.5);
  237. //ambientVec *= skyBoxSpecular;
  238. //color.rgb *= (clamp(ambientVec + difuseVec, 0, 1) + specularVec);
  239. //vec3 caleidoscop = mix(skyBoxSpecular, color.rgb, cross(normal, viewDir));
  240. //float dotNormalEye = dot(normal, viewDir);
  241. //dotNormalEye = clamp(dotNormalEye, 0, 1);
  242. //color.rgb = mix(skyBoxSpecular, color.rgb, pow(dotNormalEye, 1/1.0) ); //90 degrees, 0, reflected color
  243. //color = caleidoscop;
  244. a_outColor = clamp(vec4(color.rgb,1), 0, 1);
  245. //a_outColor = vec4(sampledMaterial.rgb,1);
  246. }