uniform vec3 camPos;
-uniform sampler2D albedoMap;
-uniform sampler2D normalMap;
-uniform sampler2D metallicMap;
-uniform sampler2D roughnessMap;
-uniform sampler2D aoMap;
+struct Material {
+ sampler2D albedoMap;
+ sampler2D normalMap;
+ sampler2D metallicRoughnessMap;
+ sampler2D aoMap;
+ bool hasAlbedo, hasNormal, hasMetallicRoughness, hasAo;
+};
+uniform Material mat;
+
uniform samplerCube irradianceMap;
+uniform samplerCube prefilterMap;
+uniform sampler2D brdfMap;
out vec4 fragColor;
-uniform vec3 lightPositions[4];
-uniform vec3 lightColors[4];
+uniform int numLights;
+uniform vec3 lightPositions[8];
+uniform vec3 lightColors[8];
const float PI = 3.14159265359;
}
vec3 getNormalFromMap() {
- vec3 tangentNormal = texture(normalMap, texCoords).xyz * 2.f - 1.f;
+ vec3 tangentNormal = vec3(0, 0, 1);
+ if (mat.hasNormal)
+ tangentNormal = texture(mat.normalMap, texCoords).xyz * 2.f - 1.f;
vec3 Q1 = dFdx(worldPos);
vec3 Q2 = dFdy(worldPos);
vec2 st1 = dFdx(texCoords);
}
void main() {
- vec3 albedo = pow(texture(albedoMap, texCoords).rgb, vec3(2.2));
+ vec3 albedo = vec3(1);
+ if (mat.hasAlbedo)
+ albedo = pow(texture(mat.albedoMap, texCoords).rgb, vec3(2.2));
+
vec3 normal = getNormalFromMap();
- float metallic = texture(metallicMap, texCoords).r;
- float roughness = texture(roughnessMap, texCoords).r;
- float ao = texture(aoMap, texCoords).r;
+
+ float metallic = 0, roughness = 1;
+ if (mat.hasMetallicRoughness) {
+ metallic = texture(mat.metallicRoughnessMap, texCoords).b;
+ roughness = texture(mat.metallicRoughnessMap, texCoords).g;
+ }
+ float ao = mat.hasAo ? texture(mat.aoMap, texCoords).r : 1;
vec3 N = normalize(normal);
vec3 V = normalize(camPos - worldPos);
vec3 F0 = mix(vec3(0.04), albedo, metallic);
+ vec3 R = reflect(-V, N);
+
// reflectance
vec3 Lo = vec3(0.f);
- for (int i = 0; i < lightPositions.length(); i++) {
+ for (int i = 0; i < numLights; i++) {
vec3 L = normalize(lightPositions[i] - worldPos);
vec3 H = normalize(V + L);
Lo += (kD * albedo / PI + specular) * radiance * mdot(N, L);
}
- vec3 kD = 1.f - fresnelSchlickRoughness(mdot(N, V), F0, roughness);
- vec3 diffuse = texture(irradianceMap, N).rgb * albedo;
- vec3 ambient = (kD * diffuse) * ao;
+ vec3 F = fresnelSchlickRoughness(mdot(N, V), F0, roughness);
+
+ vec3 kS = F;
+ vec3 kD = (1.f - kS) * (1.f - metallic);
+
+ vec3 irradiance = texture(irradianceMap, N).rgb;
+ vec3 diffuse = irradiance * albedo;
+
+ const float maxReflectionLoD = 4.f;
+ vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * maxReflectionLoD).rgb;
+ vec2 envBRDF = texture(brdfMap, vec2(mdot(N, V), roughness)).rg;
+ vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
+
+ vec3 ambient = (kD * diffuse + specular) * ao;
vec3 color = ambient + Lo;
color = color / (color + vec3(1.f)); // map to HDR