Compare commits

..

15 Commits
v0.2 ... master

Author SHA1 Message Date
Ковалев Роман Евгеньевич 7c0421c0ea Исправление проблемы с изменением размеров окна 2024-02-29 14:35:27 +03:00
Ковалев Роман Евгеньевич 6cdd1ef845 Исправление проблемы больших координат 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 4785a46cca Рисование сферы области действия источника 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 6d091e022d Функция генерации сферы 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич a4a7df2073 Вычисление коэф. угасания перед отправкой 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич e977037c8a Угасание на шейдере 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 7ad56ddac4 Радиус действия источника 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич deca2767e8 Вывод отладочных лампочек 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 55dfa6d854 Шейдер отладочных лампочек 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич b80ad37d5a Переделка работы с источниками 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич fb8c07434d Оптимизация отправки кол-ва источников 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 311ccfdcd1 Оптимизация загрузки 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 8f24e460dd Неоптимизированная загрузка 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич 1866027900 Дефрагментация данных по источникам 2024-02-27 22:59:21 +03:00
Ковалев Роман Евгеньевич cdcc729d16 Источник как часть сцены 2024-02-27 22:59:21 +03:00
12 changed files with 444 additions and 29 deletions

View File

@ -80,6 +80,8 @@ class RBO
RBO(int w, int h, GLuint component = GL_DEPTH_COMPONENT); // Создает буфер рендера с заданными параметрами размеров и используемых компонент RBO(int w, int h, GLuint component = GL_DEPTH_COMPONENT); // Создает буфер рендера с заданными параметрами размеров и используемых компонент
~RBO(); // Уничтожение буфера ~RBO(); // Уничтожение буфера
void reallocate(int w, int h, GLuint component = GL_DEPTH_COMPONENT); // Изменяет размеры буфера рендера
GLuint getHandler(); // Возвращает дескриптор буфера рендера GLuint getHandler(); // Возвращает дескриптор буфера рендера
protected: protected:
GLuint handler; // Дескриптор GLuint handler; // Дескриптор

View File

@ -3,7 +3,7 @@
#include <GLM/glm.hpp> #include <GLM/glm.hpp>
#include "Buffers.h" #include "Model.h"
// Максимальное число источников света // Максимальное число источников света
#define MAX_LIGHTS 300 #define MAX_LIGHTS 300
@ -13,17 +13,47 @@ struct LightData
{ {
alignas(16) glm::vec3 position; // Позиция alignas(16) glm::vec3 position; // Позиция
alignas(16) glm::vec3 color; // Цвет alignas(16) glm::vec3 color; // Цвет
alignas(16) glm::vec3 attenuation; // Радиус действия источника, линейный и квадратичный коэф. угасания
}; };
// Источник света // Источник света
class Light class Light : public Node
{ {
public: public:
static int getUBOsize(); // Возвращает размер буфера в байтах static int getUBOsize(); // Возвращает размер буфера в байтах
static void upload(UBO& lights_data); // Загрузка данных в буфер static void upload(UBO& lights_data); // Загрузка данных в буфер
static Light& getNew(); // Возвращает ссылку на новый источник света
void destroy(); // Уничтожает источник света
const glm::vec3& c_color() const; // Константный доступ к цвету
glm::vec3& e_color(); // Неконстантная ссылка для изменений цвета
const float& c_radius() const; // Константный доступ к радиусу
float& e_radius(); // Неконстантная ссылка для изменений радиуса
static void render(ShaderProgram &shaderProgram, UBO &material_buffer); // Рисование отладочных лампочек
private:
Light(); // Конструктор без параметров
Light(const Light& copy) = delete; // Конструктор копирования ОТКЛЮЧЕН
Light& operator=(const Light& other); // Оператор присваивания
virtual ~Light();
glm::vec3 color; // Цвет
float radius; // Радиус действия источника
int index; // Индекс в массиве отправки (может не совпадать с lights) для дефрагментированного доступа
static Light& findByIndex(GLuint index); // Возвращает ссылку на источник с нужным индексом
bool uploadReq; // Необходимость загрузки в следствии изменений
void check_id(); // Проверка что не взаимодествуем с пустым источником
void toData(); // Преобразует информацию об источнике в структуру LightData
virtual void recalcMatrices(); // Метод пересчета матрицы трансформации по необходимости, должен сбрасывать флаг changed
static GLuint count; // количество используемых источников (должно быть <= MAX_LIGHTS) static GLuint count; // количество используемых источников (должно быть <= MAX_LIGHTS)
static LightData data[MAX_LIGHTS]; // Массив данных по источникам света static LightData data[MAX_LIGHTS]; // Массив данных по источникам света
static Light lights[MAX_LIGHTS]; // Массив источников-узлов сцены
}; };
#endif // LIGHTS_H #endif // LIGHTS_H

