着色器类:
头文件 h:
#ifndef SHADER_H #define SHADER_H #include <GLAD/glad.h> #include <glfw3.h> #include <string> #include <fstream> #include <sstream> #include <iostream> class Shader { public: // 程序ID unsigned int ID; // 构造函数读取并构建着色器 Shader(const char* vertexPath,const char* fragmentPath); // 使用/激活程序 void use(); // uniform 工具函数 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; }; #endif // SHADER_H
源文件 cpp:
#include "Shader.h" Shader::Shader(const char *vertexPath, const char *fragmentPath) { // 1. 从文件路径中获取顶点/片段着色器 std::string vertexCode; std::string fragmentCode; std::ifstream vShaderFile; std::ifstream fShaderFile; // 保证ifstreamd对象可以抛出异常 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // 打开文件 vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); std::stringstream vShaderStream, fShaderStream; // 读取文件的缓冲内容到数据流中 vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // 关闭文件处理器 vShaderFile.close(); fShaderFile.close(); // 转换数据流到string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; } const char* vShaderCode = vertexCode.c_str(); const char* fShaderCode = fragmentCode.c_str(); // 顶点着色器对象 unsigned int vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); // 创建顶点着色器对象 glShaderSource(vertexShader,1,&vShaderCode,NULL); // 把顶点着色器源码附加到顶点着色器对象上 glCompileShader(vertexShader); // 编译顶点着色器对象 int success; // 检测顶点着色器对象编译是否成功 char infoLog[512]; glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success); if(!success) { glGetShaderInfoLog(vertexShader,512,NULL,infoLog); std::cout<<"Error::shader::vertex::compilation_failed\n"<<infoLog<<std::endl; } // 片段着色器对象 unsigned int fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // 创建片段着色器对象 glShaderSource(fragmentShader,1,&fShaderCode,NULL); // 把片段着色器源码附加到片段着色器对象上 glCompileShader(fragmentShader); // 编译片段着色器对象 glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&success); // 检查片段着色器对象是否编译成功 if(!success) { glGetShaderInfoLog(fragmentShader,512,NULL,infoLog); std::cout<<"Error::shader::vertex::compilation_failed\n"<<infoLog<<std::endl; } // 着色器程序对象 unsigned int shaderProgram; shaderProgram = glCreateProgram(); // 创建着色器程序对象 glAttachShader(shaderProgram,vertexShader); // 附加顶点着色器到着色器程序对象上 glAttachShader(shaderProgram,fragmentShader); // 附加片段着色器到着色器程序对象上 glLinkProgram(shaderProgram); // 链接着色器程序对象 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); // 检查着色器程序对象是否链接成功 if(!success) { glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); } ID = shaderProgram; // 把着色器对象链接到程序对象以后,删除着色器对象 glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } void Shader::use() { // 使用着色器程序对象 glUseProgram(ID); } void Shader::setBool(const std::string &name, bool value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), static_cast<int>(value)); } void Shader::setInt(const std::string &name, int value) const { glUniform1i(glGetUniformLocation(ID, name.c_str()), value); } void Shader::setFloat(const std::string &name, float value) const { glUniform1f(glGetUniformLocation(ID, name.c_str()), value); }
使用 main.cpp:
#include <iostream> #include <glad/glad.h> #include <glfw3.h> #include "Shader.h" using namespace std; // 回调函数,每当窗口改变大小,视口大小也跟随改变 void framebuffer_size_callback(GLFWwindow* window,int width,int height) { glViewport(0,0,width,height); } // 输入 在GLFW中实现一些输入控制 void processInput(GLFWwindow *window) { if(glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS) // 是否按下了返回键(Esc) { glfwSetWindowShouldClose(window,true); // 把WindowShouldClose属性设置为 true来关闭GLFW } } // ************** opengl 具体实现 ************ // 顶点数据 float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; //****************************************** int main() { cout << "你好三角形" << endl; // GLFW (窗口) glfwInit(); // 初始化GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3); // 主版本号 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3); // 次版本号 glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); // 使用核心模式 //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); Mac OS X系统 // 创建一个GLFW窗口对象 GLFWwindow* window = glfwCreateWindow(800,600,"triangle",NULL,NULL); if(window == NULL) { std::cout<< "Failed to create GLFW window"<<std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // 窗口的上下文设置为当前线程的主上下文 // GLAD if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) // 初始化GLAD(初始化OpenGL函数指针) { std::cout<<"Failed to initialize GLAD"<<std::endl; return -1; } //*********** opengl 具体实现 ****************** // 顶点数组对象 VAO unsigned int VAO; glGenVertexArrays(1,&VAO); // 创建顶点数组对象 glBindVertexArray(VAO); // 绑定顶点数组对象 // 顶点缓冲对象 VBO unsigned int VBO; glGenBuffers(1,&VBO); glBindBuffer(GL_ARRAY_BUFFER,VBO); // 绑定顶点缓冲对象 glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); // 把之前定义的顶点数据复制到缓冲的内存中 Shader shader("vertexSourceCode.vert", "fragmentSourceCode.frag"); // 链接顶点属性 (告诉 gpu 如何解析内存中的顶点数据) glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3 * sizeof(float),(void*)0); glEnableVertexAttribArray(0); //************************** // 视口 glViewport(0,0,800,600); // 视口跟随窗口大小改变 glfwSetFramebufferSizeCallback(window,framebuffer_size_callback); // 渲染循环 while(!glfwWindowShouldClose(window)) // 检查GLFW是否被要求退出 { // 输入 (用户) processInput(window); // 输入控制(自定义) //************** 渲染指令 (用户)********** glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); shader.use(); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES,0,3); //*************************************** // 检查并调用事件,交换缓冲 (默认操作) glfwSwapBuffers(window); // 交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。 glfwPollEvents(); // 有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态 } // 解绑 VAO VBO 着色器程序对象 glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // 当渲染循环结束后我们需要正确释放/删除之前的分配的所有资源 glfwTerminate(); return 0; }
着色器文件:
顶点着色器文件 vertexSourceCode.vert
#version 330 core layout (location = 0) in vec3 aPos; void main() { gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0); }
片段着色器文件 fragmentSourceCode.frag
#version 330 core out vec4 FragColor; void main() { FragColor = vec4(1.0f,0.5f,0.2f,1.0f); }
效果:
标签:std,const,OpenGL,void,Shader,value,shaders,include,着色器 From: https://www.cnblogs.com/RedWetPlace/p/18116088