引擎设计跟踪(九.10) Max插件更新,地形问题备忘
最近没有大的更新. 最近本来要做max的骨骼/动画导出, 看导出插件代码的时候, 突然想起之前tagent space导出的疑问, 于是确认了一下.
http://www.cnblogs.com/crazii/archive/2013/04/03/2997601.html
同时在网上找到了一个很明显的带有镜像UV的模型, 进行了测试.
使用该模型顺便发现了float16 (IEEE 754-2008 16 bit floating point format)即半精度浮点数 (http://en.wikipedia.org/wiki/Half_precision), 我的实现方式的bug: 由于使用了简单的位运算,
没有处理overflow和underflow的情况, 导致float32 => float16转换过程中数值溢出.
遇到的情况是一个很小的数(比如1e-6)转到float16时underflow, 正确值应该转为0, 但是由于没有处理这种情况, 导致转换的结果为-300多.
本来导出的模型有部分顶点被拉伸错位, 当时没有想到是这个原因, 在导出插件里加了很多isnan()检测和AABB越界检查, 以及flaot16跟float32的转换后比较, 最后发现是以上的原因.
最后干脆使用OpenEXR的half (https://github.com/openexr/openexr/blob/master/IlmBase/Half/half.h),
问题解决. OpenEXR的half实现是用了内建表加速转换, 具体细节没怎么看, 只看到对于half=>single presicon使用了65536个表项的表(静态数组)做全值映射.
导出的tangent space使用quaternion保存,这个之前测过没有问题. 但镜像贴图仍然有缝, crytek的pdf说tangent space的mirror模式缝很难避免, 只能通过好的tangent space生成算法来尽量改进.
这个模型是Gear of War3里面的模型, 除了面部没有使用镜像UV, 其他地方都用了. 可以看到中间是有缝的, 脖子下面有个倒L行的裂缝最明显(镜像UV到面部非镜像的过渡), 这个裂缝在贴了base map以后还可以看到(这个在MAX 2013 shaded模式里面也能看到), 而其他地方的缝, 带上贴图的时候不是特别明显, 除了离的非常近才能看到一点. 试了crytek(ShaderX4中)的方法(http://www.shaderx4.com/TangentSpaceCalculation.h),效果还是没太大改进. 打算暂时先这样吧, 以后找时间专门研究下.
然后无意间在地形渲染里发现一个严重的问题(可能上次地形更新后没有测这些-_-!), 原因已经找到, 但是不太好改:
由于上次的地形更新(http://www.cnblogs.com/crazii/archive/2013/06/01/3085449.html),
使用了layermap带替代per vertex layer buffer, 这个时候blendmap要跟layermap的纹素精确的的匹配.
如果有3张贴图,分别为A(红色贴图),B(白色贴图),C(绿色贴图) 的时候, 索引为 0, 1, 2; (蓝色半透部分为画刷)
2张贴图A,C的时候 索引为0, 2;
blendmap的混合通道为: Red, Green, Blue. Red对应第一张图即底图.
内圆有三张贴图的部分, Green通道权重为0(不显示贴图B). Blue通道为1对应贴图C,
外圆有两张贴图的部分, Green通道权重为1(全显示),对应贴图C. 所以Green通道在边缘处对应的两张贴图不一样, 通过blend weight的线性差值后, 内圆边缘处Green通道本来应该不显示的贴图B的, 但差值后中间有一部分不是0,导致边缘有缝隙.
layermap使用pointer sampling, 因为layermap保存的是atlas贴图的索引, 不能做线性插值, 否则索引就坏掉了. 如果blendmap改用point过滤(layermap, blendmap的精确匹配), 可以解决这个问题, 但是混合效果太丑, 有马赛克, 无法接受.
想了一下, 上次更新之前没,还没有问题, 是因为per vertex layer buffer实际上是per block(chunk), 即一个block上所有的vertex的layer都一样(有点浪费), 只有block之间的接缝处才有这样的问题, 而且之前blendmap的uv是预先计算的顶点数据, 在block边缘做了半个像素的偏移, 避免采样到邻接block, 所以没有缝.
现在layermap不是per block了,而是精确到每一个纹理元素, 而且没有规律, 不能做像素偏移. 即便把layermap改成per-block的精度, 但现在blendmap的UV已经没有vertex buffer, 而是在shader里面根据位置计算算, 两个block衔接处的顶点位置是一样的, 不知道是哪个block的哪一边, 确定不了偏移方式.所以没有办法在shader里做半像素的uv偏移. 除非这部分退回以前的方式, 使用vertex uv buffer保存blend map uv.
这个问题很恶心, 主要是使用了atlas以后, 还想支持一个draw call的batch合并, 产生的各种问题, 为了渲染正确, 已经做了不少work around了, 现在感觉很难处理.
目前打算把layer map做成per block,跟以前一样, 这样缝的问题只出现在block边缘, 然后的处理方式就比较多. 一种方法跟以前一样, 处理blendmap uv的偏移, 需要占用额外的内存/现存. 另一个方法是像WOW一样, blendmap也是per block, 这样就采样不到邻接block, 但是改动可能有点大, 而且这样block就不能合并draw call了. 魔兽世界地形的chunk是可以(根据情况)合并的因为他没有用atlas, 我这里用了atlas图集, 并且要支持batch合并.
还有一个方法是把blendweight放到vertex buffer里面, 由于每个block之间没有共享顶点, 不会有blend weight插值. 但这样纹理混合的精度有所损失,而且没有之前那样,精度可控(只要调整blend map的大小即可).
需要先考虑清楚有没有更好的办法, 再动手改. 后面可能先做骨骼动画的导出(mile stone 2的key feature, 拖了一年了), 也有可能先把这个问题修好.
更新:
尝试在shader里面使用bilinear采样, 代替硬件采样, 这个时候可以做一些特殊处理, 但效果不是特别好, 仍然有不明显的缝存在.
突然想起来, 如果layermap是per block的话, 没必要对一个block按顶点来保存一大块一模一样的数据, 把这一样的数据块合成一个像素, 采样出来的效果一样, 这样起码没有浪费.
更新2: 目前使用shader里面手动bilinear采样, 代替硬件采样的方式, 通过调整一些参数, 勉强可以了. 但是pixel shader多了20条指令(目前-O3已经达到190条左右), 其中有五条tex2D纹理采样. 低材质LOD的直接用点采样吧, 虽然能看到马赛克, 但是已经有点远了, 应该不是特别需要处理, 如果需要的话也用这种方式.
经过简单对比, 感觉效率比以前低了,之前的debug版, 一个512x512的tile, 在380-400FPS左右, 现在大约300-340FPS, 降低了50-60FPS的样子.
如果退回跟以前类似的的方式, 顺便把layermap处理一下, 按最大的tile大小512, 按最小的block大小为16, 而一个block对应一个像素, 则layermap 最大为 64*64*16(R4G4B4A4) 字节, 比以前小很多.blendmap的uv要加vertex stream并且预处理边界, 或者不添加顶点数据, 在现有的顶点数据里存一个标记, 在shader里面处理. 但现在不是很想改, 主要是因为那样改动太大, 而现在的改法, 改动很小. 所以目前暂时先这样吧, 也许对速度的影响不是特别大, 这次先记录下来, 以后如果真的不行, 可以再改.
引擎设计跟踪(九.10) Max插件更新,地形问题备忘的更多相关文章
- 引擎设计跟踪(九.14.2a) 导出插件问题修复和 Tangent Space 裂缝修复
由于工作很忙, 近半年的业余时间没空搞了, 不过工作马上忙完了, 趁十一有时间修了一些小问题. 这次更新跟骨骼动画无关, 修复了一个之前的, 关于tangent space裂缝的问题: 引擎设计跟踪( ...
- 引擎设计跟踪(九.14.2f) 最近更新: OpenGL ES & tools
之前骨骼动画的IK暂时放一放, 最近在搞GLES的实现. 之前除了GLES没有实现, Android的代码移植已经完毕: [原]跨平台编程注意事项(三): window 到 android 的 移植 ...
- 引擎设计跟踪(九.9) 文件包系统(Game Package System)
很早之前,闪现过写文件包系统的想法, 但是觉得还没有到时候. 由于目前工作上在做android ndk开发, 所以业余时间趁热做了android的移植, 因为android ndk提供的mountab ...
- 引擎设计跟踪(九.14.2j) TableView工具填坑以及多国语言
Blade的UI都是预定义的接口, 然后由插件来负责实现, 目前只有MFC的插件. 最近加上了TableView的视图, 用于一些文件的查看和编辑, 比如前面在文件包的笔记中提到需写一个package ...
- 引擎设计跟踪(九.14.3.2) Deferred shading的后续实现和优化
最近完成了deferred shading和spot light的支持, 并作了一部分优化. 之前forward shading也只支持方向光, 现在也支持了点光源和探照光. 对于forward sh ...
- 引擎设计跟踪(九.14.2 final) Inverse Kinematics: CCD 在Blade中的实现
因为工作忙, 好久没有记笔记了, 但是有时候发现还得翻以前的笔记去看, 所以还是尽量记下来备忘. 关于IK, 读了一些paper, 觉得之前翻译的那篇, welman的paper (http://gr ...
- 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio
最近在做纹理压缩工具, 以及数据包的生成. shader编译已经在vs工程里面了, 使用custom build tool, build命令是调用BladeShaderComplier, 并且每个文件 ...
- 引擎设计跟踪(九.14.2c) 最近一些小的更新
1. bump map与normal map 昨天拿了crytek sponza(http://www.crytek.com/cryengine/cryengine3/downloads)场景测试, ...
- 引擎设计跟踪(九.14.3.4) mile stone 2 - model和fbx导入的补漏
之前milestone2已经做完的工作, 现在趁有时间记下笔记. 1.设计 这里是指兼容3ds max导出/fbx格式转换等等一系列工作的设计. 最开始, Blade的3dsmax导出插件, 全部代码 ...
随机推荐
- hdu 1716(dfs)
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=1716 排列2 Problem Description Ray又对数字的列产生了兴趣:现 ...
- 【leetcode】15. 3Sum
题目描述: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...
- 解析XML文档之二:使用PULL解析
第一步:解析文档为一下文档 <?xml version="1.0" encoding="UTF-8"?> <students> < ...
- poj 3669 Meteor Shower
Me ...
- 《LDAP服务器和客户端的加密认证》RHEL6——第二篇 运维工程师必考
服务端的配置: (基于原先配好的ldap服务器)打开加密认证: Iptables –F setenforce 0 1.编辑ldap的配置文件:slapd.conf 2.启动ldap服务器: 3.切换 ...
- Allegro设置十字大光标
使用大十字光标,在摆放元器件时,容易对齐.在allegro中,可以通过设置实现大十字光标,其具体方法如下: 1.选择Setup->User Perferences,即可出现如下图所示界面: 2. ...
- Java应用短信猫
首先确定短信猫正常连接到主机,并安装SIM卡.先用超级终端测试短息猫能不能用.安装minicom:#sudo apt-get install minicom安装完成后,执行#sudo minicom ...
- 【Qt】Qt Assistant介绍【转】
简介 Qt Assistant也就是我们常说的Qt助手,是一款用于呈现在线文档的工具. 简介 一分钟学会使用 Qt参考文档 Qt Assistant详解 命令行选项 工具窗口 文档窗口 工具栏 菜单 ...
- thymeleaf 局部变量、属性优先级、注释
九.局部变量(local variable) 之前在th:each中遇到过局部变量 <tr th:each="prod : ${prods}"> ... </tr ...
- Gulpfile.js——编译、压缩、合并js和css文件
gulp 一个入门教程:http://www.ydcss.com/gulp API文档地址:http://www.gulpjs.com.cn/docs/api/ 我的一个Low版的gulpfile v ...