① Geometry
课件里只是简要介绍了一下,在网上找到如何使用这些预定变量,是要用glBegin(GLenummode)和glEnd()的。附上参考网址:
http://www.cnblogs.com/Clingingboy/archive/2010/10/16/1853219.html
还发现了一个用这些组合绘制出不错的几何体的网址:
http://blog.chinaunix.net/uid-20384806-id-1954360.html
② Old OpenGL: Drawing in Display
1)要记得glColor3f()的调用在glVertex3f()之前!
2)在begin和end之间,是可以使用三角函数之类的数学公式的。(也可以用for循环)。在百度里还列举出了在这之间可以调用的函数。
3)形如glTranslatef()、glScalef()、glRotatef()等几何转换接口在二者之间调用是无效的。需要在二者之前进行处理。
简易的display()代码就不贴了。注意在开始glClear(GL_COLOR_BUFFER_BIT).
③ Mordern OpenGL
是一个Vertex Buffer Objects的构思。我理解的就是,原来是一个一个画上去,现在呢是同时画上去,所以预先要用一些buffer把信息存储起来。
附上有关代码:
const int numobjects = 2 ; // number of objects for buffer
const int numperobj = 3 ; // Vertices, colors, indices
GLuint buffers[numperobj*numobjects] ; // List of buffers for geometric data
GLuint objects[numobjects] ; // For each object
GLenum PrimType[numobjects] ; // Primitive Type (quads, polygons etc.)
GLsizei NumElems[numobjects] ; // Number of geometric elements
// Floor Geometry is specified with a vertex array
// The Buffer Offset Macro is from Red Book, page 103, 106
// Note for more complex objects the indices must be integers, not bytes.
#define BUFFER_OFFSET(bytes) ((GLubyte *) NULL + (bytes))
#define NumberOf(array) (sizeof(array)/sizeof(array[0]))
enum {Vertices, Colors, Elements} ; // For arrays for object
enum {FLOOR, FLOOR2} ; // For objects, for the floor
const GLfloat floorverts[4][3] = {
{0.5, 0.5, 0.0}, {-0.5, 0.5, 0.0}, {-0.5, -0.5, 0.0}, {0.5, -0.5, 0.0}
} ;
const GLfloat floorcol[4][3] = {
{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 1.0}
} ;
const GLubyte floorinds[1][4] = { {3, 0, 1, 2} } ;
const GLfloat floorverts2[4][3] = {
{0.5, 0.5, 1.0}, {-0.5, 0.5, 1.0}, {-0.5, -0.5, 1.0}, {0.5, -0.5, 1.0}
} ;
const GLfloat floorcol2[4][3] = {
{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}
} ;
const GLubyte floorinds2[1][4] = { {0, 1, 2, 3} } ;
// This function takes in a vertex, color, index and type array
// And does the initialization for an object.
// The partner function below it draws the object
void initobject(GLuint object, GLfloat * vert, GLint sizevert, GLfloat * col, GLint sizecol, GLubyte * inds, GLint sizeind, GLenum type) {
int offset = object * numperobj ;
glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices+offset]) ;
glBufferData(GL_ARRAY_BUFFER, sizevert, vert,GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)) ;
glEnableClientState(GL_VERTEX_ARRAY) ;
glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ;
glBufferData(GL_ARRAY_BUFFER, sizecol, col,GL_STATIC_DRAW);
glColorPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)) ;
glEnableClientState(GL_COLOR_ARRAY) ;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements+offset]) ;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds,GL_STATIC_DRAW);
PrimType[object] = type ;
NumElems[object] = sizeind ;
}
void drawobject(GLuint object) {
int offset = object * numperobj ;
glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices+offset]) ;
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)) ;
glEnableClientState(GL_VERTEX_ARRAY) ;
glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ;
glColorPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)) ;
glEnableClientState(GL_COLOR_ARRAY) ;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements+offset]) ;
glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)) ;
}
1)两个常量:object的数量&每个object需要关注的属性个数
2)2个int型数组:objects数组是对应于每个object的(大小:object个数,objects数组详情:{object枚举量1,object枚举量2,...}),buffers数组存储属性(大小:object数量*属性个数,整个buffers数组就存储了所有objects的所有属性值。buffers数组详情:{[0]=object1属性1;[1]=object1属性2;[2]=object1属性3;[3]=object2属性1;[4]=object2属性2;[5]=object2属性3.}以此类推)。
3)一个枚举型数组:记录每个object属于什么type(大小:object个数;type:之前提到的那些)
4)一个GLsizei的数组。。
5)中间两个define不知道在干嘛= =
6)定义了两组枚举量。
7)然后就是对数组的初始化了:对每个object初始化numperobj个数组。第一个是描述顶点坐标的(水平x轴,深入屏幕里面的是y轴,立起来的是z轴),第二个是描述顶点颜色的,第三个(试验了好久!终于搞明白是什么了!):由于多边形的构造采用的是triangle-fan的方式构造的,因此{0,1,2,3}相当于是先绘制了{0,1,2}构成的三角形,再绘制{0,2,3}的三角形。其它情况同理可推。所以这也可以解释为什么{3,2,1,0}的四边形和{0,1,2,3}的在颜色上有差距。
8)initobject:
a)函数参数对应的就是物体(传进来的时候用的是枚举变量),以及三个属性数组及它们的大小,还有一个就是object的type。
b)offset的偏移量就对应之前分析的buffers里面的存储结构。
c)glBindBuffer和glBufferData两个函数联合起来,是要把之前定义的散装数组(vertex和color以及indice)按照规定的顺序插到buffers数组里面。具体的参数,可以参考上面的代码,或者这个网址:
http://blog.youkuaiyun.com/mzyang272/article/details/7655464
d)glVertexPointer
函数原型:void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
size:指定了每个顶点对应的坐标个数,只能是2,3,4中的一个。默认是4
type:指定了数组中每个顶点坐标的数据类型,可取常量GL_BYTE,GL_SHORT,GL_FIXED,GL_FLOAT
stride:指定了连续顶点间的字节排列方式,如果为0,数组中的顶点就会被认为是按照紧凑排列的,默认值为0
pointer。。。
具体看百度百科吧= =
e)glEnableClientState:
以下是粘来的:
glEnableClientState和glDisableClientState启用或禁用客户端的单个功能。默认的,所有客户端功能禁用。
array可以是下列符号常量:
GL_COLOR_ARRAY——如果启用,颜色矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glColorPointer。
GL_NORMAL_ARRAY——如果启用,法线矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glNormalPointer。
GL_TEXTURE_COORD_ARRAY——如果启用,纹理坐标矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glTexCoordPointer。
GL_VERTEX_ARRAY——如果启用,顶点矩阵可以用来写入以及调用glDrawArrays方法或者glDrawElements方法时进行渲染。详见glVertexPointer。
GL_POINT_SIZE_ARRAY_OES(OES_point_size_arrayextension)——如果启用,点大小矩阵控制大小以渲染点和点sprites。这时由glPointSize定义的点大小将被忽略,由点大小矩阵提供的大小将被用来渲染点和点sprites。详见glPointSize。
注意:
启用和禁用GL_TEXTURE_COORD_ARRAY将会影响活动的客户纹理单元,活动的客户纹理单元由glClientActiveTexture控制。
错误:
如果array不是被允许的值,将产生GL_INVALID_ENUM。
参数:
array——指明启用的功能,允许的符号常量有GL_COLOR_ARRAY,GL_NORMAL_ARRAY,GL_TEXTURE_COORD_ARRAY,GL_VERTEX_ARRAY,和GL_POINT_SIZE_ARRAY_OES (OES_point_size_array extension)
f)把类型数组和顶点个数数组赋值。
9)drawobject
a)步骤基本同initobject,不过不需要glBufferData这一步.
b)glDrawElements
以下是粘来的:
glDrawElements
publicvoid
功能:
由矩阵数据渲染图元。
详细:
glDrawElements用少量调用指明多重几何图元,你可以事先指明独立的顶点、法线、颜色和纹理坐标矩阵并且可以通过调用glDrawElements方法来使用它们创建序列图元。
当glDrawElements被调用,它会使用有序索引来查询可用矩阵中的元素,并以此创建序列几何图元,如果GL_VERTEX_ARRAY被禁用,则不会创建。
顶点属性由glDrawElements修改,glDrawElements在返回后会有一个未指明的值。举一个例子,如果GL_COLOR_ARRAY启用,当执行glDrawElements方法后,当前颜色的值是未定义的,属性不会维持它之前的值。
④ Initialization for Drawing, Shading
以下代码是init的后半部分。之前我们已经将物体摆放好了。
glGenBuffers(numperobj*numobjects, buffers) ;
initobject(FLOOR, (GLfloat *) floorverts, sizeof(floorverts), (GLfloat *) floorcol, sizeof (floorcol), (GLubyte *) floorinds, sizeof (floorinds), GL_POLYGON) ;
initobject(FLOOR2, (GLfloat *) floorverts2, sizeof(floorverts2), (GLfloat *) floorcol2, sizeof (floorcol2), (GLubyte *) floorinds2, sizeof (floorinds2), GL_POLYGON) ;
vertexshader = initshaders(GL_VERTEX_SHADER, "shaders/nop.vert") ;
fragmentshader = initshaders(GL_FRAGMENT_SHADER, "shaders/nop.frag") ;
shaderprogram = initprogram(vertexshader, fragmentshader) ;
函数学习:
注意,传的都是sizeof,是内存字节数,而不是数组元素个数。
initshaders函数和initprogram函数(上一课讲了的)是在这里调用的。