Files
Towards/external/loft/examples/viewer/shaders/Shading.frag
T
Martin Slachta a04f0dc262 initial
2026-07-18 14:31:15 +02:00

193 lines
4.9 KiB
GLSL

#version 460
#define M_PI 3.14159265359
layout(location = 0) in vec2 inUV;
layout(location = 0) out vec4 outColor;
// layout(location = 1) out vec4 outBloomThreshold;
layout(set = 1, binding = 1) uniform sampler2D inAlbedo;
layout(set = 1, binding = 2) uniform sampler2D inNormal;
layout(set = 1, binding = 3) uniform sampler2D inPosition;
layout(set = 1, binding = 4) uniform sampler2D inPbr;
// layout(set = 1, binding = 5) uniform sampler2D shadowMap;
float ggx_normal_distr(float NoH, float roughness) {
float a = NoH * roughness;
float k = roughness / (1.0 - NoH * NoH + a * a);
return k * k * (1.0 / M_PI);
}
vec3 schlick(float VoH, vec3 f0) {
return f0 + (vec3(1.0) - f0) * pow(1.0 - VoH, 5.0);
}
float ggx_smith_correlated(float NoV, float NoL, float a) {
float a2 = a * a;
float GGXL = NoV * sqrt((-NoL * a2 + NoL) * NoL + a2);
float GGXV = NoL * sqrt((-NoV * a2 + NoV) * NoV + a2);
return 0.5 / (GGXV + GGXL + 0.0001);
}
vec3 lambert_diffuse(vec3 albedo) {
return albedo / M_PI;
}
layout(set = 0, binding = 0) uniform Camera {
mat4 proj;
mat4 view;
vec4 position;
} cam;
struct Light {
mat4 view;
vec4 color;
vec4 position;
};
layout(set = 1, binding = 0) uniform Lights {
Light lights[];
} lights;
#define AMBIENT 0.1
float linearize_depth(float depth) {
float n = 1000.0f;
float f = 1.0f;
float z = depth;
return (2.0 * n) / (f + n - z * (f - n));
}
float textureProj(vec4 shadowCoord, vec2 off) {
return 0.0f;
/* float shadow = 0.0f;
float dist = texture( shadowMap, shadowCoord.st + off ).r;
if ( shadowCoord.w > 0.0 )
{
shadow = (dist < shadowCoord.z) ? 1.0f : 0.0f;
}
return shadow; */
}
float filterPCF(vec4 sc) {
return 0.0f;
/* ivec2 texDim = textureSize(shadowMap, 0);
float scale = 6.0f;
float dx = scale * 1.0 / float(texDim.x);
float dy = scale * 1.0 / float(texDim.y);
float shadowFactor = 0.0;
int count = 0;
int range = 12;
for (int x = -range; x <= range; x++)
{
for (int y = -range; y <= range; y++)
{
shadowFactor += textureProj(sc, vec2(dx*x, dy*y));
count++;
}
}
return shadowFactor / count; */
}
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
);
float get_shadow(int lightIdx, vec4 position) {
Light light = lights.lights[0];
vec4 relativePosition = light.view * position;
vec4 shadowCoords = relativePosition / relativePosition.w;
float shadow = filterPCF(biasMat * shadowCoords);
return shadow;
}
vec3 bsdf(vec3 normal, vec3 viewDir, vec3 lightDir, vec3 baseColor, float metallic, float roughness) {
vec3 halfway = normalize(viewDir + lightDir);
float NoH = max(0.0, dot(normal, halfway));
float NoL = max(0.0, dot(normal, lightDir));
float NoV = abs(dot(normal, viewDir)) + 1e-5;
float VoH = max(0.0, dot(viewDir, halfway));
float LoH = max(0.0, dot(lightDir, halfway));
/* color at 0 degree angle */
vec3 f0 = 0.16 * (1.0 - roughness) * (1.0 - roughness) * (1.0 - metallic) + baseColor * metallic;
vec3 diffuseColor = (1.0 - metallic) * baseColor.rgb;
/* normal distribution of the dome */
float D = ggx_normal_distr(NoH, roughness);
/* occlusion of microfacets */
float G = ggx_smith_correlated(NoV, NoL, roughness);
/* fresnel */
vec3 F = schlick(VoH, f0);
vec3 specular = D * G * F; /// (4.0 * NoV * NoL + 0.0001);
/* light emmited back by material (not reflection) */
vec3 diffuse = lambert_diffuse(diffuseColor);
return (diffuse + specular) * NoL * 4.0f;
}
vec3 bloom_threshold(vec3 base) {
float threshold = 0.8f;
float knee = 0.5f;
float intensity = 0.4f;
vec4 curveThreshold = vec4(threshold - knee, knee * 2.0f, 0.25f / max(1e-5f, knee), threshold);
// Pixel brightness
float br = max((base).x, max((base).y, (base).z));
// Under-threshold part: quadratic curve
float rq = clamp(br - curveThreshold.x, 0.0, curveThreshold.y);
rq = curveThreshold.z * rq * rq;
// Combine and apply the brightness response curve.
base *= max(rq, br - curveThreshold.w) / max(1e-5, br);
// Clamp pixel intensity if clamping enabled
if (intensity > 0.0) {
br = max(1e-5, max((base).x, max((base).y, (base).z)));
base *= 1.0 - max(0.0, br - intensity) / br;
}
return base;
}
void main() {
vec3 color = texture(inAlbedo, inUV).rgb;
float metallic = texture(inPbr, inUV).r;
float roughness = texture(inPbr, inUV).g;
roughness *= roughness;
vec3 normal = texture(inNormal, inUV).rgb;
vec3 position = texture(inPosition, inUV).rgb;
vec3 viewDir = normalize(-cam.position.xyz - position);
vec3 lightDir = -normalize(vec3(lights.lights[0].view[0][2], lights.lights[0].view[1][2], lights.lights[0].view[2][2]));
float occlusion = get_shadow(0, vec4(position, 1.0));
float lightIntensity = 1.5f;
vec3 Lo = bsdf(normal, viewDir, lightDir, color, metallic, roughness);
vec3 ambient = vec3(0.2) * color;
vec3 prd = ambient + Lo * (1.0 - occlusion) * lightIntensity;
outColor = vec4(prd, 1.0);
// outBloomThreshold = vec4(bloom_threshold(prd), dot(bloom_threshold(prd), bloom_threshold(prd)));
}