opengl--顶点数组和缓冲区对象

一、OpenGL顶点数组

作为在立即模式(glBegin()与glEnd()之间)下指定单个顶点数据的替代,你可以保存顶点数据在一组列表中,包括顶点位置、法线、纹理坐标与颜色信息。并且你可以通过索引数组绘制选定的几何图元。

顶点数组保存在你的应用程序(系统内存),它在客户端。且处在服务端的OpenGL访问它们。这就是为什么拥有顶点数组这些特殊命令的原因,使用glEnableClientState()与glDisableClientState()而不是glEnable()与glDisable()。

初始化

OpenGL提供glEnableClientState()与glDisableClientState()函数启用/禁用6中不同类别的数组。此外,有6个函数用于指定数组的精确位置(地址),因此在你的应用程序中OpenGL可以访问这些数组。

  • glVertexPointer():指定顶点坐标数组指针
  • glNormalPointer():指定法线数组指针
  • glColorPointer():指定RGB颜色数组指针
  • glIndexPointer():指定索引颜色数组指针
  • glTexCoordPointer():指定纹理坐标数组指针
  • glEdgeFlagPointer():指定边标志数组指针

glDrawArrays()

glDrawArrays()从开启的数组中顺序读取顶点数据。由于glDrawArray()不准许在顶点数组中跳跃,你必须为每个面重复指定共用顶点。

glDrawElements()

glDrawElements()通过顶点数组相关的随机数组索引绘制图元序列。

glDrawRangeElements()

与glDrawElements()类似,glDrawRangeElements()也适用于随机访问顶点数组。不过glDrawRangeElements()有额外的2个参数(start与end索引)以指定需要读取的顶点范围。

示例:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(TextVertex), vert);
glTexCoordPointer(2, GL_FLOAT, sizeof(TextVertex), &vert[0][3]);
glDrawArrays(GL_QUADS, 0, index);
// 绘制之后禁用顶点数组
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

二、Opengl缓冲区对象VAO

每当我们绘制一个几何体时,我们需要重复同样的工作(首先绑定缓冲区、然后设置顶点属性)。VAO做的事情,它将所有顶点绘制过程中的这些设置和绑定过程集中存储在一起,当我们需要时,只需要使用相应的VAO即可。
在这里插入图片描述

绑定并设置VAO

//创建VAO
GLuint VAO;
glGenVertexArrays(1, &VAO);
//设置当前VAO,之后所有操作(注意:这些操作必须是上文VAO中包含的内容所注明的调用,其他非VAO中存储的内容即使调用了也不会影响VAO)存储在该VAO中
glBindVertexArray(VAO);
   glBindBuffer(GL_ARRAY_BUFFER, VBO); //设置了VBO
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//设置VBO中的数据
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); //设置顶点属性(索引为0的属性,与shader中的内容有交互)
   glEnableVertexAttribArray(0); //设置开启顶点属性(索引为0的属性,与shader中的内容有交互)
glBindVertexArray(0); //解绑VAO(解绑主要是为了不影响后续VAO的设置,有点类似于C++中指针delete后置空,是个好习惯)

使用VAO

glUseProgram(shaderProgram);
glBindVertexArray(VAO); //绑定我们需要的VAO,会导致上面所有VAO保存的设置自动设置完成
someOpenGLFunctionThatDrawsOurTriangle();   
glBindVertexArray(0);   //解绑VAO

三、帧缓冲区

OpenGL 默认把 framebuffer 当作渲染的目的地。它由窗口系统创建并管理。framebuffer Object 是个二维数组的集合,它包括 color buffers, depth buffer, stencil buffer。

与窗口系统提供的帧缓冲区类似,FBO包含一系列渲染目的地的集合;包括颜色,深度和模板缓冲区。 FBO中的这些逻辑缓冲区称为可附着的 frame buffer。

有两种类型的可附着的 framebuffer;纹理(Texture)和renderbuffer。如果纹理被附加到FBO,OpenGL将执行“渲染到纹理”。如果renderbuffer被附加到FBO,则OpenGL会执行“离屏渲染”。
在这里插入图片描述
FBO中,

  • 有多个颜色附加点(GL_COLOR_ATTACHMENT0,…,GL_COLOR_ATTACHMENTn)
  • 一个深度附加点(GL_DEPTH_ATTACHMENT)
  • 一个模板附加点(GL_STENCIL_ATTACHMENT)。

创建FBO

void glGenFramebuffers(GLsizei n, GLuint* ids)
void glDeleteFramebuffers(GLsizei n, const GLuint* ids)

绑定FBO

void glBindFramebuffer(GLenum target, GLuint id)

附加Renderbuffer

void glGenRenderbuffers(GLsizei n, GLuint* ids)
void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)
void glRenderbufferStorage(GLenum  target,
                           GLenum  internalFormat,
                           GLsizei width,
                           GLsizei height)
 void glFramebufferRenderbuffer(GLenum target,
                               GLenum attachmentPoint,
                               GLenum renderbufferTarget,
                               GLuint renderbufferId)

附加图像

glFramebufferTexture2D(GLenum target,
                       GLenum attachmentPoint,
                       GLenum textureTarget,
                       GLuint textureId,
                       GLint  level)

检查FBO状态

FBO完整性规则为:

  • framebuffer可附加图像的宽度和高度必须不为零。
  • 如果图像附加到颜色附着点,则图像必须具有可呈现颜色的内部格式。(GL_RGBA,GL_DEPTH_COMPONENT,GL_LUMINANCE等
  • 如果图像附加到GL_DEPTH_ATTACHMENT,则图像必须具有深度可渲染内部格式。(GL_DEPTH_COMPONENT,GL_DEPTH_COMPONENT24等)
  • 如果图像附加到GL_STENCIL_ATTACHMENT,则图像必须具有模板可渲染内部格式。(GL_STENCIL_INDEX,GL_STENCIL_INDEX8等) FBO必须至少安装一张图片。
  • 附加FBO的所有图像必须具有相同的宽度和高度。 附加颜色附件点的所有图像必须具有相同的内部格式。
GLenum glCheckFramebufferStatus(GLenum target)

示例

...
// create a texture object
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
                      TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

// create a framebuffer object
GLuint fboId;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER,        // 1. fbo target: GL_FRAMEBUFFER 
                       GL_COLOR_ATTACHMENT0,  // 2. attachment point
                       GL_TEXTURE_2D,         // 3. tex target: GL_TEXTURE_2D
                       textureId,             // 4. tex ID
                       0);                    // 5. mipmap level: 0(base)

// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER,      // 1. fbo target: GL_FRAMEBUFFER
                          GL_DEPTH_ATTACHMENT, // 2. attachment point
                          GL_RENDERBUFFER,     // 3. rbo target: GL_RENDERBUFFER
                          rboId);              // 4. rbo ID

// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
    fboUsed = false;

// switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
...
..
// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// draw a scene to a texture directly
draw();

// unbind FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// trigger mipmaps generation explicitly
// NOTE: If GL_GENERATE_MIPMAP is set to GL_TRUE, then glCopyTexSubImage2D()
// triggers mipmap generation automatically. However, the texture attached
// onto a FBO should generate mipmaps manually via glGenerateMipmap().
glBindTexture(GL_TEXTURE_2D, textureId);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值