图元
点: GL_POINTS
线: GL_LINES
条带线: GL_LINE_STRIP
循环线: GL_LINE_LOOP
独立三角形: GL_TRIANGLES
三角形条带: GL_TRIANGLE_STRIP
三角形扇面: GL_TRIANGLE_FAN
多边形
1) 正反面的绘制模式:glPolygonMode(GL_FRONT_AND_BACK, GL_POINT) //GL_FRONT、GL_BACK;GL_LINE、GL_FILL
2) 反转: glFrontFace(GL_CCW) //默认为逆时针, GL_CW顺时针方向的面为正面 (控制正面的方向)
3) 裁剪: glEnable(GL_CULL_FACE)
glCullFace(GL_FRONT); //GL_BACK、GL_FRONT_AND_BACK
4) 偏移: glEnable(GL_POLYGON_OFFSET_FILL); //多边形偏移避免深度数据的z-fighting问题
glPolygonOffset(2.0f, 4.0f);
OpenGL缓存
object.BindVertexArray(); //绑定
glGenBuffers(1, &weight_vbo);
glBindBuffer(GL_ARRAY_BUFFER, weight_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);
glVertexAttribDivisor(3, 1); //位于index的顶点属性分配到几个新的属性,启用顶点属性
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(3);
glGenBuffers(1, &color_vbo);
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribDivisor(4, 1);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(4);
glBindVertexArray(0); //解绑
注意:在内存中数组之间可能是连续的,也可能不连续,此时无法用glBufferData()一次性更新所有数据,因此引入glBufferSubData()
访问缓存
glGetBufferSubData() :将opengl内存中的数据拷贝到应用程序内存中。
glMapBuffer() :通过获取一个指针的形式,直接在应用程序中对opengl内存进行访问
void *a = glMapBuffer(GL_COPY_WRITE_BUFFER, GL_WRITE_ONLY); //映射缓存
fread(data, 1, filesize, f); //将文件读入缓存
glUnMapBuffer(GL_COPY_WRITE_BUFFER); //解除映射
绘制命令
void Initial()
{ ShaderInfo shader_info[] =
{
{ GL_VERTEX_SHADER, "media/shaders/primitive_restart/primitive_restart.vs.glsl" },
{ GL_FRAGMENT_SHADER, "media/shaders/primitive_restart/primitive_restart.fs.glsl" },
{ GL_NONE, NULL }
};
render_prog = LoadShaders(shader_info);
glUseProgram(render_prog);
render_model_matrix_loc = glGetUniformLocation(render_prog, "model_matrix");
render_projection_matrix_loc = glGetUniformLocation(render_prog, "projection_matrix");
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
};
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);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)sizeof(vertex_positions));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
{
mat4 model_matrix;
...
glUseProgram(render_prog);
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]);
model_matrix = vmath::translate(-3.0f, 0.0f, -5.0f);
glUniformMatrix4fv(render_model_matrix_loc, 1, GL_FALSE, model_matrix); //绘制命令
glDrawArrays(GL_TRIANGLES, 0, 3);
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);
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);
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);
base::Display();
}
图元重启动
每次绘制的内容总是与前一次图元的类型相同,而且需要大量绘制时,使用glMultiDraw()需要很多额外的去管理起始索引位置和长度的数组,此时就需要用到图元重启动。
glEnable(GL_PRIMITIVE_RESTART)
glPrimitiveRestartIndex(0xFFFF); //从这个索引之后的顶点开始,重新开始进行相同图元的渲染
glDrawElements(GL_TRIANGLES_STRIP)
实例化/多实例渲染
1) 每连续执行多条相同的渲染命令,使用少量API渲染大量集合体的方法。
glDrawArrayInstanced(GL_TRIANGLES, 0 , size, n) //渲染n个
glDrawElementsInstanced()
glGenBuffers(1, &color_vbo);
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribDivisor(4, 1); //控制顶点属性更新的频率,index位置分配几个新的属性,如果后者为0,则禁用
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(4);