diff --git a/include/Lights.h b/include/Lights.h index 48d4355..926a7df 100644 --- a/include/Lights.h +++ b/include/Lights.h @@ -13,13 +13,15 @@ class Bulb { public: - Bulb(const glm::vec3 &pos = glm::vec3(0.0f, 0.0f, 0.0f), const glm::vec3 &color = glm::vec3(0.0f, 0.0f, 0.0f), float radius = 10.0f); // Конструктор с координатами, цветом и радиусом + Bulb(const glm::vec3 &pos = glm::vec3(0.0f, 0.0f, 0.0f), const glm::vec3 &color = glm::vec3(0.0f, 0.0f, 0.0f), float radius = 10.0f, float angle = 180, const glm::vec3 &direction = glm::vec3(0,0,1)); // Конструктор с координатами, цветом, радиусом и направлением void render(ShaderProgram &shaderProgram, UBO &material_buffer); // Отрисовка отладочной лампы и сферы alignas(16) glm::vec3 position; // Позиция alignas(16) glm::vec3 color; // Цвет void setRadius(float radius); // Задание радиуса и расчет коэф. угасания + float angle; // Угол освещенности + alignas(16) glm::vec3 direction; // Направление для прожектора private: float radius; // Радиус действия источника glm::vec2 K; // линейный и квадратичный компоненты затухания 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 5d26362..05ca466 100644 --- a/shaders/lighting.frag +++ b/shaders/lighting.frag @@ -13,6 +13,8 @@ struct LightData { vec3 position; vec3 color; + float angle; + vec3 direction; float radius; vec2 K; }; @@ -50,6 +52,7 @@ void main() vec3 H; // Вектор половины пути float specular; // Зеркальная составляющая float attenuation; // Угасание с учетом расстояния + float acosA; // Косинус между вектором от поверхности к источнику и обратным направлением источника // Фоновая освещенность @@ -69,20 +72,25 @@ void main() { // Нормирование вектора L_vertex = normalize(L_vertex); + // арккосинус между вектором от поверхности к источнику и обратным направлением источника + acosA = degrees(acos(dot(-L_vertex, normalize(light_f.data[i].direction)))); + // Если угол меньше угла источника или угол источника минимален, то считаем освещенность + if(acosA <= light_f.data[i].angle) + { + // Диффузная составляющая + 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].K[0] * L_distance + light_f.data[i].K[1] * L_distance * L_distance); - // Угасание с учетом расстояния - attenuation = 1 / (1 + light_f.data[i].K[0] * L_distance + light_f.data[i].K[1] * 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 d39076a..824e101 100644 --- a/src/Lights.cpp +++ b/src/Lights.cpp @@ -6,7 +6,7 @@ void genShpere(Model& model, float radius, int sectorsCount); // Model.cpp GrouptedModel Bulb::bulb_model; // Конструктор с координатами, цветом и радиусом -Bulb::Bulb(const glm::vec3 &pos, const glm::vec3 &c, float r) +Bulb::Bulb(const glm::vec3 &pos, const glm::vec3 &c, float r, float a, const glm::vec3 &dir) { // Если отладочная модель не загружена - загрузим if (!bulb_model.parts.size()) @@ -25,21 +25,37 @@ Bulb::Bulb(const glm::vec3 &pos, const glm::vec3 &c, float r) radius = r; K[0] = 4.5/radius; K[1] = 4 * K[0] * K[0]; + angle = a; + direction = dir; } // Отрисовка отладочной лампы и сферы void Bulb::render(ShaderProgram &shaderProgram, UBO &material_buffer) { + // Расположение uniform-переменных + GLuint model_uniform = shaderProgram.getUniformLoc("model"); + GLuint angle_uniform = shaderProgram.getUniformLoc("angle"); + GLuint direction_uniform = shaderProgram.getUniformLoc("direction"); + + // Загрузим направление + glUniform3fv(direction_uniform, 1, &direction[0]); + // Зададим параметры материала сфере действия bulb_model.parts[0].material.ka = color; bulb_model.parts[0].position = position; bulb_model.parts[0].scale = {radius, radius, radius}; + // Угол для сферы (рисуем направленный конус) + glUniform1f(angle_uniform, angle); + // Рисование сферы покрытия источника в режиме линий glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); bulb_model.parts[0].render(shaderProgram, material_buffer); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // Угол для лампочки = 180 (рисуем целую модель) + glUniform1f(angle_uniform, 180); // Зададим параметры материала сфере действия + // Зададим цвет для колбы (первая в составе модели) bulb_model.parts[1].material.ka = color; diff --git a/src/main.cpp b/src/main.cpp index fdd5b39..907652f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -121,7 +121,8 @@ int main(void) GLint lights_count = 0; lights[lights_count].position = {0.3f, 0.1f, 0.5f}; // позиция - lights[lights_count++].color = {1.0f, 0.0f, 0.0f}; // цвет + lights[lights_count].color = {1.0f, 0.0f, 0.0f}; // цвет + lights[lights_count++].angle = 35; lights[lights_count].position = {-0.3f, -0.1f, 0.5f}; // позиция lights[lights_count++].color = {0.0f, 0.0f, 1.0f}; // цвет