引擎设计跟踪(九.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导出插件, 全部代码 ...
随机推荐
- HTML+CSS学习笔记(8)- CSS选择器
标签:HTML+CSS 什么是选择器? 每一条css样式声明(定义)由两部分组成,形式如下: 选择器{ 样式; } 在{}之前的部分就是"选择器","选择器"指 ...
- 对象-关系Metadata映射模式
MetaData Mapping元数据映射 在MetaData中保存object-relation映射的详细信息. 以表格形式定义映射,并可由通用代码来处理映射. 运行机制 MetaData中的信息如 ...
- 华丽的HTML5/jQuery动画和应用 前端必备
在网页应用中,我们经常会使用jQuery来实现一些简单的动画效果,比如菜单下拉时的渐变特效,图片滑动时的淡入淡出效果等.现在我们将jQuery和HTML5互相结合,让HTML5/CSS3强大的页面渲染 ...
- The Name/Origin of Country names
1.Puerto Rico (Spanish for "Rich Port"/富裕的港口/富港 ) 2.HongKong(Chinese for "香港")
- 1 。 LightOJ 1234 打表法(数据太大,把数据缩小100倍)
原题链接http://acm.hust.edu.cn/vjudge/contest/121397#problem/A Description In mathematics, the nth harmo ...
- 全面解析SQL SERVER 的左右内连接
SQL SERVER数据库的三种常用连接解析: 这里先给出一个官方的解释: left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右 ...
- 每天一个linux命令(1):which命令(转)
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate ...
- linux系统目录架构
/bin目录:可执行的二进制文件,shell命令(就是我们说的命令:cp ls ...),所有用户都有权执行. /boot目录:引导目录,整个操作系统启动所需的所有文件都在该目录下,其中最主要的就是v ...
- (转)汉字转拼音HanziToPinyin
本文转载于:http://blog.csdn.net/zhangphil/article/details/47164665 Android系统本身自带有有将汉字转化为英文拼音的类和方法.具体的类就是H ...
- Python-Day3 Python基础进阶之集和/文件读写/函数
一.集和 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 1.创建集合 >>> s ...