quakeforge/libs/video/renderer/vulkan/shader/lighting_main.finc
Bill Currie 2fbe44a72e [vulkan] Get point light shadows working
Other than the rather bad shadow acne, this is actually quake itself
working nicely. Still need to get directional lights working for
community maps, and all sorts of other little things (hide view model,
show player, fix brush backfaces, etc).
2023-08-03 00:15:42 +09:00

71 lines
1.9 KiB
Text

#include "lighting.h"
#include "light_attach.h"
layout (location = 0) out vec4 frag_color;
layout (push_constant) uniform PushConstants {
uint queue;
};
float
spot_cone (LightData light, vec3 incoming)
{
vec3 dir = light.direction.xyz;
float cone = light.direction.w;
float spotdot = dot (incoming, dir);
return 1 - smoothstep (cone, .995 * cone + 0.005, spotdot);
}
float
diffuse (vec3 incoming, vec3 normal)
{
float lightdot = dot (incoming, normal);
return clamp (lightdot, 0, 1);
}
void
main (void)
{
vec3 c = subpassLoad (color).rgb;
vec3 e = subpassLoad (emission).rgb;
vec3 n = subpassLoad (normal).rgb;
vec3 p = subpassLoad (position).rgb;
vec3 light = vec3 (0);
uint start = bitfieldExtract (queue, 0, 16);
uint count = bitfieldExtract (queue, 16, 16);
for (uint i = start; i < count; i++) {
uint id = lightIds[i];
LightData l = lights[id];
vec3 dir = l.position.xyz - l.position.w * p;
float r2 = dot (dir, dir);
vec4 a = l.attenuation;
if (l.position.w * a.w * a.w * r2 >= 1) {
continue;
}
vec4 r = vec4 (r2, sqrt(r2), 1, 0);
vec3 incoming = dir / r.y;
float I = (1 - a.w * r.y) / dot (a, r);
uint id_data = renderer[id].id_data;
uint mat_id = bitfieldExtract (id_data, 0, 13);
uint map_id = bitfieldExtract (id_data, 13, 5);
uint layer = bitfieldExtract (id_data, 18, 11);
I *= shadow (map_id, layer, mat_id, p, l.position.xyz);
float namb = dot(l.direction.xyz, l.direction.xyz);
I *= spot_cone (l, incoming) * diffuse (incoming, n);
I = mix (1, I, namb);
vec4 col = l.color;
if (bitfieldExtract(id_data, 31, 1) == 0) {
col *= style[renderer[id].style];
}
light += I * col.w * col.xyz;
}
//light = max (light, minLight);
frag_color = vec4 (light, 1);
}