10/shaders/lighting.frag

124 lines
5.3 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#version 420 core
in vec2 texCoord;
layout(std140, binding = 0) uniform Camera
{
mat4 projection;
mat4 view;
vec3 position;
} camera;
struct LightData
{
vec3 position;
vec3 color;
vec3 attenuation;
vec4 direction_angle;
};
layout(std140, binding = 2) uniform Light
{
LightData data[300];
int count;
} light_f;
layout(std140, binding = 3) uniform Sun
{
vec3 direction;
vec3 color;
} sun;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gDiffuseP;
uniform sampler2D gAmbientSpecular;
out vec4 color;
void main()
{
// Получим данные из текстур буфера
vec3 fragPos = texture(gPosition, texCoord).rgb;
vec3 N = texture(gNormal, texCoord).rgb;
vec3 kd = texture(gDiffuseP, texCoord).rgb;
vec3 ka = texture(gAmbientSpecular, texCoord).rgb;
float ks = texture(gAmbientSpecular, texCoord).a;
float p = texture(gDiffuseP, texCoord).a;
// Переменные используемые в цикле:
vec3 L_vertex; // Данные об источнике относительно фрагмента
vec3 Cam_vertex = normalize(camera.position - fragPos); // Данные о камере относительно фрагмента
float diffuse; // Диффузная составляющая
vec3 H; // Вектор половины пути
float specular; // Зеркальная составляющая
float L_distance; // Расстояние от поверхности до источника
float attenuation; // Коэф. угасания
float acosA; // Косинус между вектором от поверхности к источнику и обратным направлением источника
float intensity; // Интенсивность для прожектора
// Фоновая освещенность
color = vec4(ka, 1);
// Расчет солнца, если его цвет не черный
if (length(sun.color) > 0)
{
// Данные об источнике относительно фрагмента
L_vertex = normalize(sun.direction);
// Диффузная составляющая
diffuse = max(dot(L_vertex, N), 0.0); // скалярное произведение с отсеканием значений < 0
// Вектор половины пути
H = normalize(L_vertex + Cam_vertex);
// Зеркальная составляющая
specular = pow(max(dot(H, N), 0.0), p*4); // скалярное произведение с отсеканием значений < 0 в степени p
// Результирующий цвет с учетом солнца
color += vec4(sun.color*kd*diffuse, 1)
+ vec4(sun.color*ks*specular, 1);
}
// Цикл по источникам света
int i;
for (i = 0; i < light_f.count; i++)
{
// Данные об источнике относительно фрагмента
L_vertex = light_f.data[i].position - fragPos;
// Расстояние от поверхности до источника
L_distance = length(L_vertex);
// Проверка на дистанцию
if (L_distance < light_f.data[i].attenuation.r)
{
// Нормирование вектора
L_vertex = normalize(L_vertex);
// арккосинус между вектором от поверхности к источнику и обратным направлением источника
acosA = degrees(acos(dot(-L_vertex, normalize(light_f.data[i].direction_angle.xyz))));
// Если угол меньше угла источника или угол источника минимален, то считаем освещенность
if(acosA <= light_f.data[i].direction_angle.a)
{
// Диффузная составляющая
diffuse = max(dot(L_vertex, N), 0.0); // скалярное произведение с отсеканием значений < 0
// Вектор половины пути
H = normalize(L_vertex + Cam_vertex);
// Зеркальная составляющая
specular = pow(max(dot(H, N), 0.0), p*4); // скалярное произведение с отсеканием значений < 0 в степени p
// Угасание с учетом расстояния
attenuation = 1 / (1 + light_f.data[i].attenuation[1] * L_distance + light_f.data[i].attenuation[2] * L_distance * L_distance);
// Если источник - прожектор, то добавим смягчение
if (light_f.data[i].direction_angle.a < 180)
{
intensity = clamp((light_f.data[i].direction_angle.a - acosA) / 5, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
}
color += vec4(light_f.data[i].color*kd*diffuse * attenuation, 1)
+ vec4(light_f.data[i].color*ks*specular * attenuation, 1);
}
}
}
}