From 1a74ce4d41e47f152c3440a762c155dbad4532ef Mon Sep 17 00:00:00 2001 From: "re.kovalev" Date: Tue, 20 Dec 2022 15:58:42 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=83=D0=B3=D0=BB=D0=B0=20=D0=B8=20?= =?UTF-8?q?=D1=80=D0=B8=D1=81=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B8=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D0=BE=D0=B9=20=D1=81=D1=84=D0=B5=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Lights.h | 7 +++++++ shaders/bulb.frag | 11 ++++++++++- shaders/bulb.vert | 3 +++ shaders/lighting.frag | 32 ++++++++++++++++++++------------ src/Lights.cpp | 32 +++++++++++++++++++++++++++++++- src/main.cpp | 1 + 6 files changed, 72 insertions(+), 14 deletions(-) diff --git a/include/Lights.h b/include/Lights.h index ffe2423..04caa92 100644 --- a/include/Lights.h +++ b/include/Lights.h @@ -7,6 +7,8 @@ // Максимальное число источников света #define MAX_LIGHTS 300 +// Стандартное направление источника без поворота +#define DEFAULT_LIGHT_DIRECTION glm::vec4(0.0f, 0.0f, 1.0f, 0.0f) // Точечный источник света struct LightData @@ -14,6 +16,7 @@ struct LightData alignas(16) glm::vec3 position; // Позиция alignas(16) glm::vec3 color; // Цвет alignas(16) glm::vec3 attenuation; // Радиус действия источника, линейный и квадратичный коэф. угасания + alignas(16) glm::vec4 direction_angle; // Направление и половинный угол освещенности }; // Источник света @@ -32,6 +35,9 @@ class Light : public Node const float& c_radius() const; // Константный доступ к радиусу float& e_radius(); // Неконстантная ссылка для изменений радиуса + const float& c_angle() const; // Константный доступ к углу освещенности + float& e_angle(); // Неконстантная ссылка для изменений угла освещенности + static void render(ShaderProgram &shaderProgram, UBO &material_buffer); // Рисование отладочных лампочек private: Light(); // Конструктор без параметров @@ -41,6 +47,7 @@ class Light : public Node glm::vec3 color; // Цвет float radius; // Радиус действия источника + float angle; // Угол полный освещенности int index; // Индекс в массиве отправки (может не совпадать с lights) для дефрагментированного доступа static Light& findByIndex(GLuint index); // Возвращает ссылку на источник с нужным индексом diff --git a/shaders/bulb.frag b/shaders/bulb.frag index 9329edf..d6aaf90 100644 --- a/shaders/bulb.frag +++ b/shaders/bulb.frag @@ -8,9 +8,18 @@ layout(std140, binding = 1) uniform Material float p; }; +in vec3 pos_local; + out vec4 color; +uniform float angle; +uniform vec3 direction; + void main() { - color = vec4(ka, 1); + float cosA = dot(normalize(pos_local), normalize(direction)); + if (degrees(acos(cosA)) <= angle) + color = vec4(ka, 1); + else + discard; } \ No newline at end of file diff --git a/shaders/bulb.vert b/shaders/bulb.vert index 7ce8b0b..e84ca7e 100644 --- a/shaders/bulb.vert +++ b/shaders/bulb.vert @@ -11,7 +11,10 @@ layout(std140, binding = 0) uniform Camera uniform mat4 model; +out vec3 pos_local; + void main() { + pos_local = pos; gl_Position = camera.projection * camera.view * model * vec4(pos, 1.0); } \ No newline at end of file diff --git a/shaders/lighting.frag b/shaders/lighting.frag index 88b259d..01f9a7b 100644 --- a/shaders/lighting.frag +++ b/shaders/lighting.frag @@ -14,6 +14,7 @@ struct LightData vec3 position; vec3 color; vec3 attenuation; + vec4 direction_angle; }; layout(std140, binding = 2) uniform Light @@ -47,6 +48,8 @@ void main() float specular; // Зеркальная составляющая float L_distance; // Расстояние от поверхности до источника float attenuation; // Коэф. угасания + float acosA; // Косинус между вектором от поверхности к источнику и обратным направлением источника + // Фоновая освещенность color = vec4(ka, 1); @@ -66,20 +69,25 @@ void main() { // Нормирование вектора 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 - // Диффузная составляющая - 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); - // Угасание с учетом расстояния - 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); + color += vec4(light_f.data[i].color*kd*diffuse * attenuation, 1) + + vec4(light_f.data[i].color*ks*specular * attenuation, 1); + } } } } \ No newline at end of file diff --git a/src/Lights.cpp b/src/Lights.cpp index 4852fcf..7e7aa2f 100644 --- a/src/Lights.cpp +++ b/src/Lights.cpp @@ -104,6 +104,10 @@ void Light::toData() data[index].attenuation[1] = 4.5/radius; // Линейный коэф. угасания data[index].attenuation[2] = 4 * data[index].attenuation[1] * data[index].attenuation[1]; // Квадратичный коэф. угасания } + // Направление и угол источника + data[index].direction_angle = glm::vec4( glm::normalize(glm::vec3(result_transform * DEFAULT_LIGHT_DIRECTION)) + , angle / 2 // Половинный угол для вычислений на шейдере + ); } // Возвращает ссылку на новый источник света @@ -150,7 +154,7 @@ Light& Light::findByIndex(GLuint index) } // Конструктор без параметров -Light::Light() : Node(), index(-1), uploadReq(false), color(1.0f), radius(10.0f) +Light::Light() : Node(), index(-1), uploadReq(false), color(1.0f), radius(10.0f), angle(360.0f) { } @@ -165,6 +169,7 @@ Light& Light::operator=(const Light& other) uploadReq = other.uploadReq; // Необходимость загрузки color = other.color; radius = other.radius; + angle = other.angle; Node::operator=(other); } @@ -183,9 +188,17 @@ 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); + GLuint angle_uniform = shaderProgram.getUniformLoc("angle"); + GLuint direction_uniform = shaderProgram.getUniformLoc("direction"); + // Цикл по источникам света for (int i = 0; i < count; i++) { + // Загрузим направление + glUniform3fv(direction_uniform, 1, &data[i].direction_angle.x); + // Угол для лампочки = 180 (рисуем целую модель) + glUniform1f(angle_uniform, 180); // Зададим параметры материала сфере действия + // Сдвиг на позицию источника bulb.root.e_position() = data[i].position; sphere.e_scale() = glm::vec3(data[i].attenuation.r); // Масштабирование сферы @@ -195,6 +208,9 @@ void Light::render(ShaderProgram &shaderProgram, UBO &material_buffer) // Вызов отрисовки bulb.render(shaderProgram, material_buffer); + // Угол для сферы (рисуем направленный конус) + glUniform1f(angle_uniform, data[i].direction_angle.a); + // Рисование сферы покрытия источника в режиме линий glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); sphere.render(shaderProgram, material_buffer); @@ -215,3 +231,17 @@ float& Light::e_radius() return radius; } + +// Константный доступ к углу освещенности +const float& Light::c_angle() const +{ + return angle; +} + +// Неконстантная ссылка для изменений угла освещенности +float& Light::e_angle() +{ + uploadReq = true; + + return angle; +} diff --git a/src/main.cpp b/src/main.cpp index 71a05fc..2579500 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -136,6 +136,7 @@ int main(void) Light& first = Light::getNew(); first.e_color() = {1.0f, 0.0f, 0.0f}; // цвет first.e_position() = {0.3f, 0.1f, 0.5f}; // Позиция + first.e_angle() = 70.0f; Light& second = Light::getNew(); second.e_color() = {0.0f, 0.0f, 1.0f}; // цвет second.e_position() = {-0.3f, -0.1f, 0.5f}; // Позиция