Класс шейдерной программы
This commit is contained in:
		
							parent
							
								
									26fd1657fc
								
							
						
					
					
						commit
						1e9c74cf7a
					
				
							
								
								
									
										30
									
								
								include/Shader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/Shader.h
									
									
									
									
									
										Normal 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 ©); | ||||
|         ~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); // Оператор присваивания
 | ||||
| 
 | ||||
|         static void init_textures(GLuint programID); // Инициализация текстур на шейдере
 | ||||
|         void use(); // Привязка текстуры
 | ||||
|         static void disable(GLuint type); // Отвязка текстуры по типу
 | ||||
|         GLuint getType(); // Возвращает тип текстуры
 | ||||
|  | ||||
							
								
								
									
										154
									
								
								src/Shader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/Shader.cpp
									
									
									
									
									
										Normal 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 ©) : 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() | ||||
| { | ||||
|  | ||||
							
								
								
									
										115
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ | ||||
| #include "Camera.h" | ||||
| #include "Model.h" | ||||
| #include "Texture.h" | ||||
| #include "Shader.h" | ||||
| 
 | ||||
| #define WINDOW_WIDTH 800 | ||||
| #define WINDOW_HEIGHT 600 | ||||
| @ -19,102 +20,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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Camera camera(800.0f/600.0f); | ||||
|   | ||||
| bool firstMouse = true; | ||||
| @ -181,12 +86,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*)); | ||||
|     // camera.move({0,0,-20});
 | ||||
| 
 | ||||
|     // Загрузка сцены из obj файла
 | ||||
| @ -196,7 +104,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); | ||||
| @ -222,9 +130,6 @@ int main(void) | ||||
|         glfwPollEvents(); | ||||
|     } | ||||
| 
 | ||||
|     // Удаление шейдерной программы
 | ||||
|     glDeleteProgram(shaderProgram); | ||||
| 
 | ||||
|     // Отключение атрибутов
 | ||||
|     glDisableVertexAttribArray(0); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user