OpenGL中的绘制命令
来源:互联网 发布:ibeacon室内定位算法 编辑:程序博客网 时间:2024/05/22 08:25
OpenGL中的绘制命令
1.直接绘制命令
OpenGL中以Draw开头的绘制命令主要分成两大类,一类是从GL_ELEMENT_ARRAY_BUFFER缓存中获取绘制信息的函数,一类是不从其获得绘制信息的函数。注意GL_ELEMENT_ARRAY_BUFFER是用于存放顶点索引数组的缓存,可以见OpenGL4.3如何管理buffer中的数据的这篇文章。当从GL_ELEMENT_ARRAY_BUFFER得到绘制信息时,OpenGL将会利用此缓存内存储的索引序号来读取当前顶点数组的顶点。而非此类绘制则是按照指定的顺序来读取顶点。
不利用GL_ELEMENT_ARRAY_BUFFER的绘制函数:
函数原形:
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
函数说明:从顶点数组中first个开头的顶点,绘制count个顶点,绘制原语由mode指出,通常有GL_TRIANGLES, GL_LINE_LOOP,
GL_LINES, GL_POINTS等等
利用GL_ELEMENT_ARRAY_BUFFER的绘制函数:
函数原形: void glDrawElements(GLenum mode, GLsizei count,GLenum type, const GLvoid *indices);
函数说明:mode指定绘制原语,与上函数类似,*indices应为一个数组,指出每个偏移地址,指出从GL_ELEMENT_ARRAY_BUFFER当前元素数组的哪个读取数组索引(这个才是顶点的编号),count表示读取多少个顶点,而type表示数组中的值用何种数据类型存储的,只可以为GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT, GL_UNSIGNED_INT。
2.间接绘制命令
间接命令绘制的缓存对象需要被存储于GL_DRAW_INDIRECT_BUFFER中。
函数原形:
void glDrawArraysIndirect(GLenum mode,const GLvoid *indirect);
函数说明:从 GL_DRAW_INDIRECT_BUFFER 中读取数据,indirect指出一个命令结构体地址的偏移量,OpenGL将会从间接绘制缓存中此偏移地址获取绘制指令的其余部分,并调用glDrawArraysInstanced()。
下面是偏移地址中绘制指令的结构体:
typedef struct DrawArraysIndirectCommand_t{GLuint count;GLuint primCount;GLuint first;GLuint baseInstance;} DrawArraysIndirectCommand;
DrawArraysIndirectCommand中的成员将会被解释为调用glDrawArraysInstanced()函数的参数,first及count将会被直接传递给函数,primCount是实例的数量,baseInstance是顶点实例的偏移地址。(后面还会说明)
函数原形:
void glDrawElementsIndirect(GLenum mode, GLenum type, const GLvoid * indirect);
函数说明:与glDrawElements基本相同,不同是从 GL_DRAW_INDIRECT_BUFFER 中读取数据,indirect指出一个命令结构体地址的偏移量,OpenGL将会从间接绘制缓存中此偏移地址获取绘制指令的剩余部分。
下面是偏移地址中绘制指令的结构体:
typedef struct DrawElementsIndirectCommand_t{GLuint count;GLuint primCount;GLuint firstIndex;GLuint baseVertex;GLuint baseInstance;} DrawElementsIndirectCommand;
3.多重绘制命令
多重绘制指令与此前的绘制指令类似,仅不同的是用数组来表示多个绘制指令的参数,下面仅说明一个多重绘制指令,其余的没有特殊的部分则不再多提:
函数原形:
void glMultiDrawArrays(GLenum mode, const GLint * first, const GLint * count, GLsizei primcount);
函数说明:*first,*count都是数组,primcount指出了所需执行的操作数量
下面给出了函数c语言的模拟代码:
void glMultiDrawArrays(GLenum mode,const GLint * first,const GLint * count,GLsizei primcount){ GLsizei i; for (i = 0; i < primcount; i++) { glDrawArrays(mode, first[i], count[i]); }}
红宝书给出了一个说明的例子,但不能完整运行,用于说明绘制指令:
例3.5 - 3.6:
//顶点数组static const GLfloat vertex_positions[] ={ -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,};// 颜色数组static const GLfloat vertex_colors[] ={ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f};//索引数组static const GLushort vertex_indices[] ={ 0, 1, 2};// 设置元素缓存GL_ELEMENT_ARRAY_BUFFER,注意用的vertex_indices填充的glGenBuffers(1, ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);// 设置顶点缓存,将顶点和颜色都存放到了顶点缓存glGenVertexArrays(1, vao);glBindVertexArray(vao[0]);glGenBuffers(1, vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);glBufferData(GL_ARRAY_BUFFER,sizeof(vertex_positions) + sizeof(vertex_colors),NULL, GL_STATIC_DRAW);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_positions), vertex_positions);glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_positions), sizeof(vertex_colors), vertex_colors);//利用多种方式绘制三角型 //平移 model_matrix = vmath::translation(-3.0f, 0.0f, -5.0f);//将平移信息传递给shaderglUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, model_matrix);//绘制第一个三角glDrawArrays(GL_TRIANGLES, 0, 3);// 利用索引数组绘制model_matrix = vmath::translation(-1.0f, 0.0f, -5.0f);glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, model_matrix);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL);// DrawElementsBaseVertexmodel_matrix = vmath::translation(1.0f, 0.0f, -5.0f);glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, model_matrix);glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL, 1);// DrawArraysInstancedmodel_matrix = vmath::translation(3.0f, 0.0f, -5.0f);glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, model_matrix);glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);
注意,书中给的代码是各种不能用阿,我费尽千辛万苦终于实现了书中的图:
下面先给出完整代码:
#include <iostream>#include "vgl.h"#include "LoadShaders.h"#include "vmath.h"using namespace std;GLint render_model_matrix_loc;GLint render_projection_matrix_loc;float aspect = 1.0;static const GLfloat vertex_positions[] ={ -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,};// 颜色数组static const GLfloat vertex_colors[] ={ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f};//索引数组static const GLushort vertex_indices[] ={ 0, 1, 2}; GLuint ebo[2]; GLuint vao[2]; GLuint vbo[2];void init(void){ // 设置元素缓存GL_ELEMENT_ARRAY_BUFFER,注意用的vertex_indices填充的 ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE, NULL } }; //例程中给的ShaderInfo竟然与自己定义的不兼容,为了方便起见,这里仍然调用了例1.1的shader相关文件 GLuint program = LoadShaders(shaders); glUseProgram(program); //寻找着色器中对应uniform数据的索引 render_model_matrix_loc = glGetUniformLocation(program, "model_matrix"); render_projection_matrix_loc = glGetUniformLocation(program, "projection_matrix"); //将索引数组绑定到GL_ELEMENT_ARRAY_BUFFER glGenBuffers(1, ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW); // 设置顶点缓存,将顶点和颜色都存放到了顶点缓存 glGenVertexArrays(1, vao); glBindVertexArray(vao[0]); glGenBuffers(1, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions) + sizeof(vertex_colors), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_positions), vertex_positions); glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_positions), sizeof(vertex_colors), vertex_colors); //第一个参数0对应了顶点着色器中的layout (location = 0)参数 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); //第一个参数1对应了顶点着色器中的layout (location = 1)参数 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)sizeof(vertex_positions)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);}//---------------------------------------------------------------------//// display//voiddisplay(void){ vmath::mat4 model_matrix; //使能功能 glEnable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //设置投影矩阵和平移矩阵,后面课程应该会有深入讲解 //设置投影矩阵,只需执行一次 vmath::mat4 projection_matrix(vmath::frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 500.0f)); glUniformMatrix4fv(render_projection_matrix_loc, 1, GL_FALSE, projection_matrix); // 为绘制设定缓存 glBindVertexArray(vao[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]); // 设置平移矩阵,传递给顶点shader,并绘制图形 model_matrix = vmath::translate(-3.0f, 0.0f, -5.0f); //这里第二个参数应为1,原程序给的是4,坑爹。。。下同 glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, model_matrix); glDrawArrays(GL_TRIANGLES, 0, 3); // DrawElements形式的设置平移矩阵,传递给顶点shader,并绘制图形 model_matrix = vmath::translate(-1.0f, 0.0f, -5.0f); glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, model_matrix); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL); // DrawElementsBaseVertex形式的设置平移矩阵,传递给顶点shader,并绘制图形 model_matrix = vmath::translate(1.0f, 0.0f, -5.0f); glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, model_matrix); glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL, 1); // DrawArraysInstanced形式的设置平移矩阵,传递给顶点shader,并绘制图形 model_matrix = vmath::translate(3.0f, 0.0f, -5.0f); glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, model_matrix); glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1); //解除绑定 glBindVertexArray(0); glutSwapBuffers(); }intmain(int argc, char** argv){ //这里用的仍然是例1.1的主程序,原文提供的代码里没找到他的主程序。。 glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA); glutInitWindowSize(512, 512); glutInitContextVersion(4, 3); glutInitContextProfile(GLUT_CORE_PROFILE); glutCreateWindow(argv[0]); glewExperimental = GL_TRUE; if (glewInit()) { cerr << "Unable to initialize GLEW ... exiting" << endl; exit(EXIT_FAILURE); } init(); glutDisplayFunc(display); glutMainLoop();}
下面是两个shader的代码,和例1.1不同
triangles.vert
#version 430 coreuniform mat4 model_matrix;uniform mat4 projection_matrix;layout (location = 0) in vec4 position;layout (location = 1) in vec4 color;out vec4 vs_fs_color;void main(void){ vs_fs_color = color; gl_Position = projection_matrix * (model_matrix * position);}
triangles.frag
#version 430 corein vec4 vs_fs_color;layout (location = 0) out vec4 color;void main(void){ color = vs_fs_color;}
最后再唠叨几句其他注意的地方,首先loadshader用例1.1的就可以了,或者在原书提供的例程的\include 和\bin下有,此外,vmath提供了一些矩阵的函数,mat4表示4x4阶矩阵,vec3表示3阶向量,依此类推,需要包含vmath.h才能使用。
原程序的vmath::translation不能使用,需要改成vmath::translate才对。
题外话:所以说这本书的作者口口声声说虚心接受大家指出错误,希望到他的网站上提错误,然后它的网站除了一个下载代码的地址啥也没有,态度可是不咋样。。。。
- OpenGL中的绘制命令
- OpenGL 03 绘制命令
- Opengl学习程序之绘制命令
- OpenGL中的平面圆绘制与贴图
- OpenGL中的3D文字绘制
- OpenGL: OpenGL中的平面圆绘制与贴图
- OpenGL: OpenGL圆柱面绘制贴图
- OpenGL的数组绘制
- 用OpenGL绘制地球
- OpenGL曲线绘制:线段
- 利用OpenGL绘制按钮
- opengl 绘制简单图形
- openGL绘制图像
- OpenGL圆柱面绘制贴图
- OpenGL绘制填充五角星
- OpenGL 绘制几何图形
- OpenGL 绘制几何图形
- opengl 绘制 ttf 字符串
- BLE简介及连接过程
- Unicode与UTF-8互转(C语言实现)
- 防微博内容展示,使用Html.fromHtml(),解决内容不能换行的问题
- unity换装,SkinnedMeshRender
- 最大权闭合子图的简单证明
- OpenGL中的绘制命令
- ZOJ 3699 Dakar Rally(贪心)
- 倒排索引
- Android view更改背景资源,padding消失的问题
- ZooKeeper开发手册中文翻译
- 一个Myeclipse同时配置多个Tomcat
- 在win7下用U盘安装ubuntu12.04
- 使用socket函数的一些常见错误
- 嵌入式软件工程师介绍