quakeforge/libs/video/renderer/vulkan/shader/lighting_main.finc
Bill Currie a626dc7ca8 [vulkan] Split the lighting pass into per-type passes
This takes care of the type punning issue by each pass using the correct
sampler type with the correct view types bound. Also, point light and
spot light shadow maps are now guaranteed to be separated (it was just
luck that they were before) and spot light maps may be significantly
smaller as their cone angle is taken into account. Lighting is quite
borked, but at least the engine is running again.
2023-08-02 19:34:26 +09:00

71 lines
1.8 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);
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);
}