View File

@ -11,6 +11,8 @@
#include <vector> #include <vector>
class Model genShpere(float radius, int sectorsCount, class Node* parent = NULL); // Генерирует сферу заданного радиуса с определенным количеством сегментов
// Класс узла сцены // Класс узла сцены
class Node class Node
{ {

View File

@ -23,6 +23,8 @@ class Texture
Texture& operator=(const Texture& other); // Оператор присваивания Texture& operator=(const Texture& other); // Оператор присваивания
void reallocate(GLuint width, GLuint height, GLuint texType = TEX_DIFFUSE, GLint internalformat = GL_RGBA, GLint format = GL_RGBA, GLenum dataType = GL_FLOAT); // Пересоздает текстуру для имеющегося дескриптора
void use(); // Привязка текстуры void use(); // Привязка текстуры
static void disable(GLuint type); // Отвязка текстуры по типу static void disable(GLuint type); // Отвязка текстуры по типу
GLuint getType(); // Возвращает тип текстуры GLuint getType(); // Возвращает тип текстуры

16
shaders/bulb.frag Normal file
View File

@ -0,0 +1,16 @@
#version 420 core
layout(std140, binding = 1) uniform Material
{
vec3 ka;
vec3 kd;
vec3 ks;
float p;
};
out vec4 color;
void main()
{
color = vec4(ka, 1);
}

17
shaders/bulb.vert Normal file
View File

@ -0,0 +1,17 @@
#version 420 core
layout(location = 0) in vec3 pos;
layout(std140, binding = 0) uniform Camera
{
mat4 projection;
mat4 view;
vec3 position;
} camera;
uniform mat4 model;
void main()
{
gl_Position = camera.projection * camera.view * model * vec4(pos, 1.0);
}

View File

@ -13,6 +13,7 @@ struct LightData
{ {
vec3 position; vec3 position;
vec3 color; vec3 color;
vec3 attenuation;
}; };
layout(std140, binding = 2) uniform Light layout(std140, binding = 2) uniform Light
@ -44,6 +45,8 @@ void main()
float diffuse; // Диффузная составляющая float diffuse; // Диффузная составляющая
vec3 H; // Вектор половины пути vec3 H; // Вектор половины пути
float specular; // Зеркальная составляющая float specular; // Зеркальная составляющая
float L_distance; // Расстояние от поверхности до источника
float attenuation; // Коэф. угасания
// Фоновая освещенность // Фоновая освещенность
color = vec4(ka, 1); color = vec4(ka, 1);
@ -55,6 +58,12 @@ void main()
// Данные об источнике относительно фрагмента // Данные об источнике относительно фрагмента
L_vertex = light_f.data[i].position - fragPos; 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); L_vertex = normalize(L_vertex);
@ -66,7 +75,11 @@ void main()
// Зеркальная составляющая // Зеркальная составляющая
specular = pow(max(dot(H, N), 0.0), p*4); // скалярное произведение с отсеканием значений < 0 в степени p 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); attenuation = 1 / (1 + light_f.data[i].attenuation[1] * L_distance + light_f.data[i].attenuation[2] * L_distance * L_distance);
color += vec4(light_f.data[i].color*kd*diffuse * attenuation, 1)
+ vec4(light_f.data[i].color*ks*specular * attenuation, 1);
}
} }
} }

View File

