首页 > 其他分享 >OpenGL之绘制三角形使用顶点颜色

OpenGL之绘制三角形使用顶点颜色

时间:2023-08-05 10:56:01浏览次数:38  
标签:VAO OpenGL 0.0 VBO Program 顶点 GL 绘制

 ● VBO、VAO 与 EBO 之间的联系与区别: ⭐️ ⭐️
  ① 顶点缓冲对象 VBO 是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标、顶点法向量、顶点颜色数据等。在渲染时,可以直接从 VBO 中取出顶点的各类属性数据,由于 VBO 在显存而不是在内存中,不需要从CPU传输数据,所以处理效率更高。
   所以可以理解为 VBO 就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个 VBO ,每个 VBO 在 OpenGL 中有它的唯一标识 ID ,这个 ID 对应着具体的 VBO 的显存地址,通过这个 ID 可以对特定的 VBO 内的数据进行存取操作。

  ② VAO 是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的 VBO 对象的引用。
   因为 VBO 保存了一个模型的顶点属性信息,每次绘制模型之前需要绑定顶点的所有信息。当数据量很大时,重复这样的动作变得非常麻烦。VAO 可以把这些所有的配置都存储在一个对象中,每次绘制模型时,只需要绑定这个 VAO 对象就可以了。
   另外,VAO 本身并没有存储顶点的相关属性数据,这些信息是存储在 VBO 中的,VAO 相当于是对很多个 VBO 的引用,把一些 VBO 组合在一起作为一个对象统一管理。

  ③ 索引缓冲对象 EBO 相当于 OpenGL 中的顶点数组的概念,是为了解决同一个顶点多次重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。
   EBO 中存储的内容就是顶点位置的索引 indices,EBO 跟 VBO 类似,也是在显存中的一块内存缓冲器,只不过 EBO 保存的是顶点的索引。

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_f.txt

1 // 文件名为 “shader_f.txt”
2 #version 330 core        // 3.30版本
3 in vec3 ourColor;        // 输入(3维)颜色向量
4 out vec4 FragColor;     // 输出到四个浮点数构成的一个(4维)向量 FragColor
5 void main()
6 {
7     FragColor = vec4(ourColor, 1.0f);    // 核心函数(颜色信息赋值)
8 }
View Code

3.shader_v.txt

 1 // 文件名为 “shader_v.txt”
 2 #version 330 core                            // 3.30版本
 3 layout(location = 0) in vec3 position;        // 位置变量的属性位置值为0
 4 layout(location = 1) in vec3 color;            // 颜色变量的属性位置值为1
 5 out vec3 ourColor;                            // 颜色输出
 6 void main()
 7 {
 8     gl_Position = vec4(position, 1.0f);        // 核心函数(位置信息赋值)
 9     ourColor = color;
10 } 
View Code

4.DrawTriangleUseVColor.cpp

 1 /* 引入相应的库 */
 2 #include <iostream>
 3 using namespace std;
 4 
 5 #define GLEW_STATIC    
 6 
 7 #include <GL/glew.h>    
 8 #include <GLFW/glfw3.h> 
 9 #include "Shader.h"
