引擎设计跟踪(九.14.2i) Android GLES 3.0 完善
最近把渲染设备对应的GLES的API填上了. 主要有IRenderDevice/IShader/ITexture/IGraphicsResourceManager/IIndexBuffer/IVertexBuffer.
都是体力活, 根据文档(https://www.khronos.org/opengles/sdk/docs/man3/)填上对应的API就可了.
遇到的问题纪录在下面:
- 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), 因为没开警告, 所以没发现.
- C++standard并没有要求char必须是unsigned
- 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上都适用.
- Error: uniform variables in vertex shader do not fit in 256 vectors.
- 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的支持, 只是简单刷了一个地形, 没有仔细去编辑:
最近android的进度主要得益于工作上android的积累, 另外设计上一直以跨平台为目标, 所以改动不是很大.
突然有想做indie game的冲动, 甚至有了一些移动端小型3D动作游戏的idea, 可惜现在积累还不够. 后面如果有机会的话再做indiegame吧. 而且现在有了孩子, 考虑的因素也多了. 后面会放慢进度, 因为工作实在很忙, 业余也没有太多时间.
引擎设计跟踪(九.14.2i) Android GLES 3.0 完善的更多相关文章
- 引擎设计跟踪(九.14.2a) 导出插件问题修复和 Tangent Space 裂缝修复
由于工作很忙, 近半年的业余时间没空搞了, 不过工作马上忙完了, 趁十一有时间修了一些小问题. 这次更新跟骨骼动画无关, 修复了一个之前的, 关于tangent space裂缝的问题: 引擎设计跟踪( ...
- 引擎设计跟踪(九.14.2f) 最近更新: OpenGL ES & tools
之前骨骼动画的IK暂时放一放, 最近在搞GLES的实现. 之前除了GLES没有实现, Android的代码移植已经完毕: [原]跨平台编程注意事项(三): window 到 android 的 移植 ...
- 引擎设计跟踪(九.14.2h) 开发计划
以后的开发计划: 完善game runtime code, 跑简单的demo目前只有编辑器的运行流程, 没有游戏/demo流程, 图形的测试主要在编辑器上测试, 现在需要测试android系统的图形, ...
- 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio
最近在做纹理压缩工具, 以及数据包的生成. shader编译已经在vs工程里面了, 使用custom build tool, build命令是调用BladeShaderComplier, 并且每个文件 ...
- 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014
Origin: http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/ 简译 translation: 作者在2012年写 ...
- 引擎设计跟踪(九.14.2b) 骨骼动画基本完成
首先贴一个介绍max的sdk和骨骼动画的文章, 虽然很早的文章, 但是很有用, 感谢前辈们的贡献: 3Ds MAX骨骼动画导出插件编写 1.Dual Quaternion 关于Dual Quatern ...
- 引擎设计跟踪(九.14.3.4) mile stone 2 - model和fbx导入的补漏
之前milestone2已经做完的工作, 现在趁有时间记下笔记. 1.设计 这里是指兼容3ds max导出/fbx格式转换等等一系列工作的设计. 最开始, Blade的3dsmax导出插件, 全部代码 ...
- 引擎设计跟踪(九.14.2 final) Inverse Kinematics: CCD 在Blade中的实现
因为工作忙, 好久没有记笔记了, 但是有时候发现还得翻以前的笔记去看, 所以还是尽量记下来备忘. 关于IK, 读了一些paper, 觉得之前翻译的那篇, welman的paper (http://gr ...
- 引擎设计跟踪(九.14.2j) TableView工具填坑以及多国语言
Blade的UI都是预定义的接口, 然后由插件来负责实现, 目前只有MFC的插件. 最近加上了TableView的视图, 用于一些文件的查看和编辑, 比如前面在文件包的笔记中提到需写一个package ...
随机推荐
- PHP错误处理
错误的分类: 1.语法错误 2.运行时错误 3.逻辑错误 调试方法:1.注释法 2.输出法 error_reporting(E_ALL & ~E_NOTICE & ~E_WAR ...
- Python核心编程--学习笔记--6--序列(下)列表、元组
11 列表 类似于C语言的数组,但是列表可以包含不同类型的任意对象.列表是可变类型. 创建列表——手动赋值.工厂函数: >>> aList = [12, 'abc'] >> ...
- Ajax-goahead局部刷新页面
软件开发最常用的方法是:C/S,B/S.如果嵌入式设备中使用Ajax,那么既可以使用C/S方式,也可以使用B/S开发上位机.最近公司的一个项目需要异步获取后台数据,使用form更新数据时会有空白卡顿不 ...
- Cron表达式说明
CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表. CronT ...
- Python pexpect出现错误‘module have no attribute "spawn" 解决办法
今天我遇到了这个错误,现在将错误总结如下: 1.首先查询一下自己的操作系统,pexpect中的spawn()和run()仅仅运行在POSIX系统上,在WINDOWS下是没有这两个东西的,在官网http ...
- poj 3625 Building Roads
题目连接 http://poj.org/problem?id=3625 Building Roads Description Farmer John had just acquired several ...
- hdu 5154 Harry and Magical Computer
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5154 Harry and Magical Computer Description In reward ...
- Go字符串函数
下面的代码中,列出了Go官方包中常见的字符串函数. package main import s "strings" import "fmt" //为打印函数起个 ...
- base64和图片的互转(HTML5的File实现)
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- SQL中一种类似GUID值的函数实现
开发中会需要用到多列值组合成一个ID值的情况.比如做数据清洗的时候,一张表A有五列,分别是医院.科室.医生.职称.电话.面有许多重复的数据需要和另一个表B(和A列相同)做对比.清洗需要做两件事 ...