141 lines
4.2 KiB
GLSL
141 lines
4.2 KiB
GLSL
#version 330 core
|
|
out vec4 FragColor;
|
|
|
|
in vec3 normal;
|
|
in vec2 texCoord;
|
|
in vec3 FragPos;
|
|
in vec4 fragposlightspace;
|
|
|
|
struct DirLight {
|
|
vec3 direction;
|
|
vec3 color;
|
|
float intensity;
|
|
};
|
|
|
|
uniform DirLight dirLight;
|
|
uniform vec3 viewPos;
|
|
|
|
uniform sampler2DShadow shadowMap;
|
|
uniform sampler2D tex;
|
|
uniform samplerCube environmentMap;
|
|
uniform vec4 colorOverride = vec4(0.0);
|
|
uniform int useTexture = 0;
|
|
uniform float metallic = 0.0;
|
|
uniform float roughness = 0.7;
|
|
uniform float ao = 1.0;
|
|
uniform float envIntensity = 0.8;
|
|
|
|
const float PI = 3.14159265359;
|
|
|
|
float DistributionGGX(vec3 N, vec3 H, float rough)
|
|
{
|
|
float a = rough * rough;
|
|
float a2 = a * a;
|
|
float NdotH = max(dot(N, H), 0.0);
|
|
float NdotH2 = NdotH * NdotH;
|
|
float denom = NdotH2 * (a2 - 1.0) + 1.0;
|
|
return a2 / max(PI * denom * denom, 1e-5);
|
|
}
|
|
|
|
float GeometrySchlickGGX(float NdotV, float rough)
|
|
{
|
|
float r = rough + 1.0;
|
|
float k = (r * r) / 8.0;
|
|
return NdotV / (NdotV * (1.0 - k) + k);
|
|
}
|
|
|
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float rough)
|
|
{
|
|
float NdotV = max(dot(N, V), 0.0);
|
|
float NdotL = max(dot(N, L), 0.0);
|
|
return GeometrySchlickGGX(NdotV, rough) * GeometrySchlickGGX(NdotL, rough);
|
|
}
|
|
|
|
vec3 FresnelSchlick(float cosTheta, vec3 F0)
|
|
{
|
|
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
|
}
|
|
|
|
vec3 FresnelSchlickRoughness(float cosTheta, vec3 F0, float rough)
|
|
{
|
|
vec3 f = max(vec3(1.0 - rough), F0);
|
|
return F0 + (f - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
|
}
|
|
|
|
vec3 EnvironmentBRDF(vec3 F0, float rough, float NdotV)
|
|
{
|
|
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
|
|
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
|
|
vec4 r = rough * c0 + c1;
|
|
float a004 = min(r.x * r.x, exp2(-9.28 * NdotV)) * r.x + r.y;
|
|
vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw;
|
|
return F0 * AB.x + AB.y;
|
|
}
|
|
|
|
float ShadowCalculation(vec4 fragPosLightSpace, vec3 N, vec3 L)
|
|
{
|
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
|
projCoords = projCoords * 0.5 + 0.5;
|
|
|
|
if (projCoords.z > 1.0 || any(lessThan(projCoords, vec3(0.0))) ||
|
|
any(greaterThan(projCoords, vec3(1.0))))
|
|
return 1.0;
|
|
|
|
float bias = max(0.004 * (1.0 - dot(N, L)), 0.001);
|
|
vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));
|
|
float shadow = 0.0;
|
|
|
|
for (int x = -1; x <= 1; x++) {
|
|
for (int y = -1; y <= 1; y++) {
|
|
vec2 offset = vec2(x, y) * texelSize;
|
|
shadow += texture(shadowMap, vec3(projCoords.xy + offset, projCoords.z - bias));
|
|
}
|
|
}
|
|
return shadow / 9.0;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec4 albedoSample = vec4(0.8, 0.8, 0.8, 1.0);
|
|
if (useTexture != 0) {
|
|
albedoSample = texture(tex, texCoord);
|
|
if (albedoSample.a < 0.1)
|
|
discard;
|
|
albedoSample.rgb = pow(albedoSample.rgb, vec3(2.2));
|
|
}
|
|
|
|
albedoSample.rgb = mix(albedoSample.rgb, colorOverride.rgb, colorOverride.w);
|
|
|
|
vec3 albedo = albedoSample.rgb;
|
|
float metal = clamp(metallic, 0.0, 1.0);
|
|
float rough = clamp(roughness, 0.04, 1.0);
|
|
|
|
vec3 N = normalize(normal);
|
|
vec3 V = normalize(viewPos - FragPos);
|
|
vec3 L = normalize(-dirLight.direction);
|
|
vec3 H = normalize(V + L);
|
|
float NdotV = max(dot(N, V), 1e-4);
|
|
float NdotL = max(dot(N, L), 0.0);
|
|
|
|
vec3 F0 = mix(vec3(0.04), albedo, metal);
|
|
vec3 F = FresnelSchlick(max(dot(H, V), 0.0), F0);
|
|
float NDF = DistributionGGX(N, H, rough);
|
|
float G = GeometrySmith(N, V, L, rough);
|
|
vec3 specular = (NDF * G * F) / max(4.0 * NdotV * NdotL, 1e-4);
|
|
vec3 kD = (vec3(1.0) - F) * (1.0 - metal);
|
|
vec3 radiance = dirLight.color * dirLight.intensity;
|
|
|
|
float shadow = ShadowCalculation(fragposlightspace, N, L);
|
|
vec3 direct = (kD * albedo / PI + specular) * radiance * NdotL * shadow;
|
|
|
|
vec3 ambientF = FresnelSchlickRoughness(NdotV, F0, rough);
|
|
vec3 ambientKD = (vec3(1.0) - ambientF) * (1.0 - metal);
|
|
vec3 irradiance = pow(textureLod(environmentMap, N, 7.0).rgb, vec3(2.2)) * envIntensity;
|
|
vec3 R = reflect(-V, N);
|
|
vec3 prefiltered = pow(textureLod(environmentMap, R, rough * 7.0).rgb, vec3(2.2)) * envIntensity;
|
|
vec3 specularIBL = prefiltered * EnvironmentBRDF(F0, rough, NdotV);
|
|
vec3 ambient = (ambientKD * irradiance * albedo + specularIBL) * ao;
|
|
|
|
FragColor = vec4(direct + ambient, albedoSample.a);
|
|
}
|