10 
11 /* 编写各顶点位置与颜色 */
12 GLfloat vertices_1[] =
13 {    
14      // position            // color
15      0.0f,  0.5f, 0.0f,        1.0f, 0.0f, 0.0f,        // 上顶点(红色)
16     -0.5f, -0.5f, 0.0f,        0.0f, 1.0f, 0.0f,        // 左顶点(绿色)
17      0.5f, -0.5f, 0.0f,        0.0f, 0.0f, 1.0f        // 右顶点(蓝色)
18 };
19 
20 const GLint WIDTH = 800, HEIGHT = 600;                // 窗口的长和宽
21 
22 int main()
23 {
24     /* 初始化 */
25     glfwInit();
26     GLFWwindow* window_1 = glfwCreateWindow(WIDTH, HEIGHT, "A Beautiful Triangle", nullptr, nullptr);
27     int screenWidth_1, screenHeight_1;
28     glfwGetFramebufferSize(window_1, &screenWidth_1, &screenHeight_1);
29     glfwMakeContextCurrent(window_1);
30     glewInit();
31 
32     /* 将我们自己设置的着色器文本传进来 */
33     Shader ourShader = Shader("shader_v.txt", "shader_f.txt");    // 相对路径
34 
35     /* 设置顶点缓冲对象(VBO) + 设置顶点数组对象(VAO)  */
36     GLuint VAO, VBO;
37     glGenVertexArrays(1, &VAO);
38     glGenBuffers     (1, &VBO);
39     glBindVertexArray(VAO);
40     glBindBuffer     (GL_ARRAY_BUFFER, VBO);
41     glBufferData     (GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW);
42 
43     /* 设置链接顶点属性 */
44     glVertexAttribPointer    (0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
45     glEnableVertexAttribArray(0);    // 通道 0 打开
46     glVertexAttribPointer    (1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
47     glEnableVertexAttribArray(1);    // 通道 1 打开
48 
49     // draw loop 画图循环
50     while (!glfwWindowShouldClose(window_1))
51     {
52         glViewport    (0, 0, screenWidth_1, screenHeight_1);
53         glfwPollEvents();
54         glClearColor  (0.0f, 0.0f, 0.0f, 1.0f);
55         glClear       (GL_COLOR_BUFFER_BIT);
56 
57         /*  第九步:绘制三角形 */
58         ourShader.Use();                    // 图形渲染
59         glBindVertexArray(VAO);                // 绑定 VAO
60         glDrawArrays(GL_TRIANGLES, 0, 3);    // 画三角形  从第0个顶点开始 一共画3次
61         glBindVertexArray(0);                // 解绑定
62 
63         glfwSwapBuffers(window_1);
64     }
65 
66     glDeleteVertexArrays(1, &VAO);            // 释放资源    
67     glDeleteBuffers(1, &VBO);
68     glfwTerminate();                        // 结束
69     return 0;
70 }
View Code

 

标签:VAO,OpenGL,0.0,VBO,Program,顶点,GL,绘制
From: https://www.cnblogs.com/sansuiwantong/p/17607627.html

相关文章

  • Matplotlib学习挑战第五关--绘制多图subplot() 和 subplots()
    Matplotlib绘制多图我们可以使用pyplot中的subplot()和subplots()方法来绘制多个子图。subplot()方法在绘图时需要指定位置,subplots()方法可以一次生成多个,在调用时只需要调用生成对象的ax即可。1、subplotsubplot(nrows,ncols,index,**kwargs)subplot(pos,**kwar......
  • Openlayers 距离环绘制
    思路:利用layer的StyleFunction来使地图移动或者放缩的时候,使圆保持在地图中心/***绘制距离环*@param{number}distance每环间隔距离,单位:米*@param{array}texts要显示的内容*@description创建了个layer,然后在layer的styleFunction中做了配置,这里搞了6个环,每两......
  • 化学绘图软件ChemDraw Mac版,绘制简单的化学元素
    ChemDraw是一款化学绘图软件,在化学领域中,它可以绘制简单的化学物质的结构,属性和数据,甚至是一些数据图表。它在绘制过程中所展现出来的强大功能是非常适合做精细研究的,并且操作非常简单,它只需要点击一下鼠标就可以进行简单的操作,一步操作就可以完成它。可以制作简单的颜色,形状,图表(......
  • Python绘制多种形式的条形图(柱状图)
    绘图前的准备因为涉及到中文显示,所以需要用两行代码解决中文乱码问题importnumpyasnpfrommatplotlibimportpyplotaspltplt.rcParams['font.sans-serif']=[u'SimHei']#SimHei就是中文字体#因为设置了中文后,负号就乱码了,所以还要设置负号的编码plt.rcParams['axes.......
  • OpenGL之HelloWorld
    1#include<iostream>//C++的标准输入输出头文件2usingnamespacestd;34#defineGLEW_......
  • OpenGL之DrawTriangle
    1/*第一步:引入相应的库*/2#include<iostream>3usingnamespacestd;45#defineGLEW_STATIC6#include<GL/glew.h>7#include<GLFW/glfw3.h>8910/*第二步:编写顶点位置*/11GLfloatvertices_1[]=12{130.0......
  • 通过 IMU 绘制物体移动的空间轨迹
    一般IMU由加速度传感器、陀螺仪组成,也叫6轴IMU。还可以外加一个磁力计,构成9轴IMU。关于加速度传感器和陀螺仪的工作原理,可以参考:加速度传感器的原理和应用-手机翻转、失重检测、运动检测、位置识别;MEMS三轴加速计、三轴陀螺仪、三轴磁力计)6轴IMU+磁力计,9轴传感器讲解;......
  • [数据分析与可视化] Python绘制数据地图4-MovingPandas入门指北
    MovingPandas是一个基于Python和GeoPandas的开源地理时空数据处理库,用于处理移动物体的轨迹数据。它提供了一组强大的工具,可以轻松地加载、分析和可视化移动物体的轨迹。通过使用MovingPandas,用户可以轻松地处理和分析移动对象数据,并从中提取有关行为、模式和趋势的见解。无论是处......
  • Android View绘制原理 - SkCanvas
    上一篇文章介绍了在Android框架中的各种Canvas,其中C层的RecordingCanas承上启下,在SkiaRecordingCanvas的绘制方法会通过调用它的mRecorder来记录,而这个mRecorder的类型正好就是SkCanvas,准确的说是它的子类RecordingCanas。而各种绘制方法会对应生成一个Op对象来描述这个绘制操作,Rec......
  • MATLAB plot绘制图像
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......