OpenGL之绘制矩形使用索引和glUniform4f
glUniform更改一个uniform变量或数组的值。要更改的uniform变量的位置由location指定,location的值应该由glGetUniformLocation函数返回。通过调用glUseProgram,glUniform操作的程序对象将成为当前状态的一部分。
glUniform{1|2|3|4}{f|i}使用传进来的实参,修改通过location指定的uniform变量。
所有在程序对象中定义的活动uniform变量,在程序对象链接成功后都会被初始化为0.直到下一次程序对象链接成功再一次被初始化为0前,它们将保留通过调用glUniform赋给它们的值。
glUniform{1|2|3|4}{f|i}v可以用来更改单个uniform变量的值,或者一个uniform变量数组。
glUniformMatrix{2|3|4}fv用来更改一个矩阵或一个矩阵数组。
1.Shader.h
1 #pragma once 2 3 #include<string> 4 #include<fstream> 5 #include<sstream> 6 #include<iostream> 7 using namespace std; 8 9 // 我们自己的着色器 10 class Shader 11 { 12 private: 13 GLuint vertex, fragment; // 顶点着色器 和 片元着色器 14 public: 15 GLuint Program; // 着色器程序的ID 16 17 // Constructor(着色器构造函数) 18 Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 19 { 20 // 文件读取系列的变量定义 21 string vertexCode; 22 string fragmentCode; 23 ifstream vShaderFile; 24 ifstream fShaderFile; 25 26 // 异常机制处理:保证ifstream对象可以抛出异常: 27 vShaderFile.exceptions(ifstream::badbit); 28 fShaderFile.exceptions(ifstream::badbit); 29 30 try 31 { 32 // 打开文件 33 vShaderFile.open(vertexPath); 34 fShaderFile.open(fragmentPath); 35 stringstream vShaderStream, fShaderStream; 36 37 // 读取文件的缓冲内容到数据流中 38 vShaderStream << vShaderFile.rdbuf(); 39 fShaderStream << fShaderFile.rdbuf(); 40 41 // 关闭文件处理器 42 vShaderFile.close(); 43 fShaderFile.close(); 44 45 // 转换数据流到string 46 vertexCode = vShaderStream.str(); 47 fragmentCode = fShaderStream.str(); 48 49 } 50 catch (ifstream::failure e) { // 发生异常时输出 51 cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl; 52 } 53 54 /* 将 string 类型的字符串转化为 char数组 类型 */ 55 const GLchar* vShaderCode = vertexCode.c_str(); 56 const GLchar* fShaderCode = fragmentCode.c_str(); 57 58 /* 顶点着色器 */ 59 vertex = glCreateShader(GL_VERTEX_SHADER); // 创建顶点着色器对象 60 glShaderSource(vertex, 1, &vShaderCode, NULL); // 将顶点着色器的内容传进来 61 glCompileShader(vertex); // 编译顶点着色器 62 GLint flag; // 用于判断编译是否成功 63 GLchar infoLog[512]; 64 glGetShaderiv(vertex, GL_COMPILE_STATUS, &flag); // 获取编译状态 65 if (!flag) 66 { 67 glGetShaderInfoLog(vertex, 512, NULL, infoLog); 68 cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl; 69 } 70 71 /* 片元着色器 */ 72 fragment = glCreateShader(GL_FRAGMENT_SHADER); // 创建片元着色器对象 73 glShaderSource(fragment, 1, &fShaderCode, NULL); // 将片元着色器的内容传进来 74 glCompileShader(fragment); // 编译顶点着色器 75 glGetShaderiv(fragment, GL_COMPILE_STATUS, &flag); // 获取编译状态 76 if (!flag) 77 { 78 glGetShaderInfoLog(fragment, 512, NULL, infoLog); 79 cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl; 80 } 81 82 /* 着色器程序 */ 83 this->Program = glCreateProgram(); 84 glAttachShader(this->Program, vertex); 85 glAttachShader(this->Program, fragment); 86 glLinkProgram(this->Program); 87 if (!flag) 88 { 89 glGetProgramInfoLog(this->Program, 512, NULL, infoLog); 90 cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl; 91 } 92 // 删除着色器,它们已经链接到我们的程序中了,已经不再需要了 93 glDeleteShader(vertex); 94 glDeleteShader(fragment); 95 } 96 97 // Deconstructor(析构函数) 98 ~Shader() 99 { 100 glDetachShader(this->Program, vertex); 101 glDetachShader(this->Program, fragment); 102 glDeleteShader(vertex); 103 glDeleteShader(fragment); 104 glDeleteProgram(this->Program); 105 } 106 107 void Use() 108 { 109 glUseProgram(this->Program); 110 } 111 };
2.shader_rect_v.txt
1 #version 330 core // 3.30版本 2 layout(location = 0) in vec3 position; // 位置变量的属性位置值为0 3 void main() 4 { 5 gl_Position = vec4(position, 1.0f); // 核心函数(位置信息赋值) 6 }
3.shader_rect_f.txt
1 #version 330 core // 3.30版本 2 out vec4 FragColor; // 输出是四个浮点数构成的一个向量 RGB+aerfa 3 uniform vec4 time; // 在OpenGL程序代码中设定这个变量(uniform:实时地变量表示) 4 void main() 5 { 6 FragColor = time; // 颜色随时间变化 7 }
4.DrawRectUseIndice.cpp
1 /* 引入相应的库 */ 2 #include <iostream> 3 using namespace std; 4 5 #define GLEW_STATIC 6 #include <GL/glew.h> 7 #include <GLFW/glfw3.h> 8 9 #include"Shader.h" 10 11 /* 编写各顶点位置 */ 12 GLfloat vertices_1[] = 13 { 14 //position 15 0.5f, 0.5f, 0.0f, // top right 0 16 0.5f, -0.5f, 0.0f, // bottom right 1 17 -0.5f, -0.5f, 0.0f, // bottom left 2 18 -0.5f, 0.5f, 0.0f, // top left 3 19 }; 20 21 /* 四个顶点的连接信息给出来 */ 22 GLuint indices_1[] = 23 { 24 0, 1, 3, // 序号为 0、1、3 的顶点组合成一个三角形 25 1, 2, 3 // 序号为 1、2、3 的顶点组合成一个三角形 26 }; 27 28 const GLint WIDTH = 600, HEIGHT = 600; // 正方形窗口 29 30 int main() 31 { 32 glfwInit(); 33 GLFWwindow* window_1 = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL Triangle test", nullptr, nullptr); 34 int screenWidth_1, screenHeight_1; 35 glfwGetFramebufferSize(window_1, &screenWidth_1, &screenHeight_1); 36 glfwMakeContextCurrent(window_1); 37 glewInit(); 38 39 /* 将我们自己设置的着色器文本传进来 */ 40 Shader ourShader = Shader("shader_rect_v.txt", "shader_rect_f.txt"); // 相对路径 41 42 /* 设置顶点缓冲对象(VBO) + 设置顶点数组对象(VAO) */ 43 GLuint VAO, VBO; 44 glGenVertexArrays(1, &VAO); 45 glGenBuffers(1, &VBO); 46 glBindVertexArray(VAO); 47 glBindBuffer(GL_ARRAY_BUFFER, VBO); 48 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW); 49 50 /* 设置链接顶点属性 */ 51 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); 52 glEnableVertexAttribArray(0); // 通道 0 打开 53 54 /* 设置索引缓冲对象 */ 55 GLuint EBO; 56 glGenBuffers(1, &EBO); 57 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 58 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_1), indices_1, GL_STATIC_DRAW); 59 60 // draw loop 画图循环 61 while (!glfwWindowShouldClose(window_1)) 62 { 63 // 视口 + 时间 64 glViewport(0, 0, screenWidth_1, screenHeight_1); 65 glfwPollEvents(); 66 67 // 渲染 + 清除颜色缓冲 68 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 69 glClear(GL_COLOR_BUFFER_BIT); 70 71 /* 绘制图形 */ 72 ourShader.Use(); 73 float time = glfwGetTime(); // 获取时间 74 float redValue = sin(time) / 2.0f + 0.5f; // 红色数值计算,范围[0,1] 75 float greenValue = 1 - redValue; // 绿色数值计算,范围[0.1]。且满足 “redValue + greenValue = 1” 76 int vertexColorLocation = glGetUniformLocation(ourShader.Program, "time"); 77 glUniform4f(vertexColorLocation, redValue, greenValue, 0.0f, 1.0f); 78 79 glBindVertexArray(VAO); // 绑定 VAO 80 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // 绑定 EBO 81 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // 画两个三角形 从第0个顶点开始 一共画6次 82 glBindVertexArray(0); // 解绑定 VAO 83 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // 解绑定 EBO 84 85 // 交换缓冲 86 glfwSwapBuffers(window_1); 87 } 88 89 glDeleteVertexArrays(1, &VAO); // 释放资源 90 glDeleteBuffers(1, &VBO); 91 glDeleteBuffers(1, &EBO); 92 glfwTerminate(); // 结束 93 return 0; 94 }