在第一节课的时候,我们通过glBegin()和glEnd()在屏幕上绘制一个三角形。这种方式是旧版 OpenGL。 与之对应的是modern opengl,首先是创建一个顶点缓冲区(简单理解成内存字节数组),创建一个着 色器,顶点缓冲区跟C++数组有点类似,都是数组缓冲区,但不同的是顶点缓冲区是存在显存里。 我们定义一些数据表示三角形, 我要把他放入显存中,然后发出DrawCall指令。这就相当于我跟显 卡说,你的显存有一堆数据,读取他,并把他绘制到屏幕上。我们还需要跟显卡说如何读取和解析这些 数据以及如何放在屏幕上。这就相当于我们用C++写出来的东西在CPU运行一样。我们告诉显卡这里有 一堆数据,然后显卡响应,读取数据,理解就像是屏幕上的坐标,然后通过一段代码的指令再理解为要 绘制三角形,然后显卡就的确这么做了,然后屏幕就显示三角形而不是三个点。然后前面说一段代码的 指令就是我们说的着色器,着色器是一段代码。 还有重要的点是 Opengl是一个状态机。 这就有点像是着色器已经存在,顶点缓冲区也已经存在,这个时候我告诉显卡,你根据这个顶点缓冲 区和着色器去绘制三角形。就是他对已经存在的事情做出响应。这就是opengl运行逻辑。
glBegin(GL_TRIANGLES);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.f, 0.5f);// 0.f,0.5f是顶点数据
glVertex2f(0.5f, -0.5f);
glEnd();
然后我们修改上面的代码
定义顶点数据
unsigned int buffer;
glGenBuffers(1,&buffer);// 生成一个缓冲区id
glBindBuffer(GL_ARRAY_BUFFER, buffer); // 绑定缓冲区为数组类型
// 以下是指定数据到buffer缓冲区,两种方式
// 1、就是先指定buffer大小,然后后面再赋值
// 2、直接给数据
float position[6] =
{
-0.5f, -0.5f,
0.f, 0.5f,
0.5f, -0.5f
};
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);
glBufferData解析
void glBufferData( GLenum target,
GLsizeiptr size,
const GLvoid * data,
GLenum usage);
Parameters
target
Specifies the target to which the buffer object is bound for glBufferData, which must be one of the buffer binding targets in the following table:
Buffer Binding Target Purpose
GL_ARRAY_BUFFER Vertex attributes
GL_ATOMIC_COUNTER_BUFFER Atomic counter storage
GL_COPY_READ_BUFFER Buffer copy source
GL_COPY_WRITE_BUFFER Buffer copy destination
GL_DISPATCH_INDIRECT_BUFFER Indirect compute dispatch commands
GL_DRAW_INDIRECT_BUFFER Indirect command arguments
GL_ELEMENT_ARRAY_BUFFER Vertex array indices
GL_PIXEL_PACK_BUFFER Pixel read target
GL_PIXEL_UNPACK_BUFFER Texture data source
GL_QUERY_BUFFER Query result buffer
GL_SHADER_STORAGE_BUFFER Read-write storage for shaders
GL_TEXTURE_BUFFER Texture data buffer
GL_TRANSFORM_FEEDBACK_BUFFER Transform feedback buffer
GL_UNIFORM_BUFFER Uniform block storage
size
Specifies the size in bytes of the buffer object's new data store.
data
Specifies a pointer to data that will be copied into the data store for initialization, or NULL if no data is to be copied.
usage
Specifies the expected usage pattern of the data store. The symbolic constant must be GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.
绘制三角形函数
glDrawArrays(GL_TRIANGLES, 0, 3);
/*
void glDrawArrays( GLenum mode,
GLint first,
GLsizei count);
Parameters
mode
Specifies what kind of primitives to render. Symbolic constants GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY and GL_PATCHES are accepted.
first
Specifies the starting index in the enabled arrays.
count
Specifies the number of indices to be rendered.
*/
注意事项:
-
我们看到黑窗口,因为我们只是写了30%的代码,还没有说着色器,索引缓冲区。
-
glDrawArrays(GL_TRIANGLES, 0, 3);没有指明用哪个顶点数据,注意我们前面说的opengl是一个状态机,顶点数据其实glBindBuffer这个函数已经指明了。这就像说ps里面你要选中哪个图层,然后再操作是一个意思,glBindBuffer相当于选中图层。这就是opengl运行原理。
好了,今天虽然没有画出三角形,但我们先讲了顶点缓冲区这一个知识,不想一个视频占用太多时间,剩下怎么把三角形绘制出来,我们下节课再做分享。谢谢!!!