diff --git a/include/Lights.h b/include/Lights.h index 3affac5..5c0b1e8 100644 --- a/include/Lights.h +++ b/include/Lights.h @@ -4,6 +4,7 @@ #include #include "Model.h" +#include "Camera.h" // Максимальное число источников света #define MAX_LIGHTS 300 @@ -81,7 +82,7 @@ class Sun alignas(16) glm::vec3 direction; // Направление лучей источника alignas(16) glm::vec3 color; // Цвет - alignas(16) glm::mat4 vp; // Матрица вида-проекции источника + alignas(16) glm::mat4 vp[CAMERA_CASCADE_COUNT]; // Матрица вида-проекции источника void recalcVP(); // Пересчитывает по необходимости матрицу вида-проекции diff --git a/src/Lights.cpp b/src/Lights.cpp index 278a8cd..877ced4 100644 --- a/src/Lights.cpp +++ b/src/Lights.cpp @@ -305,38 +305,44 @@ glm::vec3& Sun::e_color() // Пересчитывает по необходимости матрицу вида-проекции void Sun::recalcVP() { - std::pair camProjCoords = Camera::current().getProjCoords(); + // Точки по краям проекции камеры + std::pair camProjCoords = Camera::current().getProjCoords(); // Есть изменения по источнику или камере if (uploadReq || camProjCoords.first) { uploadReq = true; // Требуется загрузка в следствии пересчета матрицы - glm::vec3 mean = glm::vec3(0); // Среднее арифметическое + glm::vec3 mean; // Среднее арифметическое glm::vec4 max, min; // макс и мин координаты glm::vec4 point; // Точка приведенная в пространство источника света - // Найдем среднее арифметическое от точек для нахождения центра прямоугольника - for (int i = 0; i < 8; i++) - mean += glm::vec3(camProjCoords.second[i]); - mean /= 8; - // Используем среднее арифметическое для получения матрицы вида параллельного источника - glm::mat4 lightView = glm::lookAt(mean + glm::normalize(direction), mean, CAMERA_UP_VECTOR); - - // Примем первую точку как минимальную и максимальную (приведя в пространство вида источника) - min = max = lightView * camProjCoords.second[0]; - // Для оставшихся точек - for (int i = 1; i < 8; i++) + + for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++) { - // Приведем в пространство вида источника - point = lightView * camProjCoords.second[i]; - max = glm::max(max, point); - min = glm::min(min, point); - } + mean = glm::vec3(0); + // Найдем среднее арифметическое от точек для нахождения центра прямоугольника + for (int i = 0; i < 8; i++) + mean += glm::vec3(camProjCoords.second[cascade][i]); + mean /= 8; + // Используем среднее арифметическое для получения матрицы вида параллельного источника + glm::mat4 lightView = glm::lookAt(mean + glm::normalize(direction), mean, CAMERA_UP_VECTOR); + + // Примем первую точку как минимальную и максимальную (приведя в пространство вида источника) + min = max = lightView * camProjCoords.second[cascade][0]; + // Для оставшихся точек + for (int i = 1; i < 8; i++) + { + // Приведем в пространство вида источника + point = lightView * camProjCoords.second[cascade][i]; + max = glm::max(max, point); + min = glm::min(min, point); + } - // Максимальное значение глубины - max.z = std::max(fabs(max.z), fabs(min.z)); - // На основании максимальных и минимальных координат создадим матрицу проекции источника - vp = glm::ortho(min.x, max.x, min.y, max.y, min.z, max.z) * lightView; + // Максимальное значение глубины + max.z = std::max(fabs(max.z), fabs(min.z)); + // На основании максимальных и минимальных координат создадим матрицу проекции источника + vp[cascade] = glm::ortho(min.x, max.x, min.y, max.y, min.z, max.z) * lightView; + } } }