跨平台显示MMD模型
过年了,祝大家喜气洋洋,心想事成!
然后呢,过年后,依然进行Qt以及3D的研究。最近翻出以前的技术研究成果,并且花了将近一个月,成功地在移动平台上显示MMD模型了。
蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43912325。欢迎同行前来探讨。
首先,花了几周的时间,将MMD模型脚本化,也就是说,可以使用QML定义一个MMD类,指定参数即可显示。这里的移植参照了以前写QML和C++混合的经验,写起来还算好,不过有的时候也有很多波折。
接着,在以前的研究中,我实现了带光照渲染模型的方法,当时写了两篇博文:
这两篇博文介绍了将三种光源应用到模型的渲染中。当时的着色器只是适应了桌面的运行环境,没有考虑移动的环境,而且使用的框架是Qt Graphics-View,在移动平台上不可行,必须换成Qt推荐的Qt Quick框架才行。于是我做了很多论证,为此在第二个独立游戏完成后,就开始相关的前期论证中。为此我也写了一些博文:
然后呢,感觉从Scene Graph这个层级进行3D模型的显示,有一些不方便,比如说clip frustum的zNear和zFar是根据Item的堆叠个数决定的,如果zFar– zNear过小,那么模型显示不全,会被裁掉。所以放弃了Scene Graph,直接寻求原生的OpenGL在Qt Quick中的渲染。一开始是让我的渲染框架依赖QtQuick的,让相关类继承QQuickItem,但是发现QQuickItem可能比较复杂,类比较大,后面也尝试让相关类直接继承QObject,后面折腾了很久default属性,最后发现直接继承QObject,竟然无法实现Animation那一套框架,而QQuickItem轻而易举地就能实现了。这里面的技术细节真的很深啊……后面还是老老实实地回到继承QQuickItem中来了。也就是说,现在的框架是依赖Qt Quick的。
最后在移植的时候,着色器也是必须要考虑的。在OpenGL ES 2上,对有些类型的变量(uniform、varying的)一定要指定精度。好在Qt有预处理符号,在运行环境不支持highp的时候,我们写的highp会转化为mediump,所以我在着色器中,需要指定精度的地方一律指定了highp。而在WindowsPhon 8.1的移植上,由于Qt使用ANGLE对GLSL进行转化,我觉得这其中的capability是降低的,我尝试调用了glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_maxAttribute );和glGetIntegerv(GL_MAX_VARYING_VECTORS, &m_maxVarying );,发现在我的Lumia 530,maxAttribute为16(正常),maxVarying只有6(不正常)。按照OpenGLES 2的规定,maxVarying最小为8。所以我写的那个光照处理的着色器代码使用了超过6的varying。因此在链接的时候出现了“Could not pack varying spotAmbient”的问题。于是我只好删除了处理光照的代码,保留剩下的部分。我想,光照的处理和细节的展示,以后可能通过延迟渲染来处理。最一个最简单的版本,先不要光照好了。
在研究之中,得知Qt 3D的消息,又开始研究Qt3D了。Qt 3D的确很不错,采用data driven的方式来解决颇为头疼的渲染问题,而且从OpenGL1.0一直支持到最高的规范。这是非常不容易的。不过,现在在移动平台上的效果如何,现在不得而知。这段时间也写了几篇Qt 3D的文章,看来Qt 3D还是需要长期关注的。
最后献上我在我的笔记本计算机(Windows 8.1)、台电A10HD(Android)以及Lumia 530(Windows Phone 8.1)机器的运行截图:
动作这方面代码方面已经移植了,只是还未进行测试。
原文地址:http://blog.csdn.net/gamesdev/article/details/43912325