Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Ковалев Роман Евгеньевич | 44d767bdfe |
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef SHADER_H
|
||||||
|
#define SHADER_H
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Класс шейдерной программы
|
||||||
|
class ShaderProgram
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderProgram();
|
||||||
|
ShaderProgram(const ShaderProgram ©);
|
||||||
|
~ShaderProgram();
|
||||||
|
ShaderProgram& operator=(const ShaderProgram& other);
|
||||||
|
|
||||||
|
void use(); // Использование шейдеров
|
||||||
|
void load(GLuint type, const char* filename); // Функция для загрузки шейдеров
|
||||||
|
void link(); // Формирование программы из загруженных шейдеров
|
||||||
|
GLuint getUniformLoc(const char* name); // Возвращает местоположение uniform-переменной
|
||||||
|
void bindUniformBlock(const char* name, int binding); // Привязка uniform-блока
|
||||||
|
void bindTextures(const char* textures_base_shader_names[], int count); // Инициализация текстур на шейдере
|
||||||
|
private:
|
||||||
|
GLuint program; // Дескриптор
|
||||||
|
static std::map<int, int> handler_count; // Получение количества использований по дескриптору шейдера (Shared pointer)
|
||||||
|
std::map<const char*, GLuint> uniformLocations; // Местоположения uniform-переменных
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHADER_H
|
|
@ -20,7 +20,6 @@ class Texture
|
||||||
|
|
||||||
Texture& operator=(const Texture& other); // Оператор присваивания
|
Texture& operator=(const Texture& other); // Оператор присваивания
|
||||||
|
|
||||||
static void init_textures(GLuint programID); // Инициализация текстур на шейдере
|
|
||||||
void use(); // Привязка текстуры
|
void use(); // Привязка текстуры
|
||||||
static void disable(GLuint type); // Отвязка текстуры по типу
|
static void disable(GLuint type); // Отвязка текстуры по типу
|
||||||
GLuint getType(); // Возвращает тип текстуры
|
GLuint getType(); // Возвращает тип текстуры
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
std::map<int, int> ShaderProgram::handler_count; // Получение количества использований по дескриптору ШП (Shared pointer)
|
||||||
|
|
||||||
|
ShaderProgram::ShaderProgram()
|
||||||
|
{
|
||||||
|
program = glCreateProgram();
|
||||||
|
handler_count[program] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderProgram::ShaderProgram(const ShaderProgram ©) : program(copy.program)
|
||||||
|
{
|
||||||
|
handler_count[program]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderProgram::~ShaderProgram()
|
||||||
|
{
|
||||||
|
if (!--handler_count[program]) // Если количество ссылок = 0
|
||||||
|
{
|
||||||
|
// Удаление шейдерной программы
|
||||||
|
glDeleteProgram(program);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Оператор присваивания
|
||||||
|
ShaderProgram& ShaderProgram::operator=(const ShaderProgram& other)
|
||||||
|
{
|
||||||
|
// Если это разные шейдерные программы
|
||||||
|
if (program != other.program)
|
||||||
|
{
|
||||||
|
this->~ShaderProgram(); // Уничтожаем имеющуюся
|
||||||
|
// Заменяем новой
|
||||||
|
program = other.program;
|
||||||
|
handler_count[program]++;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Использование шейдеров
|
||||||
|
void ShaderProgram::use()
|
||||||
|
{
|
||||||
|
glUseProgram(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция чтения шейдера из файла
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для загрузки шейдеров
|
||||||
|
void ShaderProgram::load(GLuint type, const char* filename)
|
||||||
|
{
|
||||||
|
// Создание дескрипторов шейдера
|
||||||
|
GLuint handler = glCreateShader(type);
|
||||||
|
|
||||||
|
// Переменные под результат компиляции
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
int infoLogLength;
|
||||||
|
|
||||||
|
// Считываем текст вершинного шейдера
|
||||||
|
std::string code = readFile(filename);
|
||||||
|
const char* pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
|
||||||
|
|
||||||
|
// Компиляция кода вершинного шейдера
|
||||||
|
glShaderSource(handler, 1, &pointer, NULL);
|
||||||
|
glCompileShader(handler);
|
||||||
|
|
||||||
|
// Проверка результата компиляции
|
||||||
|
glGetShaderiv(handler, GL_COMPILE_STATUS, &result);
|
||||||
|
glGetShaderiv(handler, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
if (infoLogLength > 0)
|
||||||
|
{
|
||||||
|
char* errorMessage = new char[infoLogLength + 1];
|
||||||
|
glGetShaderInfoLog(handler, infoLogLength, NULL, errorMessage);
|
||||||
|
std::cout << errorMessage;
|
||||||
|
delete[] errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Привязка скомпилированного шейдера
|
||||||
|
glAttachShader(program, handler);
|
||||||
|
|
||||||
|
// Освобождение дескриптора шейдера
|
||||||
|
glDeleteShader(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Формирование программы из загруженных шейдеров
|
||||||
|
void ShaderProgram::link()
|
||||||
|
{
|
||||||
|
// Переменные под результат компиляции
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
int infoLogLength;
|
||||||
|
|
||||||
|
// Формирование программы из привязанных шейдеров
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
// Проверка программы
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &result);
|
||||||
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||||
|
if (infoLogLength > 0)
|
||||||
|
{
|
||||||
|
char* errorMessage = new char[infoLogLength + 1];
|
||||||
|
glGetProgramInfoLog(program, infoLogLength, NULL, errorMessage);
|
||||||
|
std::cout << errorMessage;
|
||||||
|
delete[] errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Используем шейдерную программу объекта из которого вызван метод
|
||||||
|
this->use();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращает местоположение uniform-переменной
|
||||||
|
GLuint ShaderProgram::getUniformLoc(const char* name)
|
||||||
|
{
|
||||||
|
GLuint result; // Результат
|
||||||
|
// Если такую переменную ещё не искали - найдем, иначе вернем уже известный дескриптор
|
||||||
|
if (!uniformLocations.count(name))
|
||||||
|
uniformLocations[name] = result = glGetUniformLocation(program, name);
|
||||||
|
else
|
||||||
|
result = uniformLocations[name];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Привязка uniform-блока
|
||||||
|
void ShaderProgram::bindUniformBlock(const char* name, int binding)
|
||||||
|
{
|
||||||
|
glUniformBlockBinding( program
|
||||||
|
, glGetUniformBlockIndex(program, name)
|
||||||
|
, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация текстур на шейдере
|
||||||
|
void ShaderProgram::bindTextures(const char* textures_base_shader_names[], int count)
|
||||||
|
{
|
||||||
|
// Цикл по всем доступным текстурам
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
glUniform1i(getUniformLoc(textures_base_shader_names[i]), i);
|
||||||
|
}
|
|
@ -98,16 +98,6 @@ Texture::~Texture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* textures_base_shader_names[] = {"tex_diffuse"};
|
|
||||||
|
|
||||||
// Инициализация текстур на шейдере
|
|
||||||
void Texture::init_textures(GLuint programID)
|
|
||||||
{
|
|
||||||
// Цикл по всем доступным текстурам
|
|
||||||
for (int i = 0; i < TEX_AVAILABLE_COUNT; i++)
|
|
||||||
glUniform1i(glGetUniformLocation(programID, textures_base_shader_names[i]), i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Привязка текстуры
|
// Привязка текстуры
|
||||||
void Texture::use()
|
void Texture::use()
|
||||||
{
|
{
|
||||||
|
|
115
src/main.cpp
115
src/main.cpp
|
@ -6,6 +6,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
|
#include "Shader.h"
|
||||||
|
|
||||||
#define WINDOW_WIDTH 800
|
#define WINDOW_WIDTH 800
|
||||||
#define WINDOW_HEIGHT 600
|
#define WINDOW_HEIGHT 600
|
||||||
|
@ -16,102 +17,6 @@ void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
{
|
{
|
||||||
glViewport(0, 0, width, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool firstMouse = true;
|
bool firstMouse = true;
|
||||||
float lastX, lastY;
|
float lastX, lastY;
|
||||||
|
@ -178,12 +83,15 @@ int main(void)
|
||||||
// Включаем проверку по буферу глубины
|
// Включаем проверку по буферу глубины
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
// Компиляция шейдеров
|
// Базовый шейдер
|
||||||
GLuint shaderProgram = LoadShaders("shaders/shader.vert", "shaders/shader.frag");
|
ShaderProgram base;
|
||||||
// Активация шейдера
|
// Загрузка и компиляция шейдеров
|
||||||
glUseProgram(shaderProgram);
|
base.load(GL_VERTEX_SHADER, "shaders/shader.vert");
|
||||||
|
base.load(GL_FRAGMENT_SHADER, "shaders/shader.frag");
|
||||||
|
base.link();
|
||||||
// Установим значения текстур
|
// Установим значения текстур
|
||||||
Texture::init_textures(shaderProgram);
|
const char* textures_base_shader_names[] = {"tex_diffuse"};
|
||||||
|
base.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*));
|
||||||
|
|
||||||
// Загрузка сцены из obj файла
|
// Загрузка сцены из obj файла
|
||||||
Scene scene = loadOBJtoScene("../resources/models/cubes.obj", "../resources/models/", "../resources/textures/");
|
Scene scene = loadOBJtoScene("../resources/models/cubes.obj", "../resources/models/", "../resources/textures/");
|
||||||
|
@ -192,7 +100,7 @@ int main(void)
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
// Расположение Uniform-переменной
|
// Расположение Uniform-переменной
|
||||||
GLuint model_uniform = glGetUniformLocation(shaderProgram, "model");
|
GLuint model_uniform = base.getUniformLoc("model");
|
||||||
|
|
||||||
// Uniform-буферы
|
// Uniform-буферы
|
||||||
UBO cameraUB(sizeof(glm::mat4)*2, 0);
|
UBO cameraUB(sizeof(glm::mat4)*2, 0);
|
||||||
|
@ -217,9 +125,6 @@ int main(void)
|
||||||
// Обработка системных событий
|
// Обработка системных событий
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Удаление шейдерной программы
|
|
||||||
glDeleteProgram(shaderProgram);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue