天天看点

蔡军生先生第二人生的源码分析(五十五)OpenGL的API函数管理

对于高性能的3D游戏显示,目前在世界上流行的就两套API,一套是OpenGL,一套是微软的D3D。由于OpenGL跨平台的特性,对于第二人生来说,是没有别的选择了。那么在第二人生里渲染管道到底是怎么样调用OpenGL函数的呢?又有什么特别的方式可以让调用OpenGL更加方便呢?由于OpenGL并不是基于C++的接口,所以在第二人生里就肯定先把这些API组织成类的方式,才会更方便使用。下面就来仔细地分析类LLGLImmediate,它的声明如下: #001  #002 class LLGLImmediate #003 { #004 public: #005       LLGLImmediate(); #006    下面函数通过当前矩阵乘以参数构造的平移矩阵实现平移功能。 #007       void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);   下面函数把当前矩阵压入到栈里,避免当前的操作对当前的矩阵下一次使用有影响。 #008       void pushMatrix();   下面函数把栈顶里的矩阵取出来,恢复前面保存的矩阵。 #009       void popMatrix();   下面函数指明像素混合的方式。 #010       void blendFunc(GLenum sfactor, GLenum dfactor);   下面函数指明一帧图片渲染开始。 #011       void start();   下面函数指明一帧图片渲染结束。 #012       void stop();   下面函数指明OPENGL一帧图片渲染生效。 #013       void flush(); #014    下面两个函数指明OPENGL一帧图片渲染开始和结束。 #015       void begin(const GLuint& mode); #016       void end();   下面的函数都是指明顶点。 #017       void vertex2i(const GLint& x, const GLint& y); #018       void vertex2f(const GLfloat& x, const GLfloat& y); #019       void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z); #020       void vertex2fv(const GLfloat* v); #021       void vertex3fv(const GLfloat* v); #022         下面的函数指明纹理坐标位置。 #023       void texCoord2i(const GLint& x, const GLint& y); #024       void texCoord2f(const GLfloat& x, const GLfloat& y); #025       void texCoord2fv(const GLfloat* tc); #026    下面的函数都是指明当前顶点的颜色。 #027       void color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a); #028       void color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a); #029       void color4fv(const GLfloat* c); #030       void color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b); #031       void color3fv(const GLfloat* c); #032       void color4ubv(const GLubyte* c); #033  #034       // switch clever mode GL immediate rendering on or off. Setting to true builds #035       // client arrays manually, setting to false passes through the GL immediate mode #036       // commands to the GL implementation. Controllable by the RenderUseCleverUI #037       // debug setting. #038       // *NOTE: I have measured that this has about a 9% performance cost (0.6ms) for the #039       // Render/UI fasttimer vs the old #if CLEVER compile time switch. Dave Parks and I #040       // agreed that this was acceptable at the time due to it enabling better regression #041       // testing for QA. #042       // -Brad   下面指明是否使用顶点缓冲区来优化对API的操作,主要减少对API的操作,这样可以提高速度。 #043       void setClever(bool do_clever); #044  #045       typedef struct Vertex #046       { #047              GLfloat v[3]; #048              GLubyte c[4]; #049              GLfloat uv[2]; #050       }; #051  #052 private: #053       static bool sClever; #054  #055       U32 mCount; #056       U32 mMode;   自己定义的顶点缓冲区,以便保存数据,最后一次性里设置到OPENGL里。 #057       Vertex mBuffer[4096]; #058 };   通过上面的函数,学会了怎么样封装OPENGL的API函数,并且提出了使用缓冲区的方法来提高渲染速度。在第二人生渲染管道里会不断地调用这个类的函数来操作OPENGL,这样比较容易维护,也达到更加容易使用的目的,并且全局只一个渲染对象。

继续阅读