Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
|
@ -11,7 +11,7 @@
|
|||
// Ближняя граница области отсечения
|
||||
#define CAMERA_NEAR 0.1f
|
||||
// Дальняя граница области отсечения
|
||||
#define CAMERA_FAR 100.0f
|
||||
#define CAMERA_FAR 15.0f
|
||||
// Вектор, задающий верх для камеры
|
||||
#define CAMERA_UP_VECTOR glm::vec3(0.0f, 1.0f, 0.0f)
|
||||
// Вектор, задающий стандартный поворот углами Эйлера (в положительном направлении оси Z)
|
||||
|
@ -20,11 +20,6 @@
|
|||
#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
|
||||
|
@ -59,7 +54,7 @@ class Camera : public Node
|
|||
static Camera& current(); // Ссылка на текущую используемую камеру
|
||||
|
||||
CameraData& getData(); // Данные о камере для шейдера
|
||||
std::pair<bool, const glm::vec4(*)[8]> getProjCoords(); // Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется
|
||||
std::pair<bool, const glm::vec4*> getProjCoords(); // Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется
|
||||
protected:
|
||||
Camera(const glm::vec3 &position, const glm::vec3 &initialRotation); // Защищенный (protected) конструктор камеры без перспективы
|
||||
|
||||
|
@ -68,8 +63,7 @@ class Camera : public Node
|
|||
glm::mat4 vp; // Матрица произведения вида и проекции
|
||||
bool requiredRecalcVP; // Необходимость пересчета матрицы вида и проекции камеры
|
||||
bool requiredRecalcCoords; // Необходимость пересчета точек, описывающих пространство камеры
|
||||
glm::vec4 coords[CAMERA_CASCADE_COUNT][8]; // Координаты, описывающие пространство камеры
|
||||
glm::mat4 cascade_proj[CAMERA_CASCADE_COUNT]; // Матрицы проекций каскадов
|
||||
glm::vec4 coords[8]; // Координаты, описывающие пространство камеры
|
||||
|
||||
float sensitivity; // Чувствительность мыши
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <GLM/glm.hpp>
|
||||
|
||||
#include "Model.h"
|
||||
#include "Camera.h"
|
||||
|
||||
// Максимальное число источников света
|
||||
#define MAX_LIGHTS 300
|
||||
|
@ -82,7 +81,7 @@ class Sun
|
|||
|
||||
alignas(16) glm::vec3 direction; // Направление лучей источника
|
||||
alignas(16) glm::vec3 color; // Цвет
|
||||
alignas(16) glm::mat4 vp[CAMERA_CASCADE_COUNT]; // Матрица вида-проекции источника
|
||||
alignas(16) glm::mat4 vp; // Матрица вида-проекции источника
|
||||
|
||||
void recalcVP(); // Пересчитывает по необходимости матрицу вида-проекции
|
||||
|
||||
|
|
|
@ -44,18 +44,4 @@ class Texture : public BaseTexture
|
|||
virtual void use(); // Привязка текстуры
|
||||
};
|
||||
|
||||
// Класс 3D текстуры
|
||||
class TextureArray : public BaseTexture
|
||||
{
|
||||
public:
|
||||
TextureArray(GLuint levels, GLuint width, GLuint height, GLuint attachment, GLuint texType = TEX_DIFFUSE, GLint internalformat = GL_RGBA, GLint format = GL_RGBA, GLenum dataType = GL_FLOAT); // Конструктор текстуры заданного размера для использования в буфере
|
||||
TextureArray(const TextureArray& other); // Конструктор копирования
|
||||
|
||||
TextureArray& operator=(const TextureArray& other); // Оператор присваивания
|
||||
|
||||
void reallocate(GLuint levels, GLuint width, GLuint height, GLuint texType = TEX_DIFFUSE, GLint internalformat = GL_RGBA, GLint format = GL_RGBA, GLenum dataType = GL_FLOAT); // Пересоздает текстуру для имеющегося дескриптора
|
||||
|
||||
virtual void use(); // Привязка текстуры
|
||||
};
|
||||
|
||||
#endif // TEXTURE_H
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#version 330 core
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
}
|
|
@ -27,16 +27,14 @@ layout(std140, binding = 3) uniform Sun
|
|||
{
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
mat4 vp[4];
|
||||
mat4 vp;
|
||||
} sun;
|
||||
|
||||
uniform float camera_cascade_distances[4]; // Размер массива должен соответствовать количеству каскадов
|
||||
|
||||
uniform sampler2D gPosition;
|
||||
uniform sampler2D gNormal;
|
||||
uniform sampler2D gDiffuseP;
|
||||
uniform sampler2D gAmbientSpecular;
|
||||
uniform sampler2DArray sunShadowDepth;
|
||||
uniform sampler2D sunShadowDepth;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
|
@ -62,18 +60,10 @@ void main()
|
|||
float intensity; // Интенсивность для прожектора
|
||||
vec3 fragPosLightSpace; // Фрагмент в пространстве источника
|
||||
float shadowValue; // Значение затененности
|
||||
vec2 texelSize = 1.0 / textureSize(sunShadowDepth, 0).xy; // Размер текселя текстуры теней
|
||||
vec2 texelSize = 1.0 / textureSize(sunShadowDepth, 0); // Размер текселя текстуры теней
|
||||
int x, y; // Счетчик для PCF
|
||||
float pcfDepth; // Глубина PCF
|
||||
|
||||
vec4 fragPosCamSpace = camera.view * vec4(fragPos, 1); // Фрагмент в пространстве камеры
|
||||
int cascade_index; // Индекс текущего каскада для вычисления теней
|
||||
|
||||
// Определение индекса каскада в который попадает фрагмент (цикл на 1 меньше чем кол-во каскадов)
|
||||
for (cascade_index = 0; cascade_index < 3; cascade_index++)
|
||||
if (abs(fragPosCamSpace.z) < camera_cascade_distances[cascade_index])
|
||||
break;
|
||||
|
||||
// Фоновая освещенность
|
||||
color = vec4(ka, 1);
|
||||
|
||||
|
@ -81,7 +71,7 @@ void main()
|
|||
if (length(sun.color) > 0)
|
||||
{
|
||||
// Расположение фрагмента в координатах теневой карты
|
||||
fragPosLightSpace = (sun.vp[cascade_index] * vec4(fragPos, 1.0)).xyz;
|
||||
fragPosLightSpace = (sun.vp * vec4(fragPos, 1.0)).xyz;
|
||||
// Переход от [-1;1] к [0;1]
|
||||
fragPosLightSpace = (fragPosLightSpace + vec3(1.0)) / 2;
|
||||
// Сдвиг для решения проблемы акне
|
||||
|
@ -92,7 +82,7 @@ void main()
|
|||
{
|
||||
for(y = -1; y <= 1; ++y)
|
||||
{
|
||||
pcfDepth = texture(sunShadowDepth, vec3(fragPosLightSpace.xy + vec2(x, y) * texelSize, cascade_index)).r;
|
||||
pcfDepth = texture(sunShadowDepth, fragPosLightSpace.xy + vec2(x, y) * texelSize).r;
|
||||
shadowValue += fragPosLightSpace.z > pcfDepth ? 1.0 : 0.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#version 420 core
|
||||
|
||||
layout(triangles, invocations = 4) in; // здесь invocations должно соответствовать количеству каскадов
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
|
||||
layout(std140, binding = 3) uniform Sun
|
||||
{
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
mat4 vp[4];
|
||||
} sun;
|
||||
|
||||
void main()
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
gl_Position = sun.vp[gl_InvocationID] * gl_in[i].gl_Position;
|
||||
gl_Layer = gl_InvocationID;
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
|
@ -4,7 +4,14 @@ layout (location = 0) in vec3 pos;
|
|||
|
||||
uniform mat4 model;
|
||||
|
||||
layout(std140, binding = 3) uniform Sun
|
||||
{
|
||||
vec3 direction;
|
||||
vec3 color;
|
||||
mat4 vp;
|
||||
} sun;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = model * vec4(pos, 1.0);
|
||||
gl_Position = sun.vp * model * vec4(pos, 1.0);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
// Указатель на текущую используемую камеру
|
||||
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) // Пусть по умолчанию камера не относится к сцене
|
||||
{
|
||||
|
@ -36,8 +33,7 @@ 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),
|
||||
requiredRecalcCoords(true)
|
||||
: Node(copy), projection(copy.projection), requiredRecalcVP(copy.requiredRecalcVP), sensitivity(copy.sensitivity)
|
||||
{
|
||||
// Если у оригинала не было изменений - перепишем матрицу вида-проекции
|
||||
if (!requiredRecalcVP)
|
||||
|
@ -94,8 +90,6 @@ 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]);
|
||||
}
|
||||
|
||||
// Устанавливает заданную ортографическую матрицу
|
||||
|
@ -104,9 +98,6 @@ 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]);
|
||||
|
||||
}
|
||||
|
||||
// Изменяет чувствительность мыши
|
||||
|
@ -201,7 +192,7 @@ CameraData& Camera::getData()
|
|||
}
|
||||
|
||||
// Доступ к координатам с флагом изменения, описывающим пространство вида с пересчетом, если это требуется
|
||||
std::pair<bool, const glm::vec4(*)[8]> Camera::getProjCoords()
|
||||
std::pair<bool, const glm::vec4*> Camera::getProjCoords()
|
||||
{
|
||||
const glm::mat4& cam_vp = getVP(); // Получение ссылки на матрицу вида-проекции с пересчетом, если требуется и активацией флага requiredRecalcCoords
|
||||
bool changes = false; // Возвращаемое значение
|
||||
|
@ -219,16 +210,11 @@ std::pair<bool, const glm::vec4(*)[8]> Camera::getProjCoords()
|
|||
, {-1, 1,-1,1}
|
||||
, {-1,-1, 1,1}
|
||||
, {-1,-1,-1,1}};
|
||||
|
||||
for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
coords[i] = inv * typical_points[i];
|
||||
coords[i] /= coords[i].w; // Переход от гомогенных координат к обычным
|
||||
}
|
||||
|
||||
requiredRecalcCoords = false; // Сбрасываем флаг
|
||||
|
|
|
@ -305,36 +305,31 @@ glm::vec3& Sun::e_color()
|
|||
// Пересчитывает по необходимости матрицу вида-проекции
|
||||
void Sun::recalcVP()
|
||||
{
|
||||
// Точки по краям проекции камеры
|
||||
std::pair <bool, const glm::vec4(*)[8]> camProjCoords = Camera::current().getProjCoords();
|
||||
std::pair <bool, const glm::vec4*> camProjCoords = Camera::current().getProjCoords();
|
||||
|
||||
// Есть изменения по источнику или камере
|
||||
if (uploadReq || camProjCoords.first)
|
||||
{
|
||||
uploadReq = true; // Требуется загрузка в следствии пересчета матрицы
|
||||
|
||||
glm::vec3 mean; // Среднее арифметическое
|
||||
glm::vec3 mean = glm::vec3(0); // Среднее арифметическое
|
||||
glm::vec4 max, min; // макс и мин координаты
|
||||
glm::vec4 point; // Точка приведенная в пространство источника света
|
||||
|
||||
|
||||
for (int cascade = 0; cascade < CAMERA_CASCADE_COUNT; cascade++)
|
||||
{
|
||||
mean = glm::vec3(0);
|
||||
// Найдем среднее арифметическое от точек для нахождения центра прямоугольника
|
||||
for (int i = 0; i < 8; i++)
|
||||
mean += glm::vec3(camProjCoords.second[cascade][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[cascade][0];
|
||||
min = max = lightView * camProjCoords.second[0];
|
||||
// Для оставшихся точек
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
// Приведем в пространство вида источника
|
||||
point = lightView * camProjCoords.second[cascade][i];
|
||||
point = lightView * camProjCoords.second[i];
|
||||
max = glm::max(max, point);
|
||||
min = glm::min(min, point);
|
||||
}
|
||||
|
@ -342,7 +337,6 @@ void Sun::recalcVP()
|
|||
// Максимальное значение глубины
|
||||
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;
|
||||
}
|
||||
vp = glm::ortho(min.x, max.x, min.y, max.y, min.z, max.z) * lightView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,62 +151,3 @@ void BaseTexture::setType(GLuint type)
|
|||
{
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
// Конструктор текстуры заданного размера для использования в буфере
|
||||
TextureArray::TextureArray(GLuint levels, GLuint width, GLuint height, GLuint attachment, GLuint texType, GLint internalformat, GLint format, GLenum dataType)
|
||||
{
|
||||
type = texType;
|
||||
// Генерация текстуры заданного размера
|
||||
glGenTextures(1, &handler);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, handler);
|
||||
glTexImage3D(
|
||||
GL_TEXTURE_2D_ARRAY, 0, internalformat, width, height, levels, 0, format, dataType, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Привязка к буферу кадра
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, attachment, handler, 0);
|
||||
|
||||
// Создаем счетчик использований дескриптора
|
||||
handler_count[handler] = 1;
|
||||
}
|
||||
|
||||
// Конструктор копирования
|
||||
TextureArray::TextureArray(const TextureArray& other)
|
||||
{
|
||||
handler = other.handler;
|
||||
type = other.type;
|
||||
// Делаем копию и увеличиваем счетчик
|
||||
handler_count[handler]++;
|
||||
}
|
||||
|
||||
// Оператор присваивания
|
||||
TextureArray& TextureArray::operator=(const TextureArray& other)
|
||||
{
|
||||
// Если это разные текстуры
|
||||
if (handler != other.handler)
|
||||
{
|
||||
this->~TextureArray(); // Уничтожаем имеющуюся
|
||||
// Заменяем новой
|
||||
handler = other.handler;
|
||||
handler_count[handler]++;
|
||||
}
|
||||
type = other.type;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Пересоздает текстуру для имеющегося дескриптора
|
||||
void TextureArray::reallocate(GLuint levels, GLuint width, GLuint height, GLuint texType, GLint internalformat, GLint format, GLenum dataType)
|
||||
{
|
||||
use();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, dataType, NULL);
|
||||
}
|
||||
|
||||
// Привязка текстуры
|
||||
void TextureArray::use()
|
||||
{
|
||||
glActiveTexture(type + GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, handler); // Привязка текстуры как активной
|
||||
}
|
||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -182,8 +182,6 @@ int main(void)
|
|||
lightShader.link();
|
||||
const char* gtextures_shader_names[] = {"gPosition", "gNormal", "gDiffuseP", "gAmbientSpecular", "sunShadowDepth"};
|
||||
lightShader.bindTextures(gtextures_shader_names, sizeof(gtextures_shader_names)/sizeof(const char*));
|
||||
// Загрузка данных о границах каскадов
|
||||
glUniform1fv(lightShader.getUniformLoc("camera_cascade_distances"), CAMERA_CASCADE_COUNT, &camera_cascade_distances[1]);
|
||||
|
||||
glm::vec3 quadVertices[] = { {-1.0f, 1.0f, 0.0f}
|
||||
, {-1.0f, -1.0f, 0.0f}
|
||||
|
@ -202,12 +200,12 @@ int main(void)
|
|||
// Создадим буфер кадра для рендера теней
|
||||
FBO sunShadowBuffer;
|
||||
// Создадим текстуры для буфера кадра
|
||||
TextureArray sunShadowDepth(CAMERA_CASCADE_COUNT, sunShadow_resolution, sunShadow_resolution, GL_DEPTH_ATTACHMENT, 4, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
|
||||
Texture sunShadowDepth(sunShadow_resolution, sunShadow_resolution, GL_DEPTH_ATTACHMENT, 4, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
|
||||
// Правка фантомных теней
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
float shadowBorderColor[] = { 1.0, 1.0, 1.0, 1.0 };
|
||||
glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, shadowBorderColor);
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, shadowBorderColor);
|
||||
// Отключим работу с цветом
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
@ -218,8 +216,6 @@ int main(void)
|
|||
ShaderProgram sunShadowShader;
|
||||
// Загрузим шейдер
|
||||
sunShadowShader.load(GL_VERTEX_SHADER, "shaders/sun_shadow.vert");
|
||||
sunShadowShader.load(GL_GEOMETRY_SHADER, "shaders/sun_shadow.geom");
|
||||
sunShadowShader.load(GL_FRAGMENT_SHADER, "shaders/empty.frag");
|
||||
sunShadowShader.link();
|
||||
|
||||
// Модель прямоугольника
|
||||
|
|
Loading…
Reference in New Issue