195 lines
5.3 KiB
GLSL
195 lines
5.3 KiB
GLSL
|
#include "lighting.glsl"
|
||
|
|
||
|
in VS_OUT {
|
||
|
vec3 FragPos;
|
||
|
vec3 Normal;
|
||
|
vec2 TexCoords;
|
||
|
mat3 TBN;
|
||
|
} vs_in;
|
||
|
|
||
|
layout(location = 0) out vec4 outColor;
|
||
|
layout(location = 1) out vec4 brightColor;
|
||
|
|
||
|
struct Light {
|
||
|
vec4 position;
|
||
|
vec3 color;
|
||
|
int type;
|
||
|
vec3 direction;
|
||
|
float radius;
|
||
|
mat4 lightspace;
|
||
|
};
|
||
|
|
||
|
layout(std140, binding = 0) uniform UniformSceneData {
|
||
|
mat4 projection, view, model;
|
||
|
vec4 cameraPosition;
|
||
|
} sceneData;
|
||
|
|
||
|
layout(std140, binding = 1) uniform UniformMaterialData {
|
||
|
vec4 albedoTint;
|
||
|
vec3 emission;
|
||
|
float metallic, roughness;
|
||
|
} materialData;
|
||
|
|
||
|
layout(std140, binding = 2) uniform UniformLightData {
|
||
|
Light lights[MAX_LIGHTS];
|
||
|
int numlights;
|
||
|
} lightData;
|
||
|
|
||
|
const mat4 biasMat = mat4(
|
||
|
0.5, 0.0, 0.0, 0.0,
|
||
|
0.0, 0.5, 0.0, 0.0,
|
||
|
0.0, 0.0, 1.0, 0.0,
|
||
|
0.5, 0.5, 0.0, 1.0 );
|
||
|
|
||
|
layout(binding = 3) uniform sampler2D albedo_tex;
|
||
|
layout(binding = 4) uniform sampler2D normal_tex;
|
||
|
layout(binding = 5) uniform sampler2D metallic_tex;
|
||
|
layout(binding = 6) uniform sampler2D roughness_tex;
|
||
|
layout(binding = 7) uniform sampler2D directional_shadow;
|
||
|
layout(binding = 8) uniform samplerCube point_shadow;
|
||
|
|
||
|
float PointShadowCalculation(Light light)
|
||
|
{
|
||
|
if(light.position.w == 0.0f)
|
||
|
return 1.0f;
|
||
|
|
||
|
vec3 fragToLight = vs_in.FragPos - light.position.xyz;
|
||
|
float closestDepth = texture(point_shadow, fragToLight).r;
|
||
|
closestDepth *= 25.0; //far-plane
|
||
|
|
||
|
float currentDepth = length(fragToLight);
|
||
|
|
||
|
float bias = 0.05;
|
||
|
float shadow = currentDepth - bias > closestDepth ? 0.0 : 1.0;
|
||
|
|
||
|
return shadow;
|
||
|
}
|
||
|
|
||
|
float ShadowCalculation(Light light)
|
||
|
{
|
||
|
if(light.position.w == 0.0f)
|
||
|
return 1.0f;
|
||
|
|
||
|
vec4 fragPosLightSpace = light.lightspace * vec4(vs_in.FragPos, 1.0);
|
||
|
|
||
|
float bias = 0.001;
|
||
|
|
||
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||
|
projCoords = projCoords * 0.5 + 0.5;
|
||
|
float closestDepth = texture(directional_shadow, projCoords.xy).r;
|
||
|
float currentDepth = projCoords.z;
|
||
|
float shadow = currentDepth - bias > closestDepth ? 0.0 : 1.0;
|
||
|
|
||
|
return shadow;
|
||
|
}
|
||
|
|
||
|
vec4 GetAlbedo() {
|
||
|
if(textureSize(albedo_tex, 0).x <= 1)
|
||
|
return vec4(materialData.albedoTint.rgb, 1.0);
|
||
|
|
||
|
return vec4(texture(albedo_tex, vs_in.TexCoords).rgb * materialData.albedoTint.rgb, texture(albedo_tex, vs_in.TexCoords).a);
|
||
|
}
|
||
|
|
||
|
vec3 GetNormal() {
|
||
|
if(textureSize(normal_tex, 0).x <= 1)
|
||
|
return normalize(vs_in.Normal);
|
||
|
|
||
|
vec3 normal = texture(normal_tex, vs_in.TexCoords).rgb;
|
||
|
normal = 2.0 * normal - 1.0;
|
||
|
|
||
|
normal = vs_in.TBN * normal;
|
||
|
|
||
|
return normalize(normal);
|
||
|
}
|
||
|
|
||
|
float GetMetallic() {
|
||
|
if(textureSize(metallic_tex, 0).x <= 1)
|
||
|
return materialData.metallic;
|
||
|
|
||
|
return texture(metallic_tex, vs_in.TexCoords).r;
|
||
|
}
|
||
|
|
||
|
float GetRoughness() {
|
||
|
if(textureSize(roughness_tex, 0).x <= 1)
|
||
|
return materialData.roughness;
|
||
|
|
||
|
return texture(roughness_tex, vs_in.TexCoords).r;
|
||
|
}
|
||
|
|
||
|
vec3 CalculatePointLight(Light light, vec3 kD, vec3 F) {
|
||
|
vec3 N = GetNormal();
|
||
|
vec3 V = normalize(sceneData.cameraPosition.xyz - vs_in.FragPos);
|
||
|
|
||
|
vec3 L = normalize(light.position.xyz - vs_in.FragPos);
|
||
|
vec3 H = normalize(V + L);
|
||
|
vec3 radiance = (light.color * (CalculateAttenuation(light.position.xyz, light.radius, vs_in.FragPos) * light.radius)) * PointShadowCalculation(light);
|
||
|
|
||
|
float NDF = DistributionGGX(N, H, GetRoughness());
|
||
|
float G = GeometrySmith(N, V, L, GetRoughness());
|
||
|
|
||
|
vec3 nominator = NDF * G * F;
|
||
|
float denominator = 4 * max(dot(V, N), 0.0) * max(dot(L, N), 0.0) + 0.001;
|
||
|
vec3 brdf = nominator / denominator;
|
||
|
|
||
|
// add to outgoing radiance Lo
|
||
|
float NdotL = max(dot(N, L), 0.0);
|
||
|
|
||
|
return (kD * GetAlbedo().rgb / PI + brdf) * radiance * NdotL;
|
||
|
}
|
||
|
|
||
|
vec3 CalculateDirectionalLight(Light light, vec3 kD, vec3 F) {
|
||
|
vec3 N = GetNormal();
|
||
|
vec3 V = normalize(sceneData.cameraPosition.xyz - vs_in.FragPos);
|
||
|
|
||
|
vec3 L = normalize(-light.direction);
|
||
|
vec3 H = normalize(V + L);
|
||
|
vec3 radiance = light.color * ShadowCalculation(light);
|
||
|
|
||
|
float NDF = DistributionGGX(N, H, GetRoughness());
|
||
|
float G = GeometrySmith(N, V, L, GetRoughness());
|
||
|
|
||
|
vec3 nominator = NDF * G * F;
|
||
|
float denominator = 4 * max(dot(V, N), 0.0) * max(dot(L, N), 0.0) + 0.001;
|
||
|
vec3 brdf = nominator / denominator;
|
||
|
|
||
|
// add to outgoing radiance Lo
|
||
|
float NdotL = max(dot(N, L), 0.0);
|
||
|
|
||
|
return (kD * GetAlbedo().rgb / PI + brdf) * radiance * NdotL;
|
||
|
}
|
||
|
|
||
|
void main() {
|
||
|
if(GetAlbedo().a < 0.1)
|
||
|
discard;
|
||
|
|
||
|
vec3 V = normalize(sceneData.cameraPosition.xyz - vs_in.FragPos);
|
||
|
|
||
|
vec3 F0 = vec3(0.04);
|
||
|
F0 = mix(F0, GetAlbedo().rgb, GetMetallic());
|
||
|
vec3 F = fresnelSchlickRoughness(max(dot(GetNormal(), V), 0.0), F0, GetRoughness());
|
||
|
|
||
|
vec3 kS = F;
|
||
|
vec3 kD = vec3(1.0) - kS;
|
||
|
kD *= 1.0 - GetMetallic();
|
||
|
|
||
|
vec3 result = vec3(0);
|
||
|
for(int i = 0; i < lightData.numlights; i++) {
|
||
|
switch(lightData.lights[i].type) {
|
||
|
case 0:
|
||
|
result += CalculateDirectionalLight(lightData.lights[i], kD, F);
|
||
|
break;
|
||
|
case 1:
|
||
|
result += CalculatePointLight(lightData.lights[i], kD, F);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vec3 ambient = vec3(0.01) * GetAlbedo().rgb;
|
||
|
|
||
|
outColor = vec4(ambient + result + materialData.emission, GetAlbedo().a);
|
||
|
|
||
|
float brightness = dot(outColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||
|
if(brightness > 0.9)
|
||
|
brightColor = vec4(outColor.rgb, 1.0);
|
||
|
}
|