From 86de8dc1021dd7f11a7ade71b9e8c91a6cc087fb Mon Sep 17 00:00:00 2001 From: "re.kovalev" Date: Tue, 31 Oct 2023 11:04:04 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=B0=D1=82=D1=80=D0=B8=D1=86=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=B8=D0=B4=D0=B0-=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BD=D0=B0=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B8=D1=81=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Lights.h | 3 +++ src/Lights.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/Lights.h b/include/Lights.h index 569ef9d..3affac5 100644 --- a/include/Lights.h +++ b/include/Lights.h @@ -81,7 +81,10 @@ class Sun alignas(16) glm::vec3 direction; // Направление лучей источника alignas(16) glm::vec3 color; // Цвет + alignas(16) glm::mat4 vp; // Матрица вида-проекции источника + void recalcVP(); // Пересчитывает по необходимости матрицу вида-проекции + static Sun instance; // Экземпляр синглтона static bool uploadReq; // Необходимость загрузки в следствии изменений }; diff --git a/src/Lights.cpp b/src/Lights.cpp index 2a15b30..278a8cd 100644 --- a/src/Lights.cpp +++ b/src/Lights.cpp @@ -264,6 +264,8 @@ Sun& Sun::get() // Загрузка данных об источнике на шейдер void Sun::upload(UBO& sun_data) { + instance.recalcVP(); // Пересчет матрицы вида-проекции источника по необходимости (влияет на флаг uploadReq) + if (uploadReq) { sun_data.loadSub(&instance, sizeof(instance)); @@ -299,3 +301,42 @@ glm::vec3& Sun::e_color() return instance.color; } + +// Пересчитывает по необходимости матрицу вида-проекции +void Sun::recalcVP() +{ + std::pair camProjCoords = Camera::current().getProjCoords(); + + // Есть изменения по источнику или камере + if (uploadReq || camProjCoords.first) + { + uploadReq = true; // Требуется загрузка в следствии пересчета матрицы + + glm::vec3 mean = glm::vec3(0); // Среднее арифметическое + 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++) + { + // Приведем в пространство вида источника + point = lightView * camProjCoords.second[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; + } +}