diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs index 70e3b488..a9cf1a3e 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.fs +++ b/examples/shaders/resources/shaders/glsl100/pbr.fs @@ -59,97 +59,104 @@ uniform float ambient; // incrase reflectivity when surface view at larger angle vec3 schlickFresnel(float hDotV,vec3 refl) { - return refl + (1.0 - refl) * pow(1.0 - hDotV,5.0); + return refl + (1.0 - refl)*pow(1.0 - hDotV,5.0); } -float ggxDistribution(float nDotH,float roughness) +float ggxDistribution(float nDotH, float roughness) { - float a = roughness * roughness * roughness * roughness; - float d = nDotH * nDotH * (a - 1.0) + 1.0; - d = PI * d * d; - return a / max(d,0.0000001); + float a = roughness*roughness*roughness*roughness; + float d = nDotH*nDotH*(a - 1.0) + 1.0; + d = PI*d*d; + return a/max(d,0.0000001); } -float geomSmith(float nDotV,float nDotL,float roughness) +float geomSmith(float nDotV, float nDotL, float roughness) { - float r = roughness + 1.0; - float k = r * r / 8.0; - float ik = 1.0 - k; - float ggx1 = nDotV / (nDotV * ik + k); - float ggx2 = nDotL / (nDotL * ik + k); - return ggx1 * ggx2; + float r = roughness + 1.0; + float k = r*r/8.0; + float ik = 1.0 - k; + float ggx1 = nDotV/(nDotV*ik + k); + float ggx2 = nDotL/(nDotL*ik + k); + return ggx1*ggx2; } -vec3 pbr(){ - vec3 albedo = texture2D(albedoMap,vec2(fragTexCoord.x*tiling.x+offset.x,fragTexCoord.y*tiling.y+offset.y)).rgb; - albedo = vec3(albedoColor.x*albedo.x,albedoColor.y*albedo.y,albedoColor.z*albedo.z); - float metallic = clamp(metallicValue,0.0,1.0); - float roughness = clamp(roughnessValue,0.0,1.0); - float ao = clamp(aoValue,0.0,1.0); - if(useTexMRA == 1) { - vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x * tiling.x + offset.x, fragTexCoord.y * tiling.y + offset.y)); - metallic = clamp(mra.r+metallicValue,0.04,1.0); - roughness = clamp(mra.g+roughnessValue,0.04,1.0); - ao = (mra.b+aoValue)*0.5; - } - - - - vec3 N = normalize(fragNormal); - if(useTexNormal == 1) { - N = texture2D(normalMap, vec2(fragTexCoord.x * tiling.x + offset.y, fragTexCoord.y * tiling.y + offset.y)).rgb; - N = normalize(N * 2.0 - 1.0); - N = normalize(N * TBN); - } - - vec3 V = normalize(viewPos - fragPosition); +vec3 pbr() +{ + vec3 albedo = texture2D(albedoMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; + albedo = vec3(albedoColor.x*albedo.x, albedoColor.y*albedo.y, albedoColor.z*albedo.z); + + float metallic = clamp(metallicValue, 0.0, 1.0); + float roughness = clamp(roughnessValue, 0.0, 1.0); + float ao = clamp(aoValue, 0.0, 1.0); + + if (useTexMRA == 1) + { + vec4 mra = texture2D(mraMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)); + metallic = clamp(mra.r + metallicValue, 0.04, 1.0); + roughness = clamp(mra.g + roughnessValue, 0.04, 1.0); + ao = (mra.b + aoValue)*0.5; + } + + vec3 N = normalize(fragNormal); + if (useTexNormal == 1) + { + N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb; + N = normalize(N*2.0 - 1.0); + N = normalize(N*TBN); + } + + vec3 V = normalize(viewPos - fragPosition); + + vec3 e = vec3(0); + e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb).g*emissiveColor.rgb*emissivePower*float(useTexEmissive); + + // return N;//vec3(metallic,metallic,metallic); + // If dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity + vec3 baseRefl = mix(vec3(0.04), albedo.rgb, metallic); + vec3 Lo = vec3(0.0); // Acumulate lighting lum + + for (int i = 0; i < 4; i++) + { + vec3 L = normalize(lights[i].position - fragPosition); // Compute light vector + vec3 H = normalize(V + L); // Compute halfway bisecting vector + float dist = length(lights[i].position - fragPosition); // Compute distance to light + float attenuation = 1.0/(dist*dist*0.23); // Compute attenuation + vec3 radiance = lights[i].color.rgb*lights[i].intensity*attenuation; // Compute input radiance, light energy comming in + + // Cook-Torrance BRDF distribution function + float nDotV = max(dot(N,V), 0.0000001); + float nDotL = max(dot(N,L), 0.0000001); + float hDotV = max(dot(H,V), 0.0); + float nDotH = max(dot(N,H), 0.0); + float D = ggxDistribution(nDotH, roughness); // Larger the more micro-facets aligned to H + float G = geomSmith(nDotV, nDotL, roughness); // Smaller the more micro-facets shadow + vec3 F = schlickFresnel(hDotV, baseRefl); // Fresnel proportion of specular reflectance + + vec3 spec = (D*G*F)/(4.0*nDotV*nDotL); - vec3 e = vec3(0); - e = (texture2D(emissiveMap, vec2(fragTexCoord.x*tiling.x+offset.x, fragTexCoord.y*tiling.y+offset.y)).rgb).g * emissiveColor.rgb*emissivePower * float(useTexEmissive); + // Difuse and spec light can't be above 1.0 + // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent + vec3 kD = vec3(1.0) - F; - //return N;//vec3(metallic,metallic,metallic); - //if dia-electric use base reflectivity of 0.04 otherwise ut is a metal use albedo as base reflectivity - vec3 baseRefl = mix(vec3(0.04),albedo.rgb,metallic); - vec3 Lo = vec3(0.0); // acumulate lighting lum - - for(int i=0;i<4;++i){ - - vec3 L = normalize(lights[i].position - fragPosition); // calc light vector - vec3 H = normalize(V + L); // calc halfway bisecting vector - float dist = length(lights[i].position - fragPosition); // calc distance to light - float attenuation = 1.0 / (dist * dist * 0.23); // calc attenuation - vec3 radiance = lights[i].color.rgb * lights[i].intensity * attenuation; // calc input radiance,light energy comming in - - //Cook-Torrance BRDF distribution function - float nDotV = max(dot(N,V),0.0000001); - float nDotL = max(dot(N,L),0.0000001); - float hDotV = max(dot(H,V),0.0); - float nDotH = max(dot(N,H),0.0); - float D = ggxDistribution(nDotH,roughness); // larger the more micro-facets aligned to H - float G = geomSmith(nDotV,nDotL,roughness); // smaller the more micro-facets shadow - vec3 F = schlickFresnel(hDotV, baseRefl); // fresnel proportion of specular reflectance - - vec3 spec = (D * G * F) / (4.0 * nDotV * nDotL); - // difuse and spec light can't be above 1.0 - // kD = 1.0 - kS diffuse component is equal 1.0 - spec comonent - vec3 kD = vec3(1.0) - F; - //mult kD by the inverse of metallnes , only non-metals should have diffuse light - kD *= 1.0 - metallic; - Lo += ((kD * albedo.rgb / PI + spec) * radiance * nDotL)*float(lights[i].enabled); // angle of light has impact on result - } - vec3 ambient_final = (ambientColor + albedo)* ambient * 0.5; - return ambient_final+Lo*ao+e; + // Mult kD by the inverse of metallnes , only non-metals should have diffuse light + kD *= 1.0 - metallic; + Lo += ((kD*albedo.rgb/PI + spec)*radiance*nDotL)*float(lights[i].enabled); // Angle of light has impact on result + } + + vec3 ambientFinal = (ambientColor + albedo)*ambient*0.5; + + return (ambientFinal + Lo*ao + e); } void main() { - vec3 color = pbr(); - - //HDR tonemapping - color = pow(color,color + vec3(1.0)); - //gamma correction - color = pow(color,vec3(1.0/2.2)); - - gl_FragColor = vec4(color,1.0); - + vec3 color = pbr(); + + // HDR tonemapping + color = pow(color,color + vec3(1.0)); + + // Gamma correction + color = pow(color,vec3(1.0/2.2)); + + gl_FragColor = vec4(color,1.0); } diff --git a/examples/shaders/resources/shaders/glsl100/pbr.vs b/examples/shaders/resources/shaders/glsl100/pbr.vs index 87e142e0..5a93f784 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.vs +++ b/examples/shaders/resources/shaders/glsl100/pbr.vs @@ -26,17 +26,17 @@ const float normalOffset = 0.1; // https://github.com/glslify/glsl-inverse mat3 inverse(mat3 m) { - float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; - float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; - float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; - float b01 = a22*a11 - a12*a21; - float b11 = -a22*a10 + a12*a20; - float b21 = a21*a10 - a11*a20; + float b01 = a22*a11 - a12*a21; + float b11 = -a22*a10 + a12*a20; + float b21 = a21*a10 - a11*a20; - float det = a00*b01 + a01*b11 + a02*b21; + float det = a00*b01 + a01*b11 + a02*b21; - return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), + return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10), b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det; } @@ -44,14 +44,13 @@ mat3 inverse(mat3 m) // https://github.com/glslify/glsl-transpose mat3 transpose(mat3 m) { - return mat3(m[0][0], m[1][0], m[2][0], + return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]); } void main() { - // calc binormal from vertex normal and tangent vec3 vertexBinormal = cross(vertexNormal, vertexTangent); // calc fragment normal based on normal transformations