Копия проекта с 03
This commit is contained in:
parent
3b5808973c
commit
f942f5bd2b
18
.vscode/c_cpp_properties.json
vendored
Normal file
18
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "some_name",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/include",
|
||||||
|
"${workspaceFolder}/../dependencies/GLFW/include",
|
||||||
|
"${workspaceFolder}/../dependencies/glad/include",
|
||||||
|
"${workspaceFolder}/../dependencies/glm"
|
||||||
|
],
|
||||||
|
"compilerPath": "C:/MinGW/bin/g++.exe",
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++11",
|
||||||
|
"intelliSenseMode": "gcc-x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"fstream": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"atomic": "cpp"
|
||||||
|
}
|
||||||
|
}
|
75
.vscode/tasks.json
vendored
Normal file
75
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++: g++.exe сборка активного файла",
|
||||||
|
"command": "C:/MinGW/bin/g++.exe",
|
||||||
|
"args": [
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"${workspaceRoot}/src/*.cpp",
|
||||||
|
"${workspaceRoot}/../dependencies/glad/src/glad.c",
|
||||||
|
|
||||||
|
"-I${workspaceRoot}/include",
|
||||||
|
|
||||||
|
"--std=c++11",
|
||||||
|
|
||||||
|
"-I${workspaceRoot}/../dependencies/GLFW/include",
|
||||||
|
"-L${workspaceRoot}/../dependencies/GLFW/lib-mingw",
|
||||||
|
"-I${workspaceFolder}/../dependencies/glad/include",
|
||||||
|
"-I${workspaceFolder}/../dependencies/glm",
|
||||||
|
"-static",
|
||||||
|
"-lopengl32",
|
||||||
|
"-lglfw3dll",
|
||||||
|
"-o",
|
||||||
|
"${workspaceRoot}/${workspaceFolderBasename}.exe"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${fileDirname}"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"detail": "Задача создана отладчиком."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++ x64: g++.exe сборка активного файла",
|
||||||
|
"command": "C:/MinGW64/bin/g++.exe",
|
||||||
|
"args": [
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"${workspaceRoot}/src/*.cpp",
|
||||||
|
"${workspaceRoot}/../dependencies/glad/src/glad.c",
|
||||||
|
|
||||||
|
"-I${workspaceRoot}/include",
|
||||||
|
|
||||||
|
"--std=c++11",
|
||||||
|
|
||||||
|
"-I${workspaceRoot}/../dependencies/GLFW/include",
|
||||||
|
"-L${workspaceRoot}/../dependencies/GLFW/lib-mingw-w64",
|
||||||
|
"-I${workspaceFolder}/../dependencies/glad/include",
|
||||||
|
"-I${workspaceFolder}/../dependencies/glm",
|
||||||
|
"-static",
|
||||||
|
"-lopengl32",
|
||||||
|
"-lglfw3dll",
|
||||||
|
"-o",
|
||||||
|
"${workspaceRoot}/${workspaceFolderBasename}.exe"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${fileDirname}"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"detail": "Задача создана отладчиком."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
50
include/Buffers.h
Normal file
50
include/Buffers.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef BUFFERS_H
|
||||||
|
#define BUFFERS_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// Объект массива вершин
|
||||||
|
class VAO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VAO(); // Создает VAO и активирует его
|
||||||
|
~VAO(); // Уничтожает VAO
|
||||||
|
VAO(const VAO & copy); // Конструктор копирования
|
||||||
|
VAO& operator=(const VAO & other); // Оператор присваивания
|
||||||
|
|
||||||
|
void use(); // Активация VAO
|
||||||
|
static void disable(); // Деактивация активного VAO
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint handler; // Дескриптор
|
||||||
|
static std::map<GLuint, GLuint> handler_count; // Счетчик использований дескриптора
|
||||||
|
};
|
||||||
|
|
||||||
|
// Тип буфера
|
||||||
|
enum BUFFER_TYPE { VERTEX = GL_ARRAY_BUFFER
|
||||||
|
, ELEMENT = GL_ELEMENT_ARRAY_BUFFER
|
||||||
|
};
|
||||||
|
|
||||||
|
// Объект вершинного буфера
|
||||||
|
class BO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BO(BUFFER_TYPE type); // Создает пустой буфер заданного типа
|
||||||
|
BO(BUFFER_TYPE type, const void *data, int size); // Создает и загружает туда данные
|
||||||
|
~BO(); // Уничтожает буфер
|
||||||
|
BO(const BO & copy); // Конструктор копирования
|
||||||
|
BO& operator=(const BO & other); // Оператор присваивания
|
||||||
|
|
||||||
|
void load(const void *data, int size, GLuint mode = GL_STATIC_DRAW); // Загрузка данных в буфер
|
||||||
|
void use();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GLuint handler; // Дескриптор
|
||||||
|
BUFFER_TYPE type; // Тип буфера
|
||||||
|
private:
|
||||||
|
static std::map<GLuint, GLuint> handler_count; // Счетчик использований дескриптора
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BUFFERS_H
|
49
include/Camera.h
Normal file
49
include/Camera.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
|
||||||
|
#include <GLM/glm.hpp>
|
||||||
|
|
||||||
|
// Ближняя граница области отсечения
|
||||||
|
#define CAMERA_NEAR 0.1f
|
||||||
|
// Дальняя граница области отсечения
|
||||||
|
#define CAMERA_FAR 100.0f
|
||||||
|
// Вектор, задающий верх для камеры
|
||||||
|
#define CAMERA_UP_VECTOR glm::vec3(0.0f, 1.0f, 0.0f)
|
||||||
|
// Стандартный угол обзора
|
||||||
|
#define CAMERA_FOVy 60.0f
|
||||||
|
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Camera(float aspect, const glm::vec3 &position = glm::vec3(0.0f, 0.0f, 0.0f), const glm::vec2 &xyOffset = glm::vec2(90.0f, 0.0f), float fovy = CAMERA_FOVy); // Конструктор камеры с проекцией перспективы
|
||||||
|
Camera(float width, float height, const glm::vec3 &position = glm::vec3(0.0f, 0.0f, 0.0f), const glm::vec2 &xyOffset = glm::vec2(90.0f, 0.0f)); // Конструктор ортографической камеры
|
||||||
|
virtual ~Camera(); // Деструктор
|
||||||
|
const glm::mat4& getVP(); // Возвращает ссылку на константную матрицу произведения матриц вида и проекции
|
||||||
|
const glm::mat4& getProjection(); // Возвращает ссылку на константную матрицу проекции
|
||||||
|
const glm::mat4& getView(); // Возвращает ссылку на константную матрицу вида
|
||||||
|
void rotate(const glm::vec2 &xyOffset); // Поворачивает камеру на dx и dy пикселей
|
||||||
|
void move(const glm::vec3 &posOffset); // Сдвигает камеру на указанный вектор (dx,dy,dz)
|
||||||
|
void setPosition(const glm::vec3 &position); // Устанавливает местоположение
|
||||||
|
void setRotation(const glm::vec2 &xyOffset); // Устанавливает угол поворота камеры
|
||||||
|
void setPerspective(float fov, float aspect); // Устанавливает заданную матрицу перспективы
|
||||||
|
void setOrtho(float width, float height); // Устанавливает заданную ортографическую матрицу
|
||||||
|
void setSensitivity(float sensitivity); // Изменяет чувствительность мыши
|
||||||
|
protected:
|
||||||
|
Camera(const glm::vec3 &position, const glm::vec2 &xyOffset); // Защищенный (protected) констуктор камеры без перспективы
|
||||||
|
void recalcTarget(); // Пересчет цели, на которую смотрит камера
|
||||||
|
void recalcView(); // Пересчет матрицы вида
|
||||||
|
void recalcVP(); // Пересчет произведения матриц
|
||||||
|
|
||||||
|
glm::vec3 position; // Местоположение камеры
|
||||||
|
glm::vec3 target; // Цель, на которую смотрит камера
|
||||||
|
glm::vec2 currentRotation; // Текущий поворот камеры
|
||||||
|
glm::mat4 projection; // Матрица проекции
|
||||||
|
glm::mat4 view; // Матрица вида
|
||||||
|
glm::mat4 vp; // Матрица произведения вида и проекции
|
||||||
|
bool requiredRecalcVP; // Необходимость пересчета матрицы вида и проекции камеры
|
||||||
|
bool requiredRecalcView; // Необходимость пересчета матрицы вида камеры
|
||||||
|
float sensitivity; // Чувствительность мыши
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CAMERA_H
|
31
include/Model.h
Normal file
31
include/Model.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MODEL_H
|
||||||
|
#define MODEL_H
|
||||||
|
|
||||||
|
#include "Buffers.h"
|
||||||
|
|
||||||
|
#include <GLM/glm.hpp>
|
||||||
|
|
||||||
|
class Model
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Model(); // Конструктор без параметров
|
||||||
|
Model(const Model& copy); // Конструктор копирования
|
||||||
|
~Model();
|
||||||
|
void render(const GLuint &mvp_uniform); // Вызов отрисовки
|
||||||
|
void load_verteces(glm::vec3* verteces, GLuint count); // Загрузка вершин в буфер
|
||||||
|
void load_indices(GLuint* indices, GLuint count); // Загрузка индексов в буфер
|
||||||
|
|
||||||
|
glm::vec3 position; // позиция модели
|
||||||
|
glm::vec3 rotation; // поворот модели
|
||||||
|
glm::vec3 scale; // мастабирование модели
|
||||||
|
glm::mat4 getTransformMatrix(); // Матрица трансформации модели
|
||||||
|
|
||||||
|
private:
|
||||||
|
VAO vao;
|
||||||
|
BO vertex_vbo, index_vbo; // вершинный и индексный буферы
|
||||||
|
GLuint verteces_count; // Количество вершин
|
||||||
|
GLuint indices_count; // Количество индексов
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODEL_H
|
8
shaders/shader.frag
Normal file
8
shaders/shader.frag
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
out vec3 color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
color = vec3(1, 0, 0);
|
||||||
|
}
|
10
shaders/shader.vert
Normal file
10
shaders/shader.vert
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 pos;
|
||||||
|
|
||||||
|
uniform mat4 mvp;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = mvp * vec4(pos, 1.0);
|
||||||
|
}
|
119
src/Buffers.cpp
Normal file
119
src/Buffers.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "Buffers.h"
|
||||||
|
|
||||||
|
// Счетчики использований дескрипторов
|
||||||
|
std::map<GLuint, GLuint> VAO::handler_count;
|
||||||
|
std::map<GLuint, GLuint> BO::handler_count;
|
||||||
|
|
||||||
|
// Создает VAO и активирует его
|
||||||
|
VAO::VAO()
|
||||||
|
{
|
||||||
|
glGenVertexArrays(1, &handler); // Генерация одного объекта массива вершин
|
||||||
|
glBindVertexArray(handler); // Привязка для использования
|
||||||
|
handler_count[handler] = 1; // Инициализация счетчика для дескриптора
|
||||||
|
}
|
||||||
|
|
||||||
|
// Уничтожает VAO
|
||||||
|
VAO::~VAO()
|
||||||
|
{
|
||||||
|
// Если дескриптор никем не используется - освободим его
|
||||||
|
if (!--handler_count[handler])
|
||||||
|
{
|
||||||
|
glDeleteVertexArrays(1, &handler);
|
||||||
|
handler_count.erase(handler); // Удаление из словаря
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конструктор копирования
|
||||||
|
VAO::VAO(const VAO & copy) : handler(copy.handler)
|
||||||
|
{
|
||||||
|
handler_count[handler]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Оператор присваивания
|
||||||
|
VAO& VAO::operator=(const VAO & other)
|
||||||
|
{
|
||||||
|
// Если это разные дескрипторы
|
||||||
|
if (handler != other.handler)
|
||||||
|
{ // то следуюет удалить текущий перед заменой
|
||||||
|
this->~VAO();
|
||||||
|
handler = other.handler;
|
||||||
|
handler_count[handler]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Активация VAO
|
||||||
|
void VAO::use()
|
||||||
|
{
|
||||||
|
glBindVertexArray(handler); // Привязка VAO для использования
|
||||||
|
}
|
||||||
|
|
||||||
|
// Деактивация активного VAO
|
||||||
|
void VAO::disable()
|
||||||
|
{
|
||||||
|
glBindVertexArray(0); // Отключение VAO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создает пустой буфер заданного типа
|
||||||
|
BO::BO(BUFFER_TYPE t) : type(t)
|
||||||
|
{
|
||||||
|
glGenBuffers(1, &handler); // Генерация одного объекта буфера
|
||||||
|
handler_count[handler] = 1;
|
||||||
|
use(); // Привязка буфера
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создает и загружает туда данные
|
||||||
|
BO::BO(BUFFER_TYPE t, const void *data, int size) : BO(t)
|
||||||
|
{
|
||||||
|
load(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Уничтожает буфер
|
||||||
|
BO::~BO()
|
||||||
|
{
|
||||||
|
if (handler) // Если буфер был создан
|
||||||
|
{
|
||||||
|
// Если дескриптор никем не используется - освободим его
|
||||||
|
if (!--handler_count[handler])
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &handler);
|
||||||
|
handler_count.erase(handler); // Удаление из словаря
|
||||||
|
}
|
||||||
|
handler = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конструктор копирования
|
||||||
|
BO::BO(const BO & copy) : handler(copy.handler), type(copy.type)
|
||||||
|
{
|
||||||
|
handler_count[handler]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Оператор присваивания
|
||||||
|
BO& BO::operator=(const BO & other)
|
||||||
|
{
|
||||||
|
// Если это разные дескрипторы
|
||||||
|
if (handler != other.handler)
|
||||||
|
{ // то следуюет удалить текущий перед заменой
|
||||||
|
this->~BO();
|
||||||
|
handler = other.handler;
|
||||||
|
handler_count[handler]++;
|
||||||
|
}
|
||||||
|
// Изменим тип
|
||||||
|
type = other.type;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузка вершин в буфер
|
||||||
|
void BO::load(const void *data, int size, GLuint mode)
|
||||||
|
{
|
||||||
|
use(); // Привязка буфера
|
||||||
|
glBufferData(type, size, data, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BO::use()
|
||||||
|
{
|
||||||
|
glBindBuffer(type, handler); // Привязка элементного буфера
|
||||||
|
}
|
141
src/Camera.cpp
Normal file
141
src/Camera.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include "Camera.h"
|
||||||
|
|
||||||
|
#include <GLM/gtc/matrix_transform.hpp>
|
||||||
|
#include <GLM/ext/matrix_transform.hpp>
|
||||||
|
|
||||||
|
// Защищенный (protected) конструктор камеры без перспективы
|
||||||
|
Camera::Camera(const glm::vec3 &pos, const glm::vec2 &xyOffset)
|
||||||
|
: position(pos), currentRotation(xyOffset)
|
||||||
|
{
|
||||||
|
sensitivity = 0.05;
|
||||||
|
recalcTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конструктор камеры с проекцией перспективы
|
||||||
|
Camera::Camera(float aspect, const glm::vec3 &position, const glm::vec2 &xyOffset, float fovy)
|
||||||
|
: Camera(position, xyOffset)
|
||||||
|
{
|
||||||
|
setPerspective(fovy, aspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конструктор ортографической камеры
|
||||||
|
Camera::Camera(float width, float height, const glm::vec3 &position, const glm::vec2 &xyOffset)
|
||||||
|
: Camera(position, xyOffset)
|
||||||
|
{
|
||||||
|
setOrtho(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Деструктор
|
||||||
|
Camera::~Camera() { }
|
||||||
|
|
||||||
|
// Пересчет цели, на которую смотрит камера
|
||||||
|
void Camera::recalcTarget()
|
||||||
|
{
|
||||||
|
if(currentRotation.y > 89.0f)
|
||||||
|
currentRotation.y = 89.0f;
|
||||||
|
if(currentRotation.y < -89.0f)
|
||||||
|
currentRotation.y = -89.0f;
|
||||||
|
|
||||||
|
target.x = cos(glm::radians(currentRotation.x)) * cos(glm::radians(currentRotation.y));
|
||||||
|
target.y = sin(glm::radians(currentRotation.y));
|
||||||
|
target.z = sin(glm::radians(currentRotation.x)) * cos(glm::radians(currentRotation.y));
|
||||||
|
|
||||||
|
requiredRecalcView = true;
|
||||||
|
requiredRecalcVP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Пересчет матрицы вида
|
||||||
|
void Camera::recalcView()
|
||||||
|
{
|
||||||
|
view = glm::lookAt(position, position + target, CAMERA_UP_VECTOR);
|
||||||
|
requiredRecalcView = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Пересчет произведения матриц
|
||||||
|
void Camera::recalcVP()
|
||||||
|
{
|
||||||
|
vp = projection * view;
|
||||||
|
requiredRecalcVP = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращает ссылку на константную матрицу проекции
|
||||||
|
const glm::mat4& Camera::getProjection()
|
||||||
|
{
|
||||||
|
return projection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращает ссылку на константную матрицу вида
|
||||||
|
const glm::mat4& Camera::getView()
|
||||||
|
{
|
||||||
|
if (requiredRecalcView)
|
||||||
|
recalcView();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращает ссылку на константную матрицу вида
|
||||||
|
const glm::mat4& Camera::getVP()
|
||||||
|
{
|
||||||
|
if (requiredRecalcVP)
|
||||||
|
{
|
||||||
|
if (requiredRecalcView)
|
||||||
|
recalcView();
|
||||||
|
recalcVP();
|
||||||
|
}
|
||||||
|
return vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Поворачивает камеру на dx и dy пикселей
|
||||||
|
void Camera::rotate(const glm::vec2 &xyOffset)
|
||||||
|
{
|
||||||
|
currentRotation += xyOffset * sensitivity;
|
||||||
|
|
||||||
|
recalcTarget();
|
||||||
|
requiredRecalcView = true;
|
||||||
|
requiredRecalcVP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сдвигает камеру на указанный вектор (dx,dy,dz)
|
||||||
|
void Camera::move(const glm::vec3 &posOffset)
|
||||||
|
{
|
||||||
|
position += posOffset;
|
||||||
|
|
||||||
|
requiredRecalcView = true;
|
||||||
|
requiredRecalcVP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Устанавливает местоположение
|
||||||
|
void Camera::setPosition(const glm::vec3 &pos)
|
||||||
|
{
|
||||||
|
position = pos;
|
||||||
|
|
||||||
|
requiredRecalcView = true;
|
||||||
|
requiredRecalcVP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Устанавливает угол поворота камеры
|
||||||
|
void Camera::setRotation(const glm::vec2 &xyOffset)
|
||||||
|
{
|
||||||
|
currentRotation = xyOffset;
|
||||||
|
recalcTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Устанавливает заданную матрицу перспективы
|
||||||
|
void Camera::setPerspective(float fovy, float aspect)
|
||||||
|
{
|
||||||
|
projection = glm::perspective(glm::radians(fovy), aspect, CAMERA_NEAR, CAMERA_FAR);
|
||||||
|
requiredRecalcVP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Устанавливает заданную ортографическую матрицу
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Изменяет чувствительность мыши
|
||||||
|
void Camera::setSensitivity(float sens)
|
||||||
|
{
|
||||||
|
sensitivity = sens;
|
||||||
|
}
|
97
src/Model.cpp
Normal file
97
src/Model.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "Model.h"
|
||||||
|
#include "Camera.h"
|
||||||
|
extern Camera camera;
|
||||||
|
|
||||||
|
// Конструктор без параметров
|
||||||
|
Model::Model() : verteces_count(0), indices_count(0), vertex_vbo(VERTEX), index_vbo(ELEMENT), position(0), rotation(0), scale(1)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конструктор копирования
|
||||||
|
Model::Model(const Model& copy) : vao(copy.vao), verteces_count(copy.verteces_count), indices_count(copy.indices_count), vertex_vbo(copy.vertex_vbo), index_vbo(copy.index_vbo), position(copy.position), rotation(copy.rotation), scale(copy.scale)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Model::~Model()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вызов отрисовки
|
||||||
|
void Model::render(const GLuint &mvp_uniform)
|
||||||
|
{
|
||||||
|
// Расчитаем матрицу трансформации
|
||||||
|
glm::mat4 mvp = camera.getVP() * this->getTransformMatrix();
|
||||||
|
glUniformMatrix4fv(mvp_uniform, 1, GL_FALSE, &mvp[0][0]);
|
||||||
|
|
||||||
|
// Подключаем VAO
|
||||||
|
vao.use();
|
||||||
|
// Если есть индексы - рисуем с их использованием
|
||||||
|
if (indices_count)
|
||||||
|
glDrawElements(GL_TRIANGLES, indices_count, GL_UNSIGNED_INT, (void*)0);
|
||||||
|
// Если есть вершины - рисуем на основании массива вершин
|
||||||
|
else if (verteces_count)
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, verteces_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для конфигурации атрибута вершинного буфера
|
||||||
|
void vertex_attrib_config()
|
||||||
|
{
|
||||||
|
// Включаем необходимый атрибут у выбранного VAO
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
// Устанавливаем связь между VAO и привязанным VBO
|
||||||
|
glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера
|
||||||
|
, 3 // количество компонент одного элемента
|
||||||
|
, GL_FLOAT // тип
|
||||||
|
, GL_FALSE // нормализованность значений
|
||||||
|
, 0 // шаг
|
||||||
|
, (void *)0 // отступ с начала массива
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузка вершин в буфер
|
||||||
|
void Model::load_verteces(glm::vec3* verteces, GLuint count)
|
||||||
|
{
|
||||||
|
// Подключаем VAO и вершинный буфер
|
||||||
|
vao.use();
|
||||||
|
vertex_vbo.use();
|
||||||
|
|
||||||
|
// Загрузка вершин в память буфера
|
||||||
|
vertex_vbo.load(verteces, sizeof(glm::vec3)*count);
|
||||||
|
vertex_attrib_config();
|
||||||
|
// Запоминаем количество вершин для отрисовки
|
||||||
|
verteces_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузка индексов в буфер
|
||||||
|
void Model::load_indices(GLuint* indices, GLuint count)
|
||||||
|
{
|
||||||
|
// Подключаем VAO и индексный буфер
|
||||||
|
vao.use();
|
||||||
|
index_vbo.use();
|
||||||
|
|
||||||
|
// Загрузка вершин в память буфера
|
||||||
|
index_vbo.load(indices, sizeof(GLuint)*count);
|
||||||
|
// Запоминаем количество вершин для отрисовки
|
||||||
|
indices_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
// Матрица трансформации модели
|
||||||
|
glm::mat4 Model::getTransformMatrix()
|
||||||
|
{
|
||||||
|
glm::mat4 transformMatrix = glm::mat4(1.0f);
|
||||||
|
// Перемещение модели
|
||||||
|
transformMatrix = glm::translate(transformMatrix, position);
|
||||||
|
// Поворот модели
|
||||||
|
transformMatrix = glm::rotate(transformMatrix, glm::radians(rotation.x), glm::vec3(1.0, 0.0, 0.0));
|
||||||
|
transformMatrix = glm::rotate(transformMatrix, glm::radians(rotation.y), glm::vec3(0.0, 1.0, 0.0));
|
||||||
|
transformMatrix = glm::rotate(transformMatrix, glm::radians(rotation.z), glm::vec3(0.0, 0.0, 1.0));
|
||||||
|
// Масштабирование
|
||||||
|
transformMatrix = glm::scale(transformMatrix, scale);
|
||||||
|
|
||||||
|
return transformMatrix;
|
||||||
|
}
|
235
src/main.cpp
Normal file
235
src/main.cpp
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLM/glm.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Camera.h"
|
||||||
|
#include "Model.h"
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH 800
|
||||||
|
#define WINDOW_HEIGHT 600
|
||||||
|
#define WINDOW_CAPTION "OPENGL notes on rekovalev.site"
|
||||||
|
|
||||||
|
// Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// Функция чтения шейдера из файла
|
||||||
|
std::string readFile(const char* filename)
|
||||||
|
{
|
||||||
|
std::string text;
|
||||||
|
std::ifstream file(filename, std::ios::in); // Открываем файл на чтение
|
||||||
|
// Если файл доступен и успешно открыт
|
||||||
|
if (file.is_open())
|
||||||
|
{
|
||||||
|
std::stringstream sstr; // Буфер для чтения
|
||||||
|
sstr << file.rdbuf(); // Считываем файл
|
||||||
|
text = sstr.str(); // Преобразуем буфер к строке
|
||||||
|
file.close(); // Закрываем файл
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для загрузки шейдеров
|
||||||
|
// Принимает два адреса вершинного и фрагментного шейдеров
|
||||||
|
// Возвращает дескриптор шейдерной программы
|
||||||
|
GLuint LoadShaders(const char *vertex_file, const char *fragment_file)
|
||||||
|
{
|
||||||
|
// Создание дескрипторов вершинного и фрагментного шейдеров
|
||||||
|
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
// Переменные под результат компиляции
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
int infoLogLength;
|
||||||
|
|
||||||
|
// Считываем текст вершинного шейдера
|
||||||
|
std::string code = readFile(vertex_file);
|
||||||
|
const char* pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
|
||||||
|
|
||||||
|
// Компиляция кода вершинного шейдера
|
||||||
|
glShaderSource(vertexShaderID, 1, &pointer, NULL);
|
||||||
|
glCompileShader(vertexShaderID);
|
||||||
|
|
||||||
|
// Проверка результата компиляции
|
||||||
|
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result);
|
||||||
|
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
if (infoLogLength > 0)
|
||||||
|
{
|
||||||
|
char* errorMessage = new char[infoLogLength + 1];
|
||||||
|
glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, errorMessage);
|
||||||
|
std::cout << errorMessage;
|
||||||
|
delete errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Считываем текст вершинного шейдера
|
||||||
|
code = readFile(fragment_file);
|
||||||
|
pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
|
||||||
|
|
||||||
|
// Компиляция кода фрагментного шейдера
|
||||||
|
glShaderSource(fragmentShaderID, 1, &pointer, NULL);
|
||||||
|
glCompileShader(fragmentShaderID);
|
||||||
|
|
||||||
|
// Проверка результата компиляции
|
||||||
|
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result);
|
||||||
|
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
if (infoLogLength > 0)
|
||||||
|
{
|
||||||
|
char* errorMessage = new char[infoLogLength + 1];
|
||||||
|
glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, errorMessage);
|
||||||
|
std::cout << errorMessage;
|
||||||
|
delete errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Привязка скомпилированных шейдеров
|
||||||
|
GLuint programID = glCreateProgram();
|
||||||
|
glAttachShader(programID, vertexShaderID);
|
||||||
|
glAttachShader(programID, fragmentShaderID);
|
||||||
|
glLinkProgram(programID);
|
||||||
|
|
||||||
|
// Проверка программы
|
||||||
|
glGetProgramiv(programID, GL_LINK_STATUS, &result);
|
||||||
|
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
if (infoLogLength > 0)
|
||||||
|
{
|
||||||
|
char* errorMessage = new char[infoLogLength + 1];
|
||||||
|
glGetProgramInfoLog(programID, infoLogLength, NULL, errorMessage);
|
||||||
|
std::cout << errorMessage;
|
||||||
|
delete errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Освобождение дескрипторов шейдеров
|
||||||
|
glDeleteShader(vertexShaderID);
|
||||||
|
glDeleteShader(fragmentShaderID);
|
||||||
|
|
||||||
|
return programID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Camera camera(800.0f/600.0f);
|
||||||
|
|
||||||
|
bool firstMouse = true;
|
||||||
|
float lastX, lastY;
|
||||||
|
|
||||||
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
if (firstMouse)
|
||||||
|
{
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
firstMouse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 offset(xpos - lastX, lastY - ypos);
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
|
||||||
|
camera.rotate(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
GLFWwindow* window; // Указатель на окно GLFW3
|
||||||
|
|
||||||
|
// Инициализация GLFW3
|
||||||
|
if (!glfwInit())
|
||||||
|
{
|
||||||
|
std::cout << "GLFW init error\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Мажорная версия спецификаций OpenGL
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Минорная версия спецификаций OpenGL
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Контекст OpenGL, который поддерживает только основные функции
|
||||||
|
|
||||||
|
// Создание окна GLFW3 с заданными шириной, высотой и заголовком окна
|
||||||
|
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION, NULL, NULL);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
std::cout << "GLFW create window error\n";
|
||||||
|
glfwTerminate(); // Завершение работы с GLFW3 в случае ошибки
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Установка основного контекста окна
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
// Установка callback-функции для изменения размеров окна и буфера кадра
|
||||||
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
|
|
||||||
|
glfwSwapInterval(1); // Вертикальная синхронизация
|
||||||
|
|
||||||
|
// Установка callback-функции для мыши и камеры
|
||||||
|
glfwSetCursorPosCallback(window, mouse_callback);
|
||||||
|
|
||||||
|
// Загрузка функций OpenGL с помощью GLAD
|
||||||
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||||
|
{
|
||||||
|
std::cout << "GLAD load GL error\n";
|
||||||
|
glfwTerminate(); // Завершение работы с GLFW3 в случае ошибки
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Компиляция шейдеров
|
||||||
|
GLuint shaderProgram = LoadShaders("shaders/shader.vert", "shaders/shader.frag");
|
||||||
|
// Активация шейдера
|
||||||
|
glUseProgram(shaderProgram);
|
||||||
|
|
||||||
|
// Вершины прямоугольника
|
||||||
|
glm::vec3 verticies[] = { {-0.5f, -0.5f, 0.0f}
|
||||||
|
, { 0.5f, -0.5f, 0.0f}
|
||||||
|
, { 0.5f, 0.5f, 0.0f}
|
||||||
|
, {-0.5f, 0.5f, 0.0f}
|
||||||
|
};
|
||||||
|
// Модель прямоугольника
|
||||||
|
Model rectangle;
|
||||||
|
|
||||||
|
// Загрузка вершин модели
|
||||||
|
rectangle.load_verteces(verticies, sizeof(verticies)/sizeof(glm::vec3));
|
||||||
|
|
||||||
|
// индексы вершин
|
||||||
|
GLuint indices[] = {0, 1, 2, 2, 3, 0};
|
||||||
|
|
||||||
|
// Загрузка индексов модели
|
||||||
|
rectangle.load_indices(indices, sizeof(indices));
|
||||||
|
|
||||||
|
rectangle.position.z = 2;
|
||||||
|
rectangle.rotation = glm::vec3(45);
|
||||||
|
|
||||||
|
// Установка цвета очистки буфера цвета
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// Расположение Uniform-переменной
|
||||||
|
GLuint mvp_uniform = glGetUniformLocation(shaderProgram, "mvp");
|
||||||
|
|
||||||
|
// Пока не произойдет событие запроса закрытия окна
|
||||||
|
while(!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
// Очистка буфера цвета
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Тут производится рендер
|
||||||
|
rectangle.render(mvp_uniform);
|
||||||
|
|
||||||
|
// Представление содержимого буфера цепочки показа на окно
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
// Обработка системных событий
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаление шейдерной программы
|
||||||
|
glDeleteProgram(shaderProgram);
|
||||||
|
|
||||||
|
// Отключение атрибутов
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// Завершение работы с GLFW3 перед выходом
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user