最近把渲染设备对应的GLES的API填上了. 主要有IRenderDevice/IShader/ITexture/IGraphicsResourceManager/IIndexBuffer/IVertexBuffer.
都是体力活, 根据文档(https://www.khronos.org/opengles/sdk/docs/man3/)填上对应的API就可了.
遇到的问题纪录在下面:

  1. Stick to the standard

    • C++standard并没有要求char必须是unsigned
      typedef char uint8; 发现这个在gcc上 uint8是带符号的, 于是改为 typedef usigned char uint8;
    • 使用标准库函数. MSVC上有abs(float) 函数, 在android上跑的时候发现数学计算有问题, 最后追到这个函数
      原来gcc没有abs(float), 查了下标准 (http://www.cplusplus.com/reference/cstdlib/abs/?kw=abs), 标准确实没有, 只有fabs(). gcc下会自动匹配abs(int), 因为没开警告, 所以没发现.
  2. Vertex Shader 编译错误:
    • Error: uniform variables in vertex shader do not fit in 256 vectors.
      GLES3.0的vertex shader uniform最少也是256. 这个很奇怪. 因为blade的骨骼动画是按照VS3.0的最低要求(256 registers)来写的, shader里面float2x4[120] 用了240个寄存器, 还有2个matrix44, 是8个寄存器.总数248应该没有超. 目前暂时把骨骼数量改为110.
    • 另外DQ动画上, HLSL的float2x4在转成GLSL时, hlsl2glsl 对其做了转置, 所以是float4x2, 这样就用掉了4个寄存器. 解决方法是直接用float4数组, 这样在D3D和GLES上都适用.
  3. GLES 的适配:
    GL的sampler属性默认是绑定在贴图上的. (glTexParameter), 这个跟D3D9的sampler state 有所不同, 幸好GLES3.0有sampler object glGenSamplers/glBindSampler/glSamplerParameter 可以实现和d3d一样的设置方式.
    整体上GLES.30没有遇到大的问题, 主要是因为去年工作上的积累, 所以实现起来比较快.

目前blade的地形和DQ动画都可以跑在android真机上了, 关于这两个模块, 动画没有做任何适配, 除了某些设备上的bug的特殊workaround.

简单记录一下地形的问题:

  • 压缩贴图不能更新部分区域, 或者部分更新有限制( glCompressedTexSubImage ), 而d3d上可以直接lock压缩贴图来更新局部区域. 这样在composite altas的时候会报错. 解决方法不难, 用Image接口(soft buffer)先合并好, 最后一次性上传, 这个方式对于GL/ES和D3D都适用. 而android上的runtime没有编辑模式, 所以不会有动态更新.
  • 在测试的android设备上地形的批次合并变慢, 估计额外的带宽太大. 所以在android上把批次合并关了. 这个只需要改配置文件, 因为批次合并本来在windows上就是可以运行时配置, 并保存到配置文件的.
  • android上的地形纹理从 512x512改成256x256, 对于一个4x4的atlas, windows上贴图大小是2048x2048, android上是1024x1024. 给BladeTexCompressor加上了scale参数, 同时给地形模块添加了额外的配置参数:texture size, 以便于动态适配.
  • 另外为了效率, 地形的detail normal也暂时关了, 因为detail normal用的是atlas normal map, 会多4次采样.

其他一些更新:

  • 加入了arm的NEON SIMD,这个是拿的DirectXMath的代码, 之前做SSE的时候已经加入了, 但是没打开NEON, 这次把它调通, 做一些修改和适配.
  • 加入了message box. 因为message box是IPlatformManager的feature, 在windows上直接调用API, android上需要JNI调用java来适配. 需要注意的是这个java文件也是放在platform level, 跟具体的project无关, 只需要最终build apk的时候复制到java的src下面.
  • shader precompile: 这个之前提到过, 在app level加上一个event handler, 加载包内的所有shader, 并保存为binary格式, 存储到本地文件夹, 并将"shader:/"路径切换为本地路径. 要注意很多细节.比如比如编译shader需要在GLES初始化以后才能做, 这个幸好blade有一个render device ready的事件. 遇到的问题是所有shader的预加载也是处理的这个事件, 而shader加载必须要在shader-precompiling结束后才能正确执行. 所以这两个handler有顺序冲突.这个问题可以抽象为event handler的调用顺序问题, 因为handler在内部存储/调用的顺序是不确定的, 导致同一个event的多个handler的调用顺序是undefined. 记得工作的时候, 第一个项目也遇到类似的问题, 当时是根据注册的顺序来调用. 但是现在觉得, 这样相当于两个不想干的模块有了注册顺序上的弱耦合, 而且注册顺序难以控制, 不是很好. 现在的做法是加了优先级, 同一个优先级的handler调用顺序不确定, 但是优先级不同的, 调用是有顺序的.因为顺序碰撞的情况比较少, 所以用几个优先级就可以了.将shader pre-complie设置为最高优先级, 这样就可以在GLES初始化以后第一时间编译shader, 具体如何判断shader是否需要重编译也有点繁琐, 需要对比文件个数, 时间戳等等, 这里就不纪录了.

目前在Adreno 330 上的release build, 一个512x512的地形, 可以跑30-50FPS, 某些设备是30, 某些是50. 具体还没有时间去profille, 猜测效率瓶颈可能有两个, 一个是顶点/三角形数量, 另一个是atlas是在fragment shader里面要动态计算uv, 并且需要多次纹理采样.

个人觉得如果架构本身支持多平台抽象, 那么平台移植的工作量不大, 主要工作量应该是在优化上. 一个真正可用的引擎不仅仅是能跑起来就可以了.

下面贴一个地形demo的apk和obb吧, 可以在真机上运行, 需要GLES3.0的支持, 只是简单刷了一个地形, 没有仔细去编辑:

https://drive.google.com/folderview?id=0B-jwAxcRPTTafk9JWEZGaklldk5GSkFSSHhDWkNwX2VUVUV1X1Y4Tjk4MEl0TkZVYklFMHc&usp=sharing

最近android的进度主要得益于工作上android的积累, 另外设计上一直以跨平台为目标, 所以改动不是很大.

突然有想做indie game的冲动, 甚至有了一些移动端小型3D动作游戏的idea, 可惜现在积累还不够. 后面如果有机会的话再做indiegame吧. 而且现在有了孩子, 考虑的因素也多了. 后面会放慢进度, 因为工作实在很忙, 业余也没有太多时间.

引擎设计跟踪(九.14.2i) Android GLES 3.0 完善的更多相关文章

  1. 引擎设计跟踪(九.14.2a) 导出插件问题修复和 Tangent Space 裂缝修复

    由于工作很忙, 近半年的业余时间没空搞了, 不过工作马上忙完了, 趁十一有时间修了一些小问题. 这次更新跟骨骼动画无关, 修复了一个之前的, 关于tangent space裂缝的问题: 引擎设计跟踪( ...

  2. 引擎设计跟踪(九.14.2f) 最近更新: OpenGL ES & tools

    之前骨骼动画的IK暂时放一放, 最近在搞GLES的实现. 之前除了GLES没有实现, Android的代码移植已经完毕: [原]跨平台编程注意事项(三): window 到 android 的 移植 ...

  3. 引擎设计跟踪(九.14.2h) 开发计划

    以后的开发计划: 完善game runtime code, 跑简单的demo目前只有编辑器的运行流程, 没有游戏/demo流程, 图形的测试主要在编辑器上测试, 现在需要测试android系统的图形, ...

  4. 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio

    最近在做纹理压缩工具, 以及数据包的生成. shader编译已经在vs工程里面了, 使用custom build tool, build命令是调用BladeShaderComplier, 并且每个文件 ...

  5. 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014

    Origin: http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/ 简译 translation: 作者在2012年写 ...

  6. 引擎设计跟踪(九.14.2b) 骨骼动画基本完成

    首先贴一个介绍max的sdk和骨骼动画的文章, 虽然很早的文章, 但是很有用, 感谢前辈们的贡献: 3Ds MAX骨骼动画导出插件编写 1.Dual Quaternion 关于Dual Quatern ...

  7. 引擎设计跟踪(九.14.3.4) mile stone 2 - model和fbx导入的补漏

    之前milestone2已经做完的工作, 现在趁有时间记下笔记. 1.设计 这里是指兼容3ds max导出/fbx格式转换等等一系列工作的设计. 最开始, Blade的3dsmax导出插件, 全部代码 ...

  8. 引擎设计跟踪(九.14.2 final) Inverse Kinematics: CCD 在Blade中的实现

    因为工作忙, 好久没有记笔记了, 但是有时候发现还得翻以前的笔记去看, 所以还是尽量记下来备忘. 关于IK, 读了一些paper, 觉得之前翻译的那篇, welman的paper (http://gr ...

  9. 引擎设计跟踪(九.14.2j) TableView工具填坑以及多国语言

    Blade的UI都是预定义的接口, 然后由插件来负责实现, 目前只有MFC的插件. 最近加上了TableView的视图, 用于一些文件的查看和编辑, 比如前面在文件包的笔记中提到需写一个package ...

随机推荐

  1. 使APP消除上方手机消息提示栏(显示WIFI,信号格那栏)消失的方法

    public void toggleFullscreen(boolean fullScreen) { // fullScreen为true时全屏,否则相反 WindowManager.LayoutPa ...

  2. 【easyui】--普通js中获取easyui中分页信息(page,pageSize等)

    对于datagrid,获取其分页信息: 方法: var pageopt = $('#list_data').datagrid('getPager').data("pagination&quo ...

  3. 下一代NoSQL:最终一致性的末日

    相比关系型数据库,NoSQL解决方案提供了shared-nothing.容错和可扩展的分布式架构等特性,同时也放弃了关系型数据库的强数据一致性和隔离性,美其名曰:"最终一致性". ...

  4. Linux之kernal分析与启动20160610

    说一下LINUX内核的分析与启动: 一. 内核启动流程,据此配置内核(机器ID) 1.1 修改Makefile 1.2 选择默认配置 : make s3c2410_defconfig 1.3 make ...

  5. JQuery中ajax跨域问题

    var url = "http://apis.juhe.cn/idcard/index?key=e0a6277420506b2816b82f7d7821976c&cardno=&qu ...

  6. StyleCop学习笔记——初识StyleCop

    一.定义 StyleCop是微软的一个开源的静态代码分析工具,检查c#代码一致性和编码风格. 二.支持的环境. JetBrains R# 5.1.3 ( 5.1.3000.12) JetBrains ...

  7. linux 下的使用 ln 创建 软链接 和 硬链接

    linux 下的一个指令 ln 作用: 创建软链接或者硬链接 Linux 系统下每创建一个文件,系统都会为此文件生成一个 index node 简称(inode) ,而每一个文件都包含用户数据(use ...

  8. Oracle ClusterwarePRCT-1011 : Failed to run "oifcfg".&nb

    OS: Oracle Linux Server release 6.3 DB: Oracle 11.2.0.3 在oracle-linux6.3安装11g RAC,在安装软件时候提示: An inte ...

  9. chkconfig 命令详解

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法: chkconfig [--a ...

  10. 019C#中使用移位运算符获取汉字编码值

    在进行移位运算时,当数值的二进制数每次向左移1位就相当于乘以2,当数值每次向右移一位就相当于除以2 private void button1_Click(object sender, EventArg ...