本文共 7164 字,大约阅读时间需要 23 分钟。
声明
#pragma once#includeclass Shaders{ public: Shaders(const char* vertexPath, const char* fragmentPath); ~Shaders(); std::string vertexString; std::string fragmentString; const char* vertexSource; const char* fragmentSource; unsigned int ID; // shaderProgram 的id void use();private: void checkCompileErrors(unsigned int id, std::string type);};
源文件
#include "Shaders.h"#include#include #include #define GLEW_STATIC // 这个一定要加不然报错 静态链接库#include #include Shaders::Shaders(const char* vertexPath, const char* fragmentPath ) { std::ifstream vertexFile; std::ifstream fragmentFile; std::stringstream vertexSStream; std::stringstream fragmentSStream; vertexFile.open(vertexPath); fragmentFile.open(fragmentPath); vertexFile.exceptions(std::ifstream::failbit || std::ifstream::badbit); fragmentFile.exceptions(std::ifstream::failbit || std::ifstream::badbit); try { if (!vertexFile.is_open() || !fragmentFile.is_open()) { throw std::exception("open file error"); } // 将 输入流的内容输出给 stringstream vertexSStream << vertexFile.rdbuf(); fragmentSStream << fragmentFile.rdbuf(); vertexString = vertexSStream.str(); fragmentString = fragmentSStream.str(); vertexSource = vertexString.c_str(); fragmentSource = fragmentString.c_str(); unsigned int vertex, fragment; // 创建这个着色器 vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vertexSource, NULL); // 编译 glCompileShader(vertex); checkCompileErrors(vertex, "VERTEX"); fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fragmentSource, NULL); // 编译 glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); //创建一个着色器程序对象 ID = glCreateProgram(); // 将之前编译的着色器附加到程序对象上 glAttachShader(ID, vertex); glAttachShader(ID, fragment); // 用glLinkProgram链接它们 glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); //删除着色器 glDeleteShader(vertex); glDeleteShader(fragment); } catch (const std::exception& ex) { std::cout << ex.what() << std::endl; }}void Shaders::use() { glUseProgram(ID);}void Shaders::checkCompileErrors(unsigned int id, std::string type) { int success; char infoLog[512]; if (type != "PROGRAM") { glGetShaderiv(id, GL_COMPILE_STATUS,&success); if (!success) { glGetShaderInfoLog(id, 512, NULL, infoLog); std::cout << "shader compile error:" << infoLog << std::endl; } } else { glGetProgramiv(id, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(id, 512, NULL, infoLog); std::cout << "program compile error:" << infoLog << std::endl; } }}Shaders::~Shaders() { }
#define GLEW_STATIC // 这个一定要加不然报错 静态链接库#include#include #include #include "Shaders.h"using namespace std;void processInput(GLFWwindow);void processInput(GLFWwindow* window) { //如果键盘输入esc 则触发 退出 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { // 设置 要求退出 glfwSetWindowShouldClose(window, true); }}// 逆时针方向绘制 默认情况下,逆时针的顶点连接顺序被定义为三角形的正// 逆时针或顺时针都是相对于观察者方向的float vertices[] { -0.5f, 0.5f, 0.0f, 1.0f, 0,0, // 左上角 0 0.5f, -0.5f, 0.0f, 0,1.0f,0, // 右下角 1 0.5f, 0.5f, 0.0f, 0,0,1.0f, // 右上角 2 // 第二个三角形 //0.5f, -0.5f, 0.0f, // 右下角 -0.5f, -0.5f, 0.0f , 1.0f,0,1.0f // 左下角 3 //-0.5f, 0.5f, 0.0f // 左上角};// 使用索引来减小画点的开销 (未用索引缓冲对象时,每个点都需要画一次(即使重复了))unsigned int indices[] { 0,1,2, //第一个三角形的索引 1,3,0 //第二个三角形的索引};int main() { // 初始化GLFW glfwInit(); // 提示 我们使用的版本是3.3 // 主版本 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, "Test window", NULL, NULL); if (window == NULL) { cout << "open window failed." << endl; // 终止 glfw glfwTerminate(); } // 绑定window到上下文对象 创建完窗口我们就可以通知GLFW将我们窗口的上下文设置为当前线程的主上下文了 glfwMakeContextCurrent(window); glewExperimental = true; // GLEW_OK 0 //init GLEW if (glewInit() != GLEW_OK) { cout << "glew init failed." << endl; // 终止 glfw glfwTerminate(); return -1; } // OpenGL渲染窗口的尺寸大小 // glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素) glViewport(0, 0, 800, 600); // 设置剔除 (opegl默认正面背面都显示(不剔除)) //glEnable(GL_CULL_FACE); // 剔除背面 GL_BACK 剔除正面 GL_FRONT //glCullFace(GL_BACK); // 线框模式 //第一个参数表示我们打算将其应用到所有的三角形的正面和背面,第二个参数告诉我们用线来绘制 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //VAO对象 unsigned int VAO; // 生成一个VAO对象 这个方法可以生成多个 由第一个参数决定 glGenVertexArrays(1, &VAO); // 绑定 VAO glBindVertexArray(VAO); unsigned int VBO; //如果多个可以用 VBO[]数组 这个方法可以生成多个 由第一个参数决定 glGenBuffers(1, &VBO); //将新创建的缓冲绑定到 GL_ARRAY_BUFFER目标上 glBindBuffer(GL_ARRAY_BUFFER, VBO); // glBufferData 是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数 // GL_STATIC_DRAW 数据不会或几乎不会改变。 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); Shaders* shaders = new Shaders("./vertexSource.txt", "./fragmentSource.txt"); // glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上) // 从 0号栏位 开始 将数据每三个为一组 单位为float 每次跳6*float字节 偏移为0 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // 以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的 //读取到0号栏位上 glEnableVertexAttribArray(0); // 读取颜色属性 从 1号栏位 开始 将数据每三个为一组 单位为float 每次跳6*float字节 偏移为3个float glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float))); // 读取到1号栏位上 glEnableVertexAttribArray(1); //渲染循环 ,它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环: //glfwWindowShouldClose 我们每次循环的开始前检查一次GLFW是否被要求退出 while (!glfwWindowShouldClose(window)) { //自定义事件 当键盘触发esc 退出 processInput(window); glClearColor(0.2, 0.3, 0.3, 1.0); // GL_COLOR_BUFFER_BIT 颜色,GL_DEPTH_BUFFER_BIT 深度 和 GL_STENCIL_BUFFER_BIT 模板 // 清除前面的那一帧的颜色 glClear(GL_COLOR_BUFFER_BIT); // 绑定 VAO glBindVertexArray(VAO); shaders->use(); // 画三角形 从0开始 绘制三个顶点 和VBO的顶点数据(通过VAO间接绑定)来绘制图元 //glDrawArrays(GL_TRIANGLES, 0, 6); 这个是不用索引画的 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//可以不需要这个 绑定VAO的同时也会自动绑定EBO //glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取索引 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //解绑VAO glBindVertexArray(0); glfwSwapBuffers(window); glfwPollEvents(); } // 最后终止 glfw glfwTerminate(); return 0;}
#version 330 core // 0号栏位读取顶点坐标layout (location = 0) in vec3 aPos; //1号栏位读取颜色颜色layout (location = 1) in vec3 aColor; out vec4 vertexColor; void main() { // gl_Position 是固定的名称 用来保存 顶点坐标的 gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); vertexColor = vec4(aColor.x+0.5,aColor.y,aColor.z,1.0);}
#version 330 core out vec4 FragColor; //uniform vec4 outColor; in vec4 vertexColor; void main() { FragColor = vertexColor; }
转载地址:http://euro.baihongyu.com/