diff --git a/include/Camera.h b/include/Camera.h index 859ae39..2af7602 100644 --- a/include/Camera.h +++ b/include/Camera.h @@ -11,7 +11,7 @@ // Ближняя граница области отсечения #define CAMERA_NEAR 0.1f // Дальняя граница области отсечения -#define CAMERA_FAR 15.0f +#define CAMERA_FAR 100.0f // Вектор, задающий верх для камеры #define CAMERA_UP_VECTOR glm::vec3(0.0f, 1.0f, 0.0f) // Вектор, задающий стандартный поворот углами Эйлера (в положительном направлении оси Z) @@ -20,6 +20,11 @@ #define CAMERA_FOVy 60.0f // Стандартная чувствительность #define CAMERA_DEFAULT_SENSIVITY 0.005f +// Количество каскадов для карт теней +#define CAMERA_CASCADE_COUNT 4 + +// Данные о дистанциях каскадов +extern const float camera_cascade_distances[]; // src/Camera.cpp // Данные о камере для шейдера struct CameraData @@ -54,7 +59,7 @@ class Camera : public Node static Camera& current(); // Ссылка на текущую используемую камеру CameraData& getData(); // Данные о камере для шейдера - std::pair getProjCoords(); // Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется + std::pair getProjCoords(); // Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется protected: Camera(const glm::vec3 &position, const glm::vec3 &initialRotation); // Защищенный (protected) конструктор камеры без перспективы @@ -63,7 +68,8 @@ class Camera : public Node glm::mat4 vp; // Матрица произведения вида и проекции bool requiredRecalcVP; // Необходимость пересчета матрицы вида и проекции камеры bool requiredRecalcCoords; // Необходимость пересчета точек, описывающих пространство камеры - glm::vec4 coords[8]; // Координаты, описывающие пространство камеры + glm::vec4 coords[CAMERA_CASCADE_COUNT][8]; // Координаты, описывающие пространство камеры + glm::mat4 cascade_proj[CAMERA_CASCADE_COUNT]; // Матрицы проекций каскадов float sensitivity; // Чувствительность мыши diff --git a/src/Camera.cpp b/src/Camera.cpp index 2b77842..b2434bd 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -3,6 +3,9 @@ // Указатель на текущую используемую камеру Camera* Camera::p_current = NULL; +// Границы каскадов +const float camera_cascade_distances[] = {CAMERA_NEAR, CAMERA_FAR / 50.0f, CAMERA_FAR / 10.0f, CAMERA_FAR / 3.0f, CAMERA_FAR}; + // Защищенный (protected) конструктор камеры без перспективы Camera::Camera(const glm::vec3 &pos, const glm::vec3 &initialRotation) : Node(NULL) // Пусть по умолчанию камера не относится к сцене { @@ -33,7 +36,8 @@ Camera::Camera(float width, float height, const glm::vec3 &position, const glm:: // Конструктор копирования камеры Camera::Camera(const Camera& copy) -: Node(copy), projection(copy.projection), requiredRecalcVP(copy.requiredRecalcVP), sensitivity(copy.sensitivity) +: Node(copy), projection(copy.projection), requiredRecalcVP(copy.requiredRecalcVP), sensitivity(copy.sensitivity), +requiredRecalcCoords(true) { // Если у оригинала не было изменений - перепишем матрицу вида-проекции if (!requiredRecalcVP) @@ -90,6 +94,8 @@ void Camera::setPerspective(float fovy, float aspect) { projection = glm::perspective(glm::radians(fovy), aspect, CAMERA_NEAR, CAMERA_FAR); requiredRecalcVP = true; + for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++) + cascade_proj[cascade] = glm::perspective(glm::radians(fovy), aspect, camera_cascade_distances[cascade], camera_cascade_distances[cascade+1]); } // Устанавливает заданную ортографическую матрицу @@ -98,6 +104,9 @@ void Camera::setOrtho(float width, float height) const float aspect = width / height; projection = glm::ortho(-1.0f, 1.0f, -1.0f/aspect, 1.0f/aspect, CAMERA_NEAR, CAMERA_FAR); requiredRecalcVP = true; + for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++) + cascade_proj[cascade] = glm::ortho(-1.0f, 1.0f, -1.0f/aspect, 1.0f/aspect, camera_cascade_distances[cascade], camera_cascade_distances[cascade+1]); + } // Изменяет чувствительность мыши @@ -192,7 +201,7 @@ CameraData& Camera::getData() } // Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется -std::pair Camera::getProjCoords() +std::pair Camera::getProjCoords() { const glm::mat4& cam_vp = getVP(); // Получение ссылки на матрицу вида-проекции с пересчетом, если требуется и активацией флага requiredRecalcCoords bool changes = false; // Возвращаемое значение @@ -210,11 +219,16 @@ std::pair Camera::getProjCoords() , {-1, 1,-1,1} , {-1,-1, 1,1} , {-1,-1,-1,1}}; - // Цикл по типовым точкам - for (int i = 0; i < 8; i++) + + for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++) { - coords[i] = inv * typical_points[i]; - coords[i] /= coords[i].w; // Переход от гомогенных координат к обычным + glm::mat4 inv = glm::inverse(cascade_proj[cascade] * getView()); + // Цикл по типовым точкам + for (int i = 0; i < 8; i++) + { + coords[cascade][i] = inv * typical_points[i]; + coords[cascade][i] /= coords[cascade][i].w; + } } requiredRecalcCoords = false; // Сбрасываем флаг