Compare commits

..

1 Commits
v0.1 ... master

5 changed files with 194 additions and 116 deletions

30
include/Shader.h Normal file
View File

@ -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 &copy);
~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

View File

@ -20,7 +20,6 @@ class Texture
Texture& operator=(const Texture& other); // Оператор присваивания
static void init_textures(GLuint programID); // Инициализация текстур на шейдере
void use(); // Привязка текстуры
static void disable(GLuint type); // Отвязка текстуры по типу
GLuint getType(); // Возвращает тип текстуры

154
src/Shader.cpp Normal file
View File

@ -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 &copy) : 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);
}

View File

@ -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()
{

View File

@ -6,6 +6,7 @@
#include <iostream>
#include "Scene.h"
#include "Shader.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
@ -16,102 +17,6 @@ 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;
}
bool firstMouse = true;
float lastX, lastY;
@ -178,12 +83,15 @@ int main(void)
// Включаем проверку по буферу глубины
glEnable(GL_DEPTH_TEST);
// Компиляция шейдеров
GLuint shaderProgram = LoadShaders("shaders/shader.vert", "shaders/shader.frag");
// Активация шейдера
glUseProgram(shaderProgram);
// Базовый шейдер
ShaderProgram base;
// Загрузка и компиляция шейдеров
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 файла
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);
// Расположение Uniform-переменной
GLuint model_uniform = glGetUniformLocation(shaderProgram, "model");
GLuint model_uniform = base.getUniformLoc("model");
// Uniform-буферы
UBO cameraUB(sizeof(glm::mat4)*2, 0);
@ -217,9 +125,6 @@ int main(void)
// Обработка системных событий
glfwPollEvents();
}
// Удаление шейдерной программы
glDeleteProgram(shaderProgram);
return 0;
}