diff --git a/include/Lights.h b/include/Lights.h index 8bc0724..189ede4 100644 --- a/include/Lights.h +++ b/include/Lights.h @@ -3,6 +3,11 @@ #include +#include "Buffers.h" + +// Максимальное число источников света +#define MAX_LIGHTS 300 + // Точечный источник света struct LightData { @@ -10,4 +15,15 @@ struct LightData alignas(16) glm::vec3 color; // Цвет }; +// Источник света +class Light +{ + public: + static int getUBOsize(); // Возвращает размер буфера в байтах + static void upload(UBO& lights_data); // Загрузка данных в буфер + + static GLuint count; // количество используемых источников (должно быть <= MAX_LIGHTS) + static LightData data[MAX_LIGHTS]; // Массив данных по источникам света +}; + #endif // LIGHTS_H diff --git a/shaders/lighting.frag b/shaders/lighting.frag index 79ad7c3..0896551 100644 --- a/shaders/lighting.frag +++ b/shaders/lighting.frag @@ -9,10 +9,16 @@ layout(std140, binding = 0) uniform Camera vec3 position; } camera; -layout(std140, binding = 2) uniform Light +struct LightData { vec3 position; vec3 color; +}; + +layout(std140, binding = 2) uniform Light +{ + LightData data[300]; + int count; } light_f; uniform sampler2D gPosition; @@ -32,20 +38,35 @@ void main() float ks = texture(gAmbientSpecular, texCoord).a; float p = texture(gDiffuseP, texCoord).a; - // Данные о камере относительно фрагмента - vec3 Cam_vertex = normalize(camera.position - fragPos); - // Данные об источнике отностиельно фрагмента - vec3 L_vertex = normalize(light_f.position - fragPos); - - // Диффузная составляющая - float diffuse = max(dot(L_vertex, N), 0.0); // скалярное произведение с отсеканием значений < 0 + // Переменные используемые в цикле: + vec3 L_vertex; // Данные об источнике относительно фрагмента + vec3 Cam_vertex = normalize(camera.position - fragPos); // Данные о камере относительно фрагмента + float diffuse; // Диффузная составляющая + vec3 H; // Вектор половины пути + float specular; // Зеркальная составляющая - // Вектор половины пути - vec3 H = normalize(L_vertex + Cam_vertex); - // Зеркальная составляющая - float specular = pow(max(dot(H, N), 0.0), p*4); // скалярное произведение с отсеканием значений < 0 в степени p + // Фоновая освещенность + color = vec4(ka, 1); - color = vec4(ka, 1) - + vec4(light_f.color*kd*diffuse, 1) - + vec4(light_f.color*ks*specular, 1); + // Цикл по источникам света + int i; + for (i = 0; i < light_f.count; i++) + { + // Данные об источнике относительно фрагмента + L_vertex = light_f.data[i].position - fragPos; + + // Нормирование вектора + L_vertex = normalize(L_vertex); + + // Диффузная составляющая + 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(light_f.data[i].color*kd*diffuse, 1) + + vec4(light_f.data[i].color*ks*specular, 1); + } } \ No newline at end of file diff --git a/src/Lights.cpp b/src/Lights.cpp new file mode 100644 index 0000000..f1e2e2e --- /dev/null +++ b/src/Lights.cpp @@ -0,0 +1,22 @@ +#include "Lights.h" + +GLuint Light::count = 0; // количество используемых источников (должно быть <= MAX_LIGHTS) +LightData Light::data[MAX_LIGHTS]; // Массив данных по источникам света + +// возвращает размер буфера в байтах +int Light::getUBOsize() +{ + return sizeof(LightData) * MAX_LIGHTS + sizeof(GLuint); +} + +// Загрузка данных в буфер +void Light::upload(UBO& lights_data) +{ + GLuint LightDataSize = sizeof(LightData); // Одного экземпляра структуры LightData + + if (count) + lights_data.loadSub(data, sizeof(LightData)*count); // Загрузка данных об источниках + + // Загружаем кол-во источников + lights_data.loadSub(&count, sizeof(count), LightDataSize*MAX_LIGHTS); +} diff --git a/src/main.cpp b/src/main.cpp index 9ee5f15..65728f1 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -103,15 +103,20 @@ int main(void) // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - // Источник света - LightData light = { {1.0f, 3.0f, 0.0f} // позиция - , {1.0f, 1.0f, 1.0f} // цвет + // Источники света + // Первый способ измений + Light::data[0] = { {0.3f, 0.1f, 0.5f} // позиция + , {1.0f, 0.0f, 0.0f} // цвет }; - + Light::count++; + // Второй способ + Light::data[Light::count].position = {-0.3f, -0.1f, 0.5f}; // позиция + Light::data[Light::count++].color = { 0.0f, 0.0f, 1.0f}; // цвет + // Uniform-буферы UBO cameraUB(sizeof(CameraData), 0); UBO material_data(sizeof(Material), 1); - UBO light_data(&light, sizeof(LightData), 2); + UBO light_data(Light::getUBOsize(), 2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Использование уменьшенных версий mipmap @@ -155,6 +160,8 @@ int main(void) { // Загрузка данных о камере cameraUB.loadSub(&Camera::current().getData(), sizeof(CameraData)); + // Загрузим информацию об источниках света + Light::upload(light_data); // Активируем G-кадра gbuffer.use();