原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/79181818
《OpenGL学习笔记》系列博客目录地址:http://blog.csdn.net/qq21497936/article/category/7315532
OpenGL学习笔记(十一):封装自己的着色器类
前话
上一章节,进一步深入理解了着色器,从上章节,是不是发现着色的编写、编译、管理是件有点繁琐的事,所以本章节写一个类(纯C++),该类从硬盘读取着色器,然后编译并链接它们,并对它们进行错误检测,这使着色器就变得很好用了。
基础程序
使用之前qt平台上mingw编译器的Demo进行修改,本章节基础程序使用《OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形》完成的demo:
文章地址:http://blog.csdn.net/qq21497936/article/details/78888286
Demo下载:http://download.csdn.net/download/qq21497936/10171739
本章完成的Demo
Demo下载:http://download.csdn.net/download/qq21497936/10227234
编写自己的着色器类
先说明一下,着色器在简化(写成自己的类)后所使用的流程,非常简单:
... #include "hmfshader.h" ... int main() { ... // 实例化我们自己的着色器 HMFShader shader("./shaders/shader.vs", "./shaders/shader.fs"); ... while (!glfwWindowShouldClose(window)) { processInput(window); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // 使用实例化的着色器 shader.use(); glBindVertexArray(VAO); glViewport(0, 0, 600, 600); glDrawArrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return 0; }
下面贴上本人自己定义的基础版本的着色器类HMFShader
Hmfshader.h
#ifndef HMFSHADER_H #define HMFSHADER_H /**************************************************\ * 类名: HFMShader : HMF-红模仿 * 描述: 着色器类,目前可定义顶点着色器和片段着色器 * 函数: * HFMSHader() : 构造函数,传入顶点着色器文件地址和片段着色器地址 * use() : 使用该着色器实例 * setBool() : 设置一个name名称的uniform全局变量,bool类型 * setInt() : 设置一个name名称的uniform全局变量,int类型 * setFloat() : 设置一个name名称的uniform全局变量,float类型 * 作者: 红模仿 QQ: 21497936 博客地址:http://blog.csdn.net/qq21497936/ * 备注:作者提供各种技术相关服务,如开发、调试、IT集成服务等等 * 版本信息: 版本号 日期 描述 * v1.0 2018年1月27日 基础功能版本 \**************************************************/ #include <iostream> #include <glad/glad.h> class HMFShader { public: // 构造函数,读取并构建着色器 HMFShader(const GLchar * vertexPath, const GLchar* fragmentPath); // 使用/激活程序 void use(); // unifrom工具函数 void setBool(const std::string &name, bool value) const; void setInt(const std::string &name, int value) const; void setFloat(const std::string &name, float value) const; private: unsigned int _id; // 程序id }; #endif // HMFSHADER_H
Hmfshader.cpp
#include "hmfshader.h" #include <iostream> #include <fstream> #include <string> #include <sstream> HMFShader::HMFShader(const GLchar *vertexPath, const GLchar *fragmentPath) { std::string vertexCode; std::string fragmentCode; std::ifstream vShaderFile; std::ifstream fShaderFile; vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); if(!vShaderFile.is_open() && !fShaderFile.is_open()) { std::cout << "ERROR::HMFSHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } // 读取文件的缓冲到数据流中 std::stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // 关闭文件处理器 vShaderFile.close(); fShaderFile.close(); // 转换数据流到string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); // 代码置位const char const char * vShaderCode = vertexCode.c_str(); const char * fShaderCode = fragmentCode.c_str(); // 编译着色器 unsigned int vertex, fragment; int success; char infoLog[512]; // 顶点着色器 创建(标识),绑定(代码),编译(着色器),获取编译结果 vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); glCompileShader(vertex); glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); std::cout << "ERROR::HMFSHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } // 片段着色器 创建(标识),绑定(代码),编译(着色器),获取编译结果 fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); std::cout << "ERROR::HMFSHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } // 着色器程序 创建(表示),绑定(各着色器id),连接(全局连接到着色器程序标识上) _id = glCreateProgram(); glAttachShader(_id, vertex); glAttachShader(_id, fragment); glLinkProgram(_id); // 打印连接错误(如果有的话) glGetProgramiv(_id, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(_id, 512, NULL, infoLog); std::cout << "ERROR::HMFSHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } // 删除着色器,它们已经链接到我们的程序当中了,已经不再需要了 glDeleteShader(vertex); glDeleteShader(fragment); } void HMFShader::use() { // 使用着色器 glUseProgram(_id); } void HMFShader::setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(_id, name.c_str()), (int)value); } void HMFShader::setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(_id, name.c_str()), value); } void HMFShader::setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(_id, name.c_str()), value); }
贴上顶点着色器代码 shader.vs
#version 330 core layout (location = 0) in vec3 aPos; void main() { #if 0 // 上下颠倒(y颠倒) gl_Position = vec4(aPos.x, -aPos.y, aPos.z, 1.0); #else // 不做变换 gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); #endif }
片段着色器代码 shader.fs
#version 330 core out vec4 FragColor; void main() { #if 1 // 灰色 FragColor = vec4(0.5f, 0.5f, 0.5f, 1.0f); #else // 橘黄色 FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); #endif }
贴上我们的 main.cpp文件
/**************************************************\ * Demo: 定义自己的着色器类 * 描述: 着色器类使用demo * 作者: 红模仿 QQ: 21497936 博客地址:http://blog.csdn.net/qq21497936/ * 备注:作者提供各种技术相关服务,如开发、调试、IT集成服务等等 * 版本信息: 版本号 日期 描述 * v1.0 2018年1月27日 demo教程版本 \**************************************************/ #include <iostream> #include <process.h> #include <GLFW/glfw3.h> #include <glad/glad.h> #include "hmfshader.h" void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(800, 600, "QQ:21497936", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glViewport(0, 0, 600, 600); // 着色器实例化 HMFShader shader("./shaders/shader.vs", "./shaders/shader.fs"); float vertices[] = { -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.866f, 0.0f, }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { processInput(window); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // 使用zhu shader.use(); glBindVertexArray(VAO); glViewport(0, 0, 600, 600); glDrawArrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return 0; }
着色器使用总结
顶点着色器:创建(标识),绑定(代码),编译(着色器),获取编译结果
片段着色器:创建(标识),绑定(代码),编译(着色器),获取编译结果
着色器程序:创建(表示) ,绑定(各着色器id),连接(全局连接到着色器程序标识上),删除(释放使用的着色器内存)
着色器使用:使用该着色器id
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/79181818