Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
|
@ -1,45 +0,0 @@
|
|||
#ifndef TRS_H
|
||||
#define TRS_H
|
||||
|
||||
#define T_SENSITIVITY 0.001f
|
||||
#define R_SENSITIVITY 0.01f
|
||||
#define S_SENSITIVITY 0.00001f
|
||||
|
||||
#include "Scene.h"
|
||||
|
||||
// Интерфейс инструмента
|
||||
class TRS
|
||||
{
|
||||
public:
|
||||
void render(GLuint64 selectedID, ShaderProgram &shaderProgram, UBO &material_buffer); // Рендер инструмента нужного типа для выбранного объекта
|
||||
virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos) = 0; // Взаимодействие с инструментом
|
||||
protected:
|
||||
void init_etc(); // Инициализирует дополнительную информацию модели
|
||||
Scene tool; // Модель
|
||||
};
|
||||
|
||||
// Инструмент трансформации
|
||||
class Transform : public TRS
|
||||
{
|
||||
public:
|
||||
Transform();
|
||||
virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos); // Взаимодействие с инструментом
|
||||
};
|
||||
|
||||
// Инструмент поворота
|
||||
class Rotate : public TRS
|
||||
{
|
||||
public:
|
||||
Rotate();
|
||||
virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& drot); // Взаимодействие с инструментом
|
||||
};
|
||||
|
||||
// Инструмент масштабирования
|
||||
class Scale : public TRS
|
||||
{
|
||||
public:
|
||||
Scale();
|
||||
virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& dscale); // Взаимодействие с инструментом
|
||||
};
|
||||
|
||||
#endif // TRS_H
|
|
@ -18,25 +18,16 @@ layout(std140, binding = 4) uniform gamma
|
|||
float inv_gamma;
|
||||
};
|
||||
|
||||
layout (location = 1) out vec3 gNormal;
|
||||
layout (location = 3) out vec4 gAmbientSpecular;
|
||||
layout (location = 4) out uvec3 gID;
|
||||
out vec4 color;
|
||||
|
||||
uniform float angle;
|
||||
uniform vec3 direction;
|
||||
|
||||
uniform uvec3 ID = uvec3(0);
|
||||
|
||||
void main()
|
||||
{
|
||||
float cosA = dot(normalize(pos_local), normalize(direction));
|
||||
if (degrees(acos(cosA)) <= angle)
|
||||
gAmbientSpecular.rgb = pow(ka, vec3(inv_gamma));
|
||||
color = vec4(pow(ka, vec3(inv_gamma)), 1);
|
||||
else
|
||||
discard;
|
||||
|
||||
gNormal = vec3(0);
|
||||
|
||||
// Сохранение идентификатора объекта
|
||||
gID = ID;
|
||||
}
|
|
@ -40,9 +40,6 @@ uniform sampler2D gAmbientSpecular;
|
|||
uniform sampler2DArray sunShadowDepth;
|
||||
uniform samplerCubeArray pointShadowDepth;
|
||||
uniform sampler2D ssao;
|
||||
uniform usampler2D gID;
|
||||
|
||||
uniform uvec3 selectedID;
|
||||
|
||||
layout(std140, binding = 4) uniform gamma
|
||||
{
|
||||
|
@ -201,21 +198,4 @@ void main()
|
|||
|
||||
// Применение гамма-коррекции
|
||||
color.rgb = pow(color.rgb, vec3(inv_gamma));
|
||||
|
||||
vec3 ID = texture(gID, texCoord).rgb;
|
||||
// Обводка выбранного объекта
|
||||
if (length(selectedID.rg) > 0 && selectedID.rg == ID.rg && ID.b == 0)
|
||||
{
|
||||
int border_width = 3;
|
||||
vec2 size = 1.0f / textureSize(gID, 0);
|
||||
for (int i = -border_width; i <= +border_width; i++)
|
||||
for (int j = -border_width; j <= +border_width; j++)
|
||||
{
|
||||
if (i == 0 && j == 0)
|
||||
continue;
|
||||
|
||||
if (texture(gID, texCoord + vec2(i, j) * size).rg != selectedID.rg)
|
||||
color.rgb = vec3(1.0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#version 420 core
|
||||
|
||||
layout(std140, binding = 1) uniform Material
|
||||
{
|
||||
vec3 ka;
|
||||
vec3 kd;
|
||||
vec3 ks;
|
||||
float p;
|
||||
bool normalmapped;
|
||||
bool parallaxmapped;
|
||||
bool displacementmapped;
|
||||
};
|
||||
|
||||
layout (location = 1) out vec3 gNormal;
|
||||
layout (location = 3) out vec4 gAmbientSpecular;
|
||||
layout (location = 4) out uvec3 gID;
|
||||
|
||||
in vec3 vertex; // Позиция вершины в пространстве
|
||||
in vec3 N; // Нормаль трансформированная
|
||||
in vec2 texCoord; // Текстурные координаты
|
||||
in vec3 T; // Касательный вектор
|
||||
in vec3 B; // Бикасательный вектор
|
||||
in vec3 view; // Вектор от поверхности к камере
|
||||
|
||||
uniform float parallax_heightScale = 0.1;
|
||||
|
||||
uniform uvec3 ID = uvec3(0);
|
||||
|
||||
void main()
|
||||
{
|
||||
gNormal = vec3(0);
|
||||
// Сохранение фоновой составляющей
|
||||
gAmbientSpecular.rgb = ka;
|
||||
// Сохранение идентификатора объекта
|
||||
gID = ID;
|
||||
|
||||
gl_FragDepth = 0.01 * gl_FragCoord.z;
|
||||
}
|
|
@ -205,10 +205,6 @@ void Light::render(ShaderProgram &shaderProgram, UBO &material_buffer)
|
|||
// Цикл по источникам света
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Идентификатор источника как узла сцены для всей модели лампочки
|
||||
bulb.set_group_id((GLuint64) &lights[i]);
|
||||
sphere.id.value = (GLuint64) &lights[i];
|
||||
|
||||
// Загрузим направление
|
||||
glUniform3fv(direction_uniform, 1, &data[i].direction_angle.x);
|
||||
// Угол для лампочки = 180 (рисуем целую модель)
|
||||
|
|
187
src/TRS.cpp
187
src/TRS.cpp
|
@ -1,187 +0,0 @@
|
|||
#include "TRS.h"
|
||||
#include <GLM/gtx/matrix_decompose.hpp>
|
||||
|
||||
// Инициализирует дополнительную информацию модели
|
||||
void TRS::init_etc()
|
||||
{
|
||||
int value = 1;
|
||||
for (auto it = tool.models.begin(); it != tool.models.end(); ++it)
|
||||
it->id.etc = value++;
|
||||
}
|
||||
|
||||
// Рендер инструмента нужного типа для выбранного объекта
|
||||
void TRS::render(GLuint64 selectedID, ShaderProgram &shaderProgram, UBO &material_buffer)
|
||||
{
|
||||
// Если есть выбранная модель - рендерим инструмент для неё
|
||||
if (selectedID)
|
||||
{
|
||||
// Указатель на объект
|
||||
Node* selectedObject = (Node*) selectedID;
|
||||
|
||||
// Смещение выбранного объекта в глобальных координатах из его матрицы трансформации (включая родительские)
|
||||
tool.root.e_position() = glm::vec3(selectedObject->getTransformMatrix()[3]);
|
||||
|
||||
// Замена идентификатора инструмента идентификатором выбранного объекта
|
||||
tool.set_group_id(selectedID); // без замены доп. информации
|
||||
|
||||
// Рендер инструмента
|
||||
tool.render(shaderProgram, material_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Transform::Transform()
|
||||
{
|
||||
tool = loadOBJtoScene("../resources/models/tools/transform.obj", "../resources/models/tools/", "../resources/textures/");
|
||||
|
||||
// Масштабирование
|
||||
tool.root.e_scale() = glm::vec3(0.3);
|
||||
|
||||
// Инициализация дополнительной информации
|
||||
init_etc();
|
||||
}
|
||||
|
||||
// Взаимодействие с инструментом
|
||||
void Transform::process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos)
|
||||
{
|
||||
// Если взаимодействие с осями инструмента
|
||||
if (etc > 0)
|
||||
// Если есть выбранная модель - рендерим инструмент для неё
|
||||
if (selectedID)
|
||||
{
|
||||
// Указатель на объект
|
||||
Node* selectedObject = (Node*) selectedID;
|
||||
|
||||
glm::vec3 dVec(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Сдвиг с учетом чувствительности для соответствующих осей
|
||||
if (etc & 01)
|
||||
dVec.x = dpos.x * T_SENSITIVITY;
|
||||
if (etc & 02)
|
||||
dVec.y = dpos.y * T_SENSITIVITY;
|
||||
if (etc & 04)
|
||||
dVec.z = dpos.z * T_SENSITIVITY;
|
||||
|
||||
// Если есть родитель - требуется учесть его поворот
|
||||
Node* parent = selectedObject->getParent();
|
||||
if (parent)
|
||||
{
|
||||
// Извлекаем 3x3 подматрицу, отвечающую за вращение и масштаб
|
||||
glm::mat3 rotationMatrix = glm::mat3(parent->getTransformMatrix());
|
||||
|
||||
// Нормализуем столбцы подматрицы, чтобы исключить масштабирование
|
||||
for (int i = 0; i < 3; i++)
|
||||
rotationMatrix[i] = glm::normalize(rotationMatrix[i]);
|
||||
|
||||
// Применим поворот родителя к вектору сдвига
|
||||
dVec = glm::inverse(rotationMatrix) * dVec;
|
||||
}
|
||||
|
||||
// Добавим сдвиг от инструмента к позиции выбранного объекта
|
||||
selectedObject->e_position() += dVec;
|
||||
}
|
||||
}
|
||||
|
||||
Rotate::Rotate()
|
||||
{
|
||||
tool = loadOBJtoScene("../resources/models/tools/rotate.obj", "../resources/models/tools/", "../resources/textures/");
|
||||
|
||||
// Масштабирование
|
||||
tool.root.e_scale() = glm::vec3(0.3);
|
||||
|
||||
int value = 1;
|
||||
for (auto it = tool.models.begin(); it != tool.models.end(); ++it)
|
||||
{
|
||||
it->id.etc = value;
|
||||
value *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Взаимодействие с инструментом
|
||||
void Rotate::process(GLuint64 selectedID, GLuint etc, const glm::vec4& drot)
|
||||
{
|
||||
// Если взаимодействие с осями инструмента
|
||||
if (etc > 0)
|
||||
// Если есть выбранная модель - рендерим инструмент для неё
|
||||
if (selectedID)
|
||||
{
|
||||
// Указатель на объект
|
||||
Node* selectedObject = (Node*) selectedID;
|
||||
glm::quat &selectedRot = selectedObject->e_rotation();
|
||||
|
||||
// Матрица родительского поворота
|
||||
glm::mat3 parentRotation(1);
|
||||
|
||||
// Учет родительского поворота для вращения
|
||||
Node* parent = selectedObject->getParent();
|
||||
if (parent)
|
||||
{
|
||||
// Извлекаем 3x3 подматрицу, отвечающую за вращение и масштаб
|
||||
parentRotation = glm::mat3(parent->getTransformMatrix());
|
||||
|
||||
// Нормализуем столбцы подматрицы, чтобы исключить масштабирование
|
||||
for (int i = 0; i < 3; i++)
|
||||
parentRotation[i] = glm::normalize(parentRotation[i]);
|
||||
}
|
||||
|
||||
// Поворот по осям
|
||||
if (etc & 01)
|
||||
selectedRot = glm::angleAxis(drot.y * R_SENSITIVITY, parentRotation * glm::vec3(1.0f, 0.0f, 0.0f)) * selectedRot;
|
||||
if (etc & 02)
|
||||
selectedRot = glm::angleAxis(drot.x * R_SENSITIVITY, parentRotation * glm::vec3(0.0f, 1.0f, 0.0f)) * selectedRot;
|
||||
if (etc & 04)
|
||||
selectedRot = glm::angleAxis(drot.z * R_SENSITIVITY, parentRotation * glm::vec3(0.0f, 0.0f, 1.0f)) * selectedRot;
|
||||
}
|
||||
}
|
||||
|
||||
Scale::Scale()
|
||||
{
|
||||
tool = loadOBJtoScene("../resources/models/tools/scale.obj", "../resources/models/tools/", "../resources/textures/");
|
||||
|
||||
// Масштабирование
|
||||
tool.root.e_scale() = glm::vec3(0.3);
|
||||
|
||||
// Инициализация дополнительной информации
|
||||
init_etc();
|
||||
}
|
||||
|
||||
// Взаимодействие с инструментом
|
||||
void Scale::process(GLuint64 selectedID, GLuint etc, const glm::vec4& dscale)
|
||||
{
|
||||
// Если взаимодействие с осями инструмента
|
||||
if (etc > 0)
|
||||
// Если есть выбранная модель - рендерим инструмент для неё
|
||||
if (selectedID)
|
||||
{
|
||||
// Указатель на объект
|
||||
Node* selectedObject = (Node*) selectedID;
|
||||
|
||||
// Для хранения результата
|
||||
glm::vec3 dVec(0);
|
||||
|
||||
// Масштабирование с учетом чувствительности для соответствующих осей
|
||||
if (etc & 01)
|
||||
dVec.x = dscale.x * S_SENSITIVITY;
|
||||
if (etc & 02)
|
||||
dVec.y = dscale.y * S_SENSITIVITY;
|
||||
if (etc & 04)
|
||||
dVec.z = dscale.z * S_SENSITIVITY;
|
||||
|
||||
// Если есть родитель - требуется учесть его поворот
|
||||
Node* parent = selectedObject->getParent();
|
||||
if (parent)
|
||||
{
|
||||
// Извлекаем 3x3 подматрицу, отвечающую за вращение и масштаб
|
||||
glm::mat3 rotationMatrix = glm::mat3(parent->getTransformMatrix());
|
||||
|
||||
// Нормализуем столбцы подматрицы, чтобы исключить масштабирование
|
||||
for (int i = 0; i < 3; i++)
|
||||
rotationMatrix[i] = glm::normalize(rotationMatrix[i]);
|
||||
|
||||
// Применим поворот родителя к вектору сдвига
|
||||
dVec = glm::inverse(rotationMatrix) * dVec;
|
||||
}
|
||||
|
||||
// Прибавим вектор масштабирования к объекту
|
||||
selectedObject->e_scale() += dVec;
|
||||
}
|
||||
}
|
94
src/main.cpp
94
src/main.cpp
|
@ -9,7 +9,6 @@
|
|||
#include "Scene.h"
|
||||
#include "Shader.h"
|
||||
#include "Lights.h"
|
||||
#include "TRS.h"
|
||||
|
||||
#define WINDOW_CAPTION "OPENGL notes on rekovalev.site"
|
||||
|
||||
|
@ -62,34 +61,23 @@ void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
|||
Camera::current().setPerspective(CAMERA_FOVy, (float)width/height);
|
||||
}
|
||||
|
||||
// Данные о мыши
|
||||
struct Mouse
|
||||
{
|
||||
float x = 0, y = 0; // Координаты курсора
|
||||
float prev_x = 0, prev_y = 0; // Координаты курсора на предыдущем кадре
|
||||
uint16_t left = 040100, right = 040100; // Состояние кнопок
|
||||
} mouse;
|
||||
|
||||
void process_mouse_button(uint16_t& button)
|
||||
{
|
||||
if ((++button & 037777) == 037777)
|
||||
button &= 0140100;
|
||||
}
|
||||
bool firstMouse = true;
|
||||
float lastX, lastY;
|
||||
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
mouse.x = xpos;
|
||||
mouse.y = ypos;
|
||||
}
|
||||
if (firstMouse)
|
||||
{
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
firstMouse = false;
|
||||
}
|
||||
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
uint16_t& mouse_button = (button == GLFW_MOUSE_BUTTON_LEFT)?mouse.left:mouse.right;
|
||||
glm::vec2 offset(xpos - lastX, lastY - ypos);
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
if (action == GLFW_PRESS && !(mouse_button & 0100000))
|
||||
mouse_button = 0100000;
|
||||
else if (action == GLFW_RELEASE)
|
||||
mouse_button = 040000;
|
||||
Camera::current().rotate(offset);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -127,7 +115,6 @@ int main(void)
|
|||
|
||||
// Установка callback-функции для мыши и камеры
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
|
||||
// Загрузка функций OpenGL с помощью GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
|
@ -155,7 +142,6 @@ int main(void)
|
|||
scene.root.e_position().z = 1;
|
||||
scene.models.begin()->material.kd = {0.5,0.5,0.5};
|
||||
scene.models.begin()->material.ka = {0.05,0.05,0.05};
|
||||
scene.set_group_id((GLuint64) &scene);
|
||||
|
||||
// Установка цвета очистки буфера цвета
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
@ -211,7 +197,7 @@ int main(void)
|
|||
lightShader.load(GL_FRAGMENT_SHADER, "shaders/lighting.frag");
|
||||
lightShader.link();
|
||||
// Привязка текстур
|
||||
const char* gtextures_shader_names[] = {"gPosition", "gNormal", "gDiffuseP", "gAmbientSpecular", "sunShadowDepth", "pointShadowDepth", "ssao", "gID"};
|
||||
const char* gtextures_shader_names[] = {"gPosition", "gNormal", "gDiffuseP", "gAmbientSpecular", "sunShadowDepth", "pointShadowDepth", "ssao"};
|
||||
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]);
|
||||
|
@ -435,19 +421,6 @@ int main(void)
|
|||
|
||||
ID selected; // Выбранная модель
|
||||
|
||||
// Шейдер для инструментов
|
||||
ShaderProgram toolsShader;
|
||||
// Загрузим шейдеры
|
||||
toolsShader.load(GL_VERTEX_SHADER, "shaders/gshader.vert");
|
||||
toolsShader.load(GL_FRAGMENT_SHADER, "shaders/tools.frag");
|
||||
toolsShader.link();
|
||||
|
||||
// Инструменты
|
||||
Transform transform;
|
||||
Rotate rotate;
|
||||
Scale scale;
|
||||
TRS& currentTool = transform;
|
||||
|
||||
// Пока не произойдет событие запроса закрытия окна
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
|
@ -469,22 +442,9 @@ int main(void)
|
|||
scene.render(gShader, material_data);
|
||||
rectangle.render(gShader, material_data);
|
||||
|
||||
// Отрисовка отладочных лампочек со специальным шейдером
|
||||
bulbShader.use();
|
||||
Light::render(bulbShader, material_data);
|
||||
|
||||
// Используем шейдер для инструментов
|
||||
toolsShader.use();
|
||||
// Рендерим инструменты для выбранного объекта
|
||||
currentTool.render(selected.value, toolsShader, material_data);
|
||||
|
||||
// Выбор объекта
|
||||
if (mouse.left == 0100000)
|
||||
{
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT4);
|
||||
glReadPixels(mouse.x, WINDOW_HEIGHT-mouse.y, 1, 1, GL_RGB_INTEGER, GL_UNSIGNED_INT, &selected);
|
||||
std::cout << (void*) selected.value << ' ' << selected.etc << '\n';
|
||||
}
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT4);
|
||||
glReadPixels(lastX, WINDOW_HEIGHT-lastY, 1, 1, GL_RGB_INTEGER, GL_UNSIGNED_INT, &selected);
|
||||
std::cout << (void*) selected.value << ' ' << selected.etc << '\n';
|
||||
|
||||
// Активируем буфер SSAO
|
||||
ssaoBuffer.use();
|
||||
|
@ -553,9 +513,6 @@ int main(void)
|
|||
gNormal.use();
|
||||
gDiffuseP.use();
|
||||
gAmbientSpecular.use();
|
||||
gID.use();
|
||||
// Идентификатор выбранного объекта для обводки
|
||||
glUniform3uiv(lightShader.getUniformLoc("selectedID"), 1, (GLuint*) &selected);
|
||||
// Подключаем текстуры теней
|
||||
sunShadowDepth.use();
|
||||
pointShadowDepth.use();
|
||||
|
@ -582,27 +539,14 @@ int main(void)
|
|||
// Возвращаем запись глубины
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Дополнительная обработка мыши
|
||||
process_mouse_button(mouse.left);
|
||||
process_mouse_button(mouse.right);
|
||||
mouse.prev_x = mouse.x;
|
||||
mouse.prev_y = mouse.y;
|
||||
// Отрисовка отладочных лампочек со специальным шейдером
|
||||
bulbShader.use();
|
||||
Light::render(bulbShader, material_data);
|
||||
|
||||
// Представление содержимого буфера цепочки показа на окно
|
||||
glfwSwapBuffers(window);
|
||||
// Обработка системных событий
|
||||
glfwPollEvents();
|
||||
|
||||
// Поворот камеры
|
||||
if (mouse.right & 0100000
|
||||
&& mouse.x != mouse.prev_x
|
||||
&& mouse.y != mouse.prev_y)
|
||||
Camera::current().rotate(glm::vec2(mouse.x - mouse.prev_x, mouse.prev_y - mouse.y));
|
||||
|
||||
// Взаимодействие с инструментом при зажатой левой кнопке
|
||||
if (mouse.left > 0100000)
|
||||
if (selected.etc)
|
||||
currentTool.process(selected.value, selected.etc, glm::transpose(Camera::current().getVP()) * glm::vec4(mouse.x - mouse.prev_x, mouse.prev_y - mouse.y, 0, 1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue