diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs index a9cf1a3e..48688ebe 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.fs +++ b/examples/shaders/resources/shaders/glsl100/pbr.fs @@ -54,23 +54,22 @@ uniform vec3 viewPos; uniform vec3 ambientColor; uniform float ambient; -// refl in range 0 to 1 -// returns base reflectivity to 1 -// incrase reflectivity when surface view at larger angle -vec3 schlickFresnel(float hDotV,vec3 refl) +// Reflectivity in range 0.0 to 1.0 +// NOTE: Reflectivity is increased 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); + 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; @@ -80,7 +79,7 @@ float geomSmith(float nDotV, float nDotL, float roughness) return ggx1*ggx2; } -vec3 pbr() +vec3 ComputePBR() { 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); @@ -104,23 +103,23 @@ vec3 pbr() 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); - + + vec3 emissive = vec3(0); + emissive = (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 + vec3 lightAccum = 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 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 @@ -128,9 +127,9 @@ vec3 pbr() 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 + 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); @@ -138,25 +137,25 @@ vec3 pbr() // 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 + // 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 + lightAccum += ((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); + return (ambientFinal + lightAccum*ao + emissive); } void main() { - vec3 color = pbr(); - + vec3 color = ComputePBR(); + // HDR tonemapping - color = pow(color,color + vec3(1.0)); + color = pow(color, color + vec3(1.0)); // Gamma correction - color = pow(color,vec3(1.0/2.2)); + 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 5a93f784..a55c0ea4 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.vs +++ b/examples/shaders/resources/shaders/glsl100/pbr.vs @@ -51,16 +51,16 @@ mat3 transpose(mat3 m) void main() { - // calc binormal from vertex normal and tangent + // Compute binormal from vertex normal and tangent vec3 vertexBinormal = cross(vertexNormal, vertexTangent); - // calc fragment normal based on normal transformations + + // Compute fragment normal based on normal transformations mat3 normalMatrix = transpose(inverse(mat3(matModel))); - // calc fragment position based on model transformations + // Compute fragment position based on model transformations fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); fragTexCoord = vertexTexCoord*2.0; - fragNormal = normalize(normalMatrix*vertexNormal); vec3 fragTangent = normalize(normalMatrix*vertexTangent); fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); @@ -70,5 +70,5 @@ void main() TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal)); // Calculate final vertex position - gl_Position = mvp * vec4(vertexPosition, 1.0); + gl_Position = mvp*vec4(vertexPosition, 1.0); } diff --git a/examples/shaders/resources/shaders/glsl120/pbr.fs b/examples/shaders/resources/shaders/glsl120/pbr.fs index 1c5eee00..63241709 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.fs +++ b/examples/shaders/resources/shaders/glsl120/pbr.fs @@ -22,7 +22,6 @@ varying vec3 fragNormal; varying vec4 shadowPos; varying mat3 TBN; - // Input uniform values uniform int numOfLights; uniform sampler2D albedoMap; @@ -53,102 +52,108 @@ uniform vec3 viewPos; uniform vec3 ambientColor; uniform float ambient; -// refl in range 0 to 1 -// returns base reflectivity to 1 -// incrase reflectivity when surface view at larger angle -vec3 schlickFresnel(float hDotV,vec3 refl) +// Reflectivity in range 0.0 to 1.0 +// NOTE: Reflectivity is increased 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 ComputePBR() +{ + 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 emissive = vec3(0); + emissive = (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 lightAccum = 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