title: OpenGL(3)三角形
date: 2020-06-28 16:01
category: 图形学
tags: opengl
OpenGL(3)三角形
1.概述
- VAO: 顶点数组对象 Vertex Array Object
- VBO: 顶点缓冲对象 Vertex Buffer Object
- IBO(EBO): 索引缓冲对象 Element Buffer Object or Index Buffer Object
在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转换为适应屏幕的2D像素。
3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线管理的;
上述意思:3D坐标可以看成一堆的原始图形数据经过一个输送管道,在这个过程中经过坐标变换,着色等等最终呈现在屏幕上。
-
将3D坐标转换为2D坐标。
-
把2D坐标转换为实际的有颜色的像素。
流程:
顶点数据
------>
顶点着色器(1)
------>
图元装配(2)
------>
几何着色器(3)
------>
光栅化(4)
------>
片段着色器(5)
------>
测试与混合(6)
以三角形为例:
-
以数组的形式传递3个3D坐标作为图形渲染管线的输入来表示一个三角形,这个数据叫做顶点数据(vertex data);那么顶点着色器
是把3D坐标转换为另一种3D坐标(输入的3D坐标不是标准的设备坐标,即不是在OpenGl的可见区域) -
利用顶点着色器输出的所有顶点作为输入,把所有的点装配成指定图元的形状
-
将图元装配阶段的输出传递给几何着色器,几何着色器把图元形式的一系列顶点的集合作为输入,通过产生新顶点构造新的图元来生成其他形状
-
几何着色器的输出被传入到光栅化阶段,将图元映射为最终屏幕上相应的像素,生成供片段着色器使用的片段,还要进行相应的裁切处理,裁切部分超出视图以外的所有像素。其实就用来生成片段,以便片段着色器对坐标点进行着色
-
用来计算一个像素的最终颜色,其中还包括3D场景数据(光照、阴影、光的颜色),这些数据可以用来计算最终像素的颜色
-
在所有对应的颜色值确定之后,最终的对象将会被传到最后一个阶段,Alpha测试和混合测试,这个阶段检查片段对应的深度,用来判断这个像素是在其他物体的前面还是后面,决定是否应该丢弃,这个阶段也会检查alpha值(透明度)并对物体进行混合。
2.顶点输入
- 绘制图形之前,需要给OpenGL输入一些顶点数据,由于OpenGL是一个3D图形库,因此OpenGL指定的所有的坐标点都是3D坐标(x,y,z)
注意:OpenGL不是简单的把所有的3D坐标变换为屏幕上的2D像素,OpenGL仅当3D坐标在3个轴(x,y和z)上都为-1.0和1.0的范围内才会处理它。(归一化设备坐标)渲染一个三角形,指定三个顶点,每个顶点有一个3D位置;
float vertices[]={
0.5f,0.5f,0.0f, //(x,y,z)
-0.5f,-0.5f,0.0f,
-0.5f,0.5f,0.0f
}
z为0,由于渲染的是一个2D三角形,因此z坐标设置为0,z坐标可以理解为深度(depth),代表一个像素在空间中与你的距离。
-
定义好了这样的顶点数据之后,将数据发送到图形渲染管线的第一个处理阶段:顶点着色器。
- 在GPU上创建内存用于储存顶点数据
- 配置OpenGL如何解释解释这些内存,指定如何将顶点着色器如何发送给显卡
- 顶点着色器处理在内存中指定数量的顶点。
-
**顶点缓冲对象(VBO)**管理在GPU上创建的内存,在内存中存储大量的顶点。
-
好处:一次性发送一大批数据到显卡上,原因是从CPU把数据发送到显卡相对较慢(针对每次发送一个顶点而言)
-
是一个OpenGL对象,有一个独一无二的ID,使用glGenBuffers函数和一个缓冲ID生成一个VBO对象
-
unsigned int VBO;
glGenBuffers(1,&VBO);
顶点缓冲对象的缓冲类型为GL_ARRAY_BUFFER,OpenGL允许同时绑定多个缓冲,只要是不同的缓冲类型。使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER;
unsigned int VBO;
glBindBuffer(GL_ARRAY_BUFFER,VBO); // 绑定的是一个顶点缓冲对象类型为GL_ARRAY_BUFFER
glBindBuffer(GL_COPY_READ_BUFFER,VBO);
//2.生成一个VBO对象
glGenBuffers(1,&VBO);
为这个VBO对象绑定多种缓冲类型 VBO对象配置一些关于缓冲类型的信息 glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_COPY_READ_BUFFER, VBO);
以上两步只要配置了,那么使用任何在这种缓冲类型的缓冲调用都会用来配置到当前绑定的VBO上
其实就是只要是这两种或者还配置其他缓冲类型的数据,只要这些缓冲类型有数据,VBO对象都是使用这些数据。
最后调用glGenBuffers来生成一个VBO对象.
要想使用这些数据,就需要把用户输入的数据存储到对应的缓存类型的缓冲内存中,只需调用glBufferData函数,就可以把之前定义好的顶点数据复制到缓冲内存中
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
//glBufferData(GL_COPY_READ_BUFFER,sizeof(vetices),vetices,GL_STATIC_DRAW);??
上述参数解释:
-
目标缓冲类型:顶点缓冲对象当前绑定到GL_ARRAY_BUFFER目标上。
-
指定传输数据的大小(以字节为单位),用sizeof计算出顶点数据大小。
-
发送的实际数据(当前来说就是顶点数组)
-
显卡如何管理给定的数据
渲染保持原样
GL_STATIC_DRAW:数据不会或几乎不会改变
数据频繁被改变,确保显卡把数据放在能够高速写入的内存部分
GL_DYNAMIC_DRAW:数据会改变很多
GL_STREAM_DRAW:数据每次绘制是都会改变。