@ -189,6 +189,13 @@ RBO::~RBO()
glDeleteRenderbuffers(1, &handler); glDeleteRenderbuffers(1, &handler);
} }
// Изменяет размеры буфера рендера
void RBO::reallocate(int w, int h, GLuint component)
{
glBindRenderbuffer(GL_RENDERBUFFER, handler); // Привязка элементного буфера
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
}
// Возвращает дескриптор буфера рендера // Возвращает дескриптор буфера рендера
GLuint RBO::getHandler() GLuint RBO::getHandler()
{ {

View File

@ -1,7 +1,12 @@
#include "Lights.h" #include "Lights.h"
#include "Scene.h" // Для отладочного вывода лампочек
#include <stdexcept>
GLuint Light::count = 0; // количество используемых источников (должно быть <= MAX_LIGHTS) GLuint Light::count = 0; // количество используемых источников (должно быть <= MAX_LIGHTS)
LightData Light::data[MAX_LIGHTS]; // Массив данных по источникам света LightData Light::data[MAX_LIGHTS]; // Массив данных по источникам света
Light Light::lights[MAX_LIGHTS]; // Массив источников-узлов сцены
// возвращает размер буфера в байтах // возвращает размер буфера в байтах
int Light::getUBOsize() int Light::getUBOsize()
@ -13,10 +18,200 @@ int Light::getUBOsize()
void Light::upload(UBO& lights_data) void Light::upload(UBO& lights_data)
{ {
GLuint LightDataSize = sizeof(LightData); // Одного экземпляра структуры LightData GLuint LightDataSize = sizeof(LightData); // Одного экземпляра структуры LightData
int first = MAX_LIGHTS, last = -1; // Начало и конец диапазона загрузки источников
static GLuint prev_count = -1; // Кол-во источников в прошлую посылку
if (count) if (count)
lights_data.loadSub(data, sizeof(LightData)*count); // Загрузка данных об источниках {
for (int i = 0; i < MAX_LIGHTS; i++)
{
lights[i].recalcMatrices(); // Пересчитаем матрицы по необходимости (проверка внутри метода)
// Если требуется загрузка
if (lights[i].uploadReq)
{
lights[i].toData(); // Перевод ноды в данные для шейдера
// Определение диапазона загрузки
if (first > lights[i].index)
first = lights[i].index;
if (last < lights[i].index)
last = lights[i].index;
lights[i].uploadReq = false; // Сброс флага
}
}
// Если есть что загрузить (определен диапазон)
if (last > -1)
lights_data.loadSub(data + first, LightDataSize*(last - first +1), LightDataSize*(first)); // Загрузка данных об источниках
}
// Если кол-во изменилось
if (prev_count != count)
{
prev_count = count;
// Загружаем кол-во источников // Загружаем кол-во источников
lights_data.loadSub(&count, sizeof(count), LightDataSize*MAX_LIGHTS); lights_data.loadSub(&count, sizeof(count), LightDataSize*MAX_LIGHTS);
}
}
// Метод пересчета матрицы трансформации по необходимости, должен сбрасывать флаг changed
void Light::recalcMatrices()
{
// Если были изменения - необходимо загрузить данные
if (changed || parent_changed)
uploadReq = true;
// Выполняем вычисление матриц методом родительского класса
Node::recalcMatrices();
}
// Константный доступ к цвету
const glm::vec3& Light::c_color() const
{
return color;
}
// Неконстантная ссылка для изменений цвета
glm::vec3& Light::e_color()
{
uploadReq = true;
return color;
}
// Проверка что не взаимодествуем с пустым источником
void Light::check_id()
{
if (index < 0
|| index >= count)
throw std::runtime_error("Попытка использовать ссылку на пустой или некорректный источник");
}
// Преобразует информацию об источнике в структуру LightData
void Light::toData()
{
check_id(); // Проверка на работу с корректным индексом
data[index].position = glm::vec3(result_transform[3]); // Позиция из матрицы трансформации
data[index].color = color; // Цвет
// Если радиус изменился
if (data[index].attenuation.r != radius)
{
data[index].attenuation.r = radius; // Радиус действия источника
data[index].attenuation[1] = 4.5/radius; // Линейный коэф. угасания
data[index].attenuation[2] = 4 * data[index].attenuation[1] * data[index].attenuation[1]; // Квадратичный коэф. угасания
}
}
// Возвращает ссылку на новый источник света
Light& Light::getNew()
{
Light& refNew = findByIndex(-1);
refNew.index = count++;
refNew.uploadReq = true;
return refNew;
}
// Уничтожает источник света
void Light::destroy()
{
check_id(); // Проверка на работу с корректным индексом
// Если удаляемый элемент не последний
if (count-1 != index)
{
// Найдем элемент для замены
Light& replace = findByIndex(--count);
replace.uploadReq = true; // Требуется загрузить данные
replace.index = index; // Заменяем индекс данных
}
operator=(Light()); // Обнулим источник путем замены на новый
}
// Возвращает ссылку на источник с нужным индексом
Light& Light::findByIndex(GLuint index)
{
// Если нет источников - возвращаем нулевой
if (!count)
return lights[0];
// Цикл по перебору источников
for (int i = 0; i < MAX_LIGHTS; i++)
if (lights[i].index == index)
return lights[i];
throw std::runtime_error("Запрашиваемый источник освещения не найден, либо достигнут лимит");
}
// Конструктор без параметров
Light::Light() : Node(), index(-1), uploadReq(false), color(1.0f), radius(10.0f)
{
}
// Оператор присваивания
Light& Light::operator=(const Light& other)
{
// Проверка на самоприсваивание
if (this != &other)
{
index = other.index; // Переносим индекс
uploadReq = other.uploadReq; // Необходимость загрузки
color = other.color;
radius = other.radius;
Node::operator=(other);
}
return *this;
}
Light::~Light()
{
}
// Рисование отладочных лампочек
void Light::render(ShaderProgram &shaderProgram, UBO &material_buffer)
{
// Загрузка модели лампочки при первом вызове функции
static Scene bulb = loadOBJtoScene("../resources/models/bulb.obj", "../resources/models/", "../resources/textures/");
static Model sphere = genShpere(1, 16, &bulb.root);
// Цикл по источникам света
for (int i = 0; i < count; i++)
{
// Сдвиг на позицию источника
bulb.root.e_position() = data[i].position;
sphere.e_scale() = glm::vec3(data[i].attenuation.r); // Масштабирование сферы
// Задание цвета
bulb.models.begin()->material.ka = sphere.material.ka = data[i].color;
// Вызов отрисовки
bulb.render(shaderProgram, material_buffer);
// Рисование сферы покрытия источника в режиме линий
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
sphere.render(shaderProgram, material_buffer);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
// Константный доступ к радиусу
const float& Light::c_radius() const
{
return radius;
}
// Неконстантная ссылка для изменений радиуса
float& Light::e_radius()
{
uploadReq = true;
return radius;
} }

View File

@ -402,3 +402,77 @@ void Model::set_texture(Texture& texture)
break; break;
}; };
} }
// Генерирует сферу заданного радиуса с определенным количеством сегментов
Model genShpere(float radius, int sectorsCount, Node* parent)
{
Model result(parent);
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<GLuint> indices;
float x, y, z, xy; // Позиция вершины
float nx, ny, nz, lengthInv = 1.0f / radius; // Нормаль вершины
float PI = 3.14159265;
float sectorStep = PI / sectorsCount; // Шаг сектора
float longAngle, latAngle; // Углы
for(int i = 0; i <= sectorsCount; ++i)
{
latAngle = PI / 2 - i * sectorStep; // Начиная с pi/2 до -pi/2
xy = radius * cos(latAngle); // r * cos(lat)
z = radius * sin(latAngle); // r * sin(lat)
// добавляем (sectorCount+1) вершин на сегмент
// Последняя и первая вершины имеют одинаковые нормали и координаты
for(int j = 0; j <= sectorsCount; ++j)
{
longAngle = j * 2 * sectorStep; // Начиная с 0 до 2*pi
// Положение вершины (x, y, z)
x = xy * cos(longAngle); // r * cos(lat) * cos(long)
y = xy * sin(longAngle); // r * cos(lat) * sin(long)
vertices.push_back({x, y, z});
// Нормали (nx, ny, nz)
nx = x * lengthInv;
ny = y * lengthInv;
nz = z * lengthInv;
normals.push_back({nx, ny, nz});
}
}
int k1, k2;
for(int i = 0; i < sectorsCount; ++i)
{
k1 = i * (sectorsCount + 1); // начало текущего сегмента
k2 = k1 + sectorsCount + 1; // начало следующего сегмента
for(int j = 0; j < sectorsCount; ++j, ++k1, ++k2)
{
// 2 треугольника на один сегмент
// k1, k2, k1+1
if(i != 0)
{
indices.push_back(k1);
indices.push_back(k2);
indices.push_back(k1 + 1);
}
// k1+1, k2, k2+1
if(i != (sectorsCount-1))
{
indices.push_back(k1 + 1);
indices.push_back(k2);
indices.push_back(k2 + 1);
}
}
}
// Загрузка в модель
result.load_verteces(&vertices[0], vertices.size());
result.load_normals(&normals[0], normals.size());
result.load_indices(&indices[0], indices.size());
return result;
}

View File

@ -115,6 +115,13 @@ Texture::~Texture()
} }
} }
// Пересоздает текстуру для имеющегося дескриптора
void Texture::reallocate(GLuint width, GLuint height, GLuint texType, GLint internalformat, GLint format, GLenum dataType)
{
use();
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, dataType, NULL);
}
// Привязка текстуры // Привязка текстуры
void Texture::use() void Texture::use()
{ {

View File

@ -9,14 +9,42 @@
#include "Shader.h" #include "Shader.h"
#include "Lights.h" #include "Lights.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_CAPTION "OPENGL notes on rekovalev.site" #define WINDOW_CAPTION "OPENGL notes on rekovalev.site"
// Указатели на текстуры для изменения размеров окна
Texture* pgPosition = NULL;
Texture* pgNormal = NULL;
Texture* pgDiffuseP = NULL;
Texture* pgAmbientSpecular = NULL;
RBO* pgrbo = NULL;
// Размеры окна
int WINDOW_WIDTH = 800;
int WINDOW_HEIGHT = 600;
// Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна // Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна
void framebuffer_size_callback(GLFWwindow* window, int width, int height) void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{ {
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
// Изменение размеров текстур для G-буфера
if (pgPosition)
pgPosition->reallocate(width, height, 0, GL_RGB32F, GL_RGB);
if (pgNormal)
pgNormal->reallocate(width, height, 1, GL_RGB16F, GL_RGB);
if (pgDiffuseP)
pgDiffuseP->reallocate(width, height, 2, GL_RGBA16F);
if (pgAmbientSpecular)
pgAmbientSpecular->reallocate(width, height, 3);
// И буфера глубины
if (pgrbo)
pgrbo->reallocate(width, height);
// Запомним новые размеры окна
WINDOW_WIDTH = width;
WINDOW_HEIGHT = height;
// Изменим параметры перспективной матрицы проекции для камеры
Camera::current().setPerspective(CAMERA_FOVy, (float)width/height);
} }
bool firstMouse = true; bool firstMouse = true;
@ -94,7 +122,6 @@ int main(void)
const char* textures_base_shader_names[] = {"tex_diffuse", "tex_ambient", "tex_specular"}; const char* textures_base_shader_names[] = {"tex_diffuse", "tex_ambient", "tex_specular"};
gShader.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*)); gShader.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*));
// Загрузка сцены из obj файла // Загрузка сцены из obj файла
Scene scene = loadOBJtoScene("../resources/models/blob.obj", "../resources/models/", "../resources/textures/"); Scene scene = loadOBJtoScene("../resources/models/blob.obj", "../resources/models/", "../resources/textures/");
scene.root.e_scale() = glm::vec3(0.01); scene.root.e_scale() = glm::vec3(0.01);
@ -106,14 +133,12 @@ int main(void)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Источники света // Источники света
// Первый способ измений Light& first = Light::getNew();
Light::data[0] = { {0.3f, 0.1f, 0.5f} // позиция first.e_color() = {1.0f, 0.0f, 0.0f}; // цвет
, {1.0f, 0.0f, 0.0f} // цвет first.e_position() = {0.3f, 0.1f, 0.5f}; // Позиция
}; Light& second = Light::getNew();
Light::count++; second.e_color() = {0.0f, 0.0f, 1.0f}; // цвет
// Второй способ second.e_position() = {-0.3f, -0.1f, 0.5f}; // Позиция
Light::data[Light::count].position = {-0.3f, -0.1f, 0.5f}; // позиция
Light::data[Light::count++].color = { 0.0f, 0.0f, 1.0f}; // цвет
// Uniform-буферы // Uniform-буферы
UBO cameraUB(sizeof(CameraData), 0); UBO cameraUB(sizeof(CameraData), 0);
@ -126,7 +151,7 @@ int main(void)
GLuint attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; GLuint attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
FBO gbuffer(attachments, sizeof(attachments) / sizeof(GLuint)); FBO gbuffer(attachments, sizeof(attachments) / sizeof(GLuint));
// Создадим текстуры для буфера кадра // Создадим текстуры для буфера кадра
Texture gPosition(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT0, 0, GL_RGB16F, GL_RGB); // Позиция вершины Texture gPosition(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT0, 0, GL_RGB32F, GL_RGB); // Позиция вершины
Texture gNormal(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT1, 1, GL_RGB16F, GL_RGB); // Нормали Texture gNormal(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT1, 1, GL_RGB16F, GL_RGB); // Нормали
Texture gDiffuseP(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT2, 2, GL_RGBA16F); // Диффузная составляющая и коэф. глянцевости Texture gDiffuseP(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT2, 2, GL_RGBA16F); // Диффузная составляющая и коэф. глянцевости
Texture gAmbientSpecular(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT3, 3); // Фоновая составляющая и один канал зеркальной Texture gAmbientSpecular(WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_ATTACHMENT3, 3); // Фоновая составляющая и один канал зеркальной
@ -136,6 +161,13 @@ int main(void)
// Активируем базовый буфер кадра // Активируем базовый буфер кадра
FBO::useDefault(); FBO::useDefault();
// Сохраним указатели на текстуры для изменения размеров окна
pgPosition = &gPosition;
pgNormal = &gNormal;
pgDiffuseP = &gDiffuseP;
pgAmbientSpecular = &gAmbientSpecular;
pgrbo = &grbo;
// Шейдер для расчета освещенности // Шейдер для расчета освещенности
ShaderProgram lightShader; ShaderProgram lightShader;
// Загрузка и компиляция шейдеров // Загрузка и компиляция шейдеров
@ -157,6 +189,13 @@ int main(void)
quadModel.load_verteces(quadVertices, 4); quadModel.load_verteces(quadVertices, 4);
quadModel.load_indices(quadIndices, 6); quadModel.load_indices(quadIndices, 6);
// Шейдер для рисования отладочных лампочек
ShaderProgram bulbShader;
// Загрузка и компиляция шейдеров
bulbShader.load(GL_VERTEX_SHADER, "shaders/bulb.vert");
bulbShader.load(GL_FRAGMENT_SHADER, "shaders/bulb.frag");
bulbShader.link();
// Пока не произойдет событие запроса закрытия окна // Пока не произойдет событие запроса закрытия окна
while(!glfwWindowShouldClose(window)) while(!glfwWindowShouldClose(window))
{ {
@ -189,6 +228,17 @@ int main(void)
// Рендерим прямоугольник с расчетом освещения // Рендерим прямоугольник с расчетом освещения
quadModel.render(); quadModel.render();
// Перенос буфера глубины
FBO::useDefault(GL_DRAW_FRAMEBUFFER); // Базовый в режиме записи
gbuffer.use(GL_READ_FRAMEBUFFER); // Буфер геометрии в режиме чтения
// Копирование значений глубины
glBlitFramebuffer(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
FBO::useDefault(); // Использование базового буфера для дальнейших работ
// Отрисовка отладочных лампочек со специальным шейдером
bulbShader.use();
Light::render(bulbShader, material_data);
// Представление содержимого буфера цепочки показа на окно // Представление содержимого буфера цепочки показа на окно
glfwSwapBuffers(window); glfwSwapBuffers(window);
// Обработка системных событий // Обработка системных событий