OpenGL之绘制矩形使用索引和glUniform4f

发布时间 2023-08-05 11:20:43作者: 三岁玩童

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 };
View Code

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 } 
View Code

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 }
View Code

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 }
View Code