引擎设计跟踪(九.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的支持, 只是簡單刷了一個地形, 沒有仔細去編輯:
https://drive.google.com/folderview?id=0B-jwAxcRPTTafk9JWEZGaklldk5GSkFSSHhDWkNwX2VUVUV1X1Y4Tjk4MEl0TkZVYklFMHc&usp=sharing
最近android的進度主要得益于工作上android的積累, 另外設計上一直以跨平臺為目標, 所以改動不是很大.
突然有想做indie game的沖動, 甚至有了一些移動端小型3D動作游戲的idea, 可惜現在積累還不夠. 后面如果有機會的話再做indiegame吧. 而且現在有了孩子, 考慮的因素也多了. 后面會放慢進度, 因為工作實在很忙, 業余也沒有太多時間.
轉載于:https://www.cnblogs.com/crazii/p/4355978.html
總結
以上是生活随笔為你收集整理的引擎设计跟踪(九.14.2i) Android GLES 3.0 完善的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浪漫的土耳其是谁唱的啊?
- 下一篇: 《梦断代码Dreaming In Cod