67 lines
2.3 KiB
GLSL
67 lines
2.3 KiB
GLSL
#define MAX_LIGHTS 8
|
||
|
||
struct Light {
|
||
vec2 position;
|
||
vec3 color;
|
||
};
|
||
|
||
extern Light lights[MAX_LIGHTS];
|
||
extern int num_lights;
|
||
extern vec2 sprite_pos; // Мировая позиция спрайта (в метрах)
|
||
extern vec3 ambient; // Эмбиентное освещение
|
||
extern vec3 sky; // Цвет неба
|
||
|
||
// Функция для имитации easing.easeInSine
|
||
float easeInSine(float x) {
|
||
return 1.0 - cos((x * 3.14159) / 2.0);
|
||
}
|
||
|
||
vec4 effect(vec4 vcolor, Image tex, vec2 texture_coords, vec2 screen_coords)
|
||
{
|
||
vec3 baseLight = ambient + (vec3(1.0) - ambient) * sky;
|
||
float luma = dot(baseLight, vec3(0.2126, 0.7152, 0.0722)); // https://en.wikipedia.org/wiki/Relative_luminance
|
||
vec3 characterBaseLight = mix(baseLight, vec3(luma), 0.3); // 30% обесцвечивания, а то глаза выгорают
|
||
|
||
vec4 texColor = Texel(tex, texture_coords);
|
||
if (texColor.a == 0.0) {
|
||
return vec4(0.0);
|
||
}
|
||
|
||
vec3 pointLight = vec3(0.0);
|
||
|
||
for (int i = 0; i < num_lights; i++) {
|
||
vec2 lightPos = lights[i].position;
|
||
vec2 lightVec = lightPos - sprite_pos;
|
||
float dist = length(lightVec);
|
||
|
||
float attenuation = 0.0;
|
||
|
||
// Логика из shadowcaster.lua:
|
||
// if lightPos.y > position.y then
|
||
// 1 - 0.3 * lightVec:length()
|
||
// elseif position.y - lightPos.y < 3 then
|
||
// (1 - easing.easeInSine((position.y - lightPos.y))) - 0.3 * lightVec:length()
|
||
|
||
if (lightPos.y > sprite_pos.y) {
|
||
attenuation = 1.0 - 0.3 * dist;
|
||
} else {
|
||
float yDiff = sprite_pos.y - lightPos.y;
|
||
if (yDiff < 3.0) {
|
||
attenuation = (1.0 - easeInSine(yDiff)) - 0.3 * dist;
|
||
}
|
||
}
|
||
|
||
attenuation = max(attenuation, 0.0);
|
||
pointLight += lights[i].color * attenuation;
|
||
}
|
||
|
||
pointLight = clamp(pointLight, 0.0, 1.0);
|
||
vec3 a = clamp(ambient, 0.0, 1.0);
|
||
|
||
// Канальный множитель: от ambient до 1 в зависимости от точечного света
|
||
// Это гарантирует, что спрайт не будет черным в отсутствие источников света
|
||
vec3 lightMultiplier = a + (vec3(1.0) - a) * pointLight;
|
||
|
||
return vec4(texColor.rgb * (characterBaseLight + pointLight), texColor.a);
|
||
}
|