使用glbegin()和glend()的限制
除了以下的函数外,glbegin()和glend()之间不能使用其他opengl函数。若使用其他函数,将产生未定义的行为,但不一定会产生错误。调试也非常困难。
点的细节
glpointsize(size) 以像素为单位,设置被渲染点的宽度。(点方块表示为size像素*size像素)size必须大于0.0,默认为1.0;
默认禁用抗锯齿,带小数的宽度值四舍五入为整型值。
直线细节
gllinewidth(width)以像素为单位设置宽度,用于直线的渲染。必须大于0.0,默认为1.0
- 使用glgetfloatv()函数查询直线宽度范围的方法
- 锯齿:
gl_aliased_line_width_range
- 抗锯齿:最小和最大宽度
(gl_smooth_line_width_range)
,支持的直线宽度的粒度(gl_smooth_line_width_granularity)
- 锯齿:
点画线
使用gllinestipple()函数定影点画模式,然后调用glenable()启用点画功能。
gllinestipple(1,0x3F07);//重复因子,位为1的重复次数
查询状态变量的当前值
glenable(enum)和gldisable(enum)
启用和关闭一个功能。如果要查询某个状态的关闭或打开情况可以使用glisenable(enum)
;
点、轮廓或实心形式的多边形
默认情况下,多边形的正面和背面是按照相同的方式绘制的。
void glpolygonmode(glneum face, glneum mode)
控制多边形的正面和背面的绘图模式。
face
- gl_front_and_back
- gl_frony
- gl_back
mode
- gl_point//点
- gl_line//轮廓
- gl_file//填充
反转和剔除多边形表面
void glfrontface(glenum mode)//指定多边形正面
默认情况下,mode是
- GL_CCW, 逆时针为正
- GL_CW,顺时针为正
void glcullface(GLenum mode)//丢弃哪些不可见的正面或者背面多边形
使用glenable(GL_CULL_FACE)
函数启用剔除功能。
mode是
- GL_FRONT 正面多边形
- GL_BACK 背面多边形
- GL_FRONT_AND_BACK 所有多边形
点画多边形
glpolygonstipple()函数指定多边形的点画模式。
启用glenable(gl_polygon_stipple)
void glpolygonstipple(const glubyte *mask)
mask参数是指向32X32位图的指针,后者被解释为0,1的掩码。1就绘制,0不绘制。
mask数据的解释受到
glpixelstore*()
gl_upack*模式的影响。
标记多边形的边界边
表示一个顶点是否应该被认为是多边形的一条边界的起点。如果flag是gl_true,边界标志就设置为true(默认),在此之后的所有顶点都被认为是边界边的起点。直到用gl_false为flag参数的值再次调用这个函数。
void gledgeflag(glboolean flag);
void gledgeflagv(const glboolean *flag);
///////////////////////////////////////////
float v0[] = {-0.9,0,0};
float v1[] = { 0, 0.9, 0 };
float v2[] = { 0, 0, 0 };
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_POLYGON);
glEdgeFlag(GL_TRUE);
glVertex3fv(v0);
glEdgeFlag(GL_FALSE);
glVertex3fv(v1);
glEdgeFlag(GL_TRUE);
glVertex3fv(v2);
glEnd();
glPointSize(5);
glBegin(GL_POINTS);
glColor3f(1, 0, 0);
glVertex3fv(v0);
glColor3f(0, 1, 0);
glVertex3fv(v1);
glColor3f(0, 0, 1);
glVertex3fv(v2);
glEnd();
法线向量
- 同一个多边形可能,共享同一条法线(平面),不共享的(曲面)。除了顶点外,不可能为多边形的其他地方分配法线。
- 物体的法线向量定义了它的表面在空间中的方向。相对光源的方向。在执行光照计算之前,它的长度会转换为1 。
- 如果进行不规则变换(如缩放或乘以剪切矩阵或指定非单位长度的法线),启用glenable(gl_normalize)。若提供单位长度法线,并执行均匀缩放,启用glenable(gl_rescale_normal),用一个常量因子(从模型视图变换矩阵得出)对法线进行缩放,使其变换后恢复为单位长度。
- 默认下,法线的自动规范和重新缩放操作都是禁用的。
顶点数组
把数据放在顶点数组中可以提高应用程序的性能。
- 使顶点数组可以减少函数调用的次数,提高性能。
- 避免共享顶点的冗余处理。
对几何图形进行渲染的3个步骤:
1. 启用数组
调用glenableclientstate()(使用枚举值作为参数),不可能同时激活gl_color_array和gl_index_array 。
如果使用光照,可能需要为每个顶点定义一条法线向量。使用顶点数组时,需要同时激活法线数组和顶点数组坐标。
若关闭光照,只用一种颜色绘制几何图元。需要调用gldisable()函数关闭光照状态。在取消光照激活状态之后,需要停止更改表面法线状态的值(因为这种做法是完全浪费)。为此,可以调用:
gldiableclientstate(GL_NORMAL_ARRAY);
glenable()和gldisable()可以存储在显示列表中,但顶点数组却不可以(数据被保存在客户端)。
2.指定数组数据
共有8个不同的函数可以指定数组,每个函数用于指定不同类型的数组。
void glvertexpointer(glint size,glenum type,glsizei stride,const glvoid *pointer);
void glcolorpointer(glint size,glenum type,glsizei stride,const glvoid *pointer);
void glsecondarycolorpointer(glint size,glenum type,glsizei stride,const glvoid *pointer);
void glindexpointer(glenum type,glsizei stride,const glvoid *pointer);
void glnormalpointer(glenum type,glsizei stride,const glvoid *pointer);
void glfogcoordpointer(glenum type,glsizei stride,const glvoid *pointer);
void gltexcoordpointer(glint size,glenum type,glsizei stride,const glvoid *pointer);
void gledgeflagpointer(glsizei stride,const glvoid *pointer);
//启用多个顶点数组
static GLfloat vertices[] = {
-0.9,0,
0.9,0,
0.5,0.5,
0,0.9
};
static GLfloat colors[] = {
1,0,0,
0,1,0,
0,0,1,
1,1,0
};
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glBegin(GL_LINES);
glArrayElement(0);
glArrayElement(1);
glArrayElement(2);
glArrayElement(3);
glEnd();
//解引用顶点数组
static GLfloat interwined[] =
{
1, 0, 0, -0.9, 0,
0, 1, 0, 0.9, 0,
0, 0, 1, 0.9, 0,
1, 1, 0, 0, 0.9
};
GLubyte index[] = {0,1,2,3};
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), &interwined[0]);
glVertexPointer(2, GL_FLOAT, 5 * sizeof(GL_FLOAT), &interwined[3]);
glDrawElements(GL_LINES, 4, GL_UNSIGNED_BYTE, index);
以上两端代码实现的效果相同,如下图:
void glArryElement(GLint ith):
获取当前所有已启用数组的一个顶点(第ith个)的数据。glarrayElement()通常是在glBegin()和glEnd()之间调用。否则,glArrayElement()函数就会设置所有启用的数组的当前状态。对于每个顶点只调用1次,因此它可能会减少函数调用的数量,提高程序的总体性能。void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid *indices):
mode:和glbegin参数相同。
count:定义一个几何图元序列,元素的索引值保存在indices数组中。
type:必须是GL_UNSIGNED_BYTE、GL_UNSIGNED_SHORT或GL_UNSIGNED_INT,表示indices数组的类型。- 把gldrawelements()放在glbegin()与glend()之间是错误的做法。
- 把gldrawelements()放在glbegin()与glend()之间是错误的做法。
void glMultiDrawElements(GLenum mode,GLsizei *count,GLenum type,const GLvoid **indices ,GLsizei primcount )
void glDrawRangeElements(GLenum mode,GLUint start,GLuint end,GLsizei count,GLenum type,const GLvoid *indices )
glDrawArrays(GLenum mode, GLint first,GLsizei count)
下面的这篇文章介绍的非常详细,但是想了解的更多还是看下opengl编程指南吧。
http://www.cnblogs.com/Clingingboy/archive/2010/10/16/1853304.html
创建缓冲区对象
void glenbuffers(glsizei n,gluint *buffers)
- 在buffer数组中返回n个当前未使用的名称,表示缓冲区对象。在buffers数组中返回的名称并不需要是连续的整数。
- 返回的名称被标记为已使用,以便分配给缓冲区对象。但是,当他们被绑定之后,只是会的一个合法的状态。
- 零是一个被保留的缓冲区对象名称,从来不会被glgenbuffers()作为缓冲区对象返回。
- 调用glisbuffer()函数,判断标志符是否是当被使用的缓冲区对象的标识符。
激活缓冲区对象
用数据分配和初始化缓冲区对象
一旦绑定缓冲区对象,就需要保留空间以存储数据。glbufferdata()。
- void glbufferdata(glenum target,glsizeiptr size,const glvoid *data,glenum usage)
分配size个存储单位(通常是字节)的opengl服务器内存,用于存储顶点数据或索引。
更新缓冲区对象的数据值
void glbuffersubdata(glenum target,glintptr offset,glsizeiptr size,const glvoid *data)
用data指向的数据更新与target相关联的当前绑定缓冲区对象中从offset(以字节为单位)开始的size个字节数据。size小于0或size+offset大于缓冲区对象创建时指定的大小,glbuffersubdata()将产生gl_invalid_value错误。glvoid *glmapbuffer(glenum target,glenum access)
返回一个指针,指向target相关联的当前绑定缓冲区对象的数据存储。
在完成对数据存储的访问之后,可以调用glunmapbuffer()取消对这个缓冲区的映射。