一种让程序支持多渲染器的方法

来源:互联网 发布:linux 查看防火墙端口 编辑:程序博客网 时间:2024/05/18 00:06

一种让程序支持多渲染器的方法

 

         在实际开发中,我们往往倾向于使用新的渲染器API进行图形的绘制,但是担心当部署到目标机器上时,由于硬件和显卡配置的限制而无法使用新的渲染器API。这可真让开发者们头疼。由于不同模型的格式不一样,渲染的方法也不尽相同,再加上渲染器的千变万化,让我们的工作量加大了很多!

         一种解决方案是使用游戏引擎来解决问题。本文并不是介绍究竟如何使用这些引擎,而是提出了一种自己的方案,通过为每一个渲染器写一个渲染处理器(render handler)来化解这性能和兼容性的矛盾。

         实例:我在开发的时候层考虑如果使用了在OpenGL1.5中提出来的VBO,那么移植到目标机器上时可能会抛弃那些并不支持OpenGL1.5规范的机器(因为可能显卡驱动没有安装等原因而无法支持OpenGL1.5规范)。不过使用glBegin()、glEnd()这样一个顶点一个顶点地添加的确会降低性能,想用VBO来提高性能。怎么办呢?

         使用C++的多态机制可以解决问题。根据多次游戏程序编写的经验,我发现一般资源都会经过初始化、使用和回收三个过程,所以我将这三个过程作为纯虚函数提炼出来。成为了IRenderHandler接口。

class IRenderHandler{public:   virtual void Init( void ) = 0;   virtual void Render( void ) = 0;   virtual void Release( void ) = 0;};

         IRenderHandler是一个接口类,它抽象了一段渲染过程,子类或实现可以重写这三个纯虚函数,做出不同的渲染效果。

         一个很简单的继承例子是,如果应用程序需要DirectX和OpenGL的支持,那么简单地继承这个接口成为两个顶级接口即可。

class IGLRenderHandler: publicIRenderHandler{ }; class IDXRenderHandler: publicIRenderHandler{ };

         更具体的情况,想要渲染各个模型,由于各个模型的渲染方式不一样,这样的情况必须再从中继承一个类以适应不同模型的渲染情况。

class MMDRenderHandler: publicIGLRenderHandler{public:   virtual ~MMDRenderHandler( void ) { }    ……   void Init( void )    {       ……    }protected:   QVector<quint16>           m_Indices;   QVector<Material>          m_Materials;   QVector<Texture2D>         m_Textures;   QVector<Bone>               m_Bones;   QString                     m_Dir;     ……};

         对于OpenGL1.1规范和OpenGL1.5规范,再从中继承两个类以实现不同OpenGL规范的渲染。

class MMDRenderHandler_1_1:       public MMDRenderHandler,       protected QOpenGLFunctions_1_1{         voidInit( void ){……}void Render(void ){……}void Release(void ){……}}class MMDRenderHandler_1_5:       public MMDRenderHandler,       protected QOpenGLFunctions_1_5{void Init( void){……}void Render(void ){……}void Release(void ){……}};

         我使用的是Qt,对于各种OpenGL规范,Qt为我们提供了各种程序集,我和大家一样,无法具体知道每一个函数是从OpenGL什么版本开始提供的,又有哪些函数从OpenGL什么版本开始消失的,还好Qt提供了QOpenGLFunctions_X_X这样的类,通过其保护继承可以让开发者知道在某个版本中OpenGL的函数是否可用,如果不可用,它会报编译错误(OpenGL1.1以及以前的函数除外)。

         在Qt中有一个非常方便的函数,可以判断当前系统支持的最高的OpenGL版本,它就是QGLFormat::openGLVersionFlags( )静态函数。我们使用一个指针(或智能指针)保存渲染处理器的地址,像这样:

QScopedPointer<MMDRenderHandler>m_pRenderHandler;

         根据系统环境来渲染的代码是:

// 看看OpenGL标准来决定渲染器if ( QGLFormat::openGLVersionFlags( ) &QGLFormat::OpenGL_Version_1_5 ){   m_pRenderHandler.reset( new MMDRenderHandler_1_5 );}else if ( QGLFormat::openGLVersionFlags( )& QGLFormat::OpenGL_Version_1_1 ){   m_pRenderHandler.reset( new MMDRenderHandler_1_1 );}

         在开发中,我接触过一游戏引擎,我看到它们对渲染器的封装很深,不过不外乎在渲染时有BeginRender()和EndRender()这样的函数。BeginRender()这样的函数我想意义在于将顶点缓存暴露出来供用户填充数据进来,而EndRender()函数则是结束用户的顶点输入,提交顶点。这里BeginRender()和EndRender()看起来和glBegin()、glEnd()的作用差不多,但由于一些特殊而高效的数据结构使得游戏引擎的执行效率很高。BeginRender()和EndRender()这对函数还包含了对渲染器代码的封装,使得使用跨渲染器的游戏引擎成为可能。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 tcl电视待机打不开怎么办 宽带电视看不了怎么办 电视总是闪退怎么办 电视出现系统更新怎么办 电视一直在更新怎么办 电视更新死机了怎么办 法院打电话不接怎么办 内向不敢辞职怎么办呀 生气后睡不着觉怎么办 被气得睡不着怎么办 一生气就睡不着怎么办 手机接电话声音小怎么办 发微信老公不回怎么办 欠钱没有欠条怎么办 朋友欠钱不还怎么办没欠条 个人欠销售货款怎么办 货款一直不还怎么办 欠钱不接电话找不到人怎么办 欠钱人电话不接怎么办 客户欠款不给怎么办 客户货款打一半怎么办 欠款人不到庭怎么办 别人打电话不接怎么办 百合注册被禁用怎么办? 监控显示未登录怎么办 发票认证了两次怎么办 拼多多账号异常怎么办 淘新闻账号异常怎么办 白领贷逾期了怎么办 用钱包信用不足怎么办 易借金app闪退怎么办 随心借不还款怎么办 苹果x来电显示慢怎么办 被垃圾短信轰炸怎么办 苹果手机被轰炸怎么办 苹果被短信轰炸怎么办 苹果电脑开不开机怎么办 苹果8plus黑屏怎么办 iphone7开不了机怎么办 苹果7自动黑屏怎么办 苹果手机黑屏打不开怎么办