最近没有大的更新. 最近本来要做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插件更新,地形问题备忘的更多相关文章

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

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

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

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

  3. 引擎设计跟踪(九.9) 文件包系统(Game Package System)

    很早之前,闪现过写文件包系统的想法, 但是觉得还没有到时候. 由于目前工作上在做android ndk开发, 所以业余时间趁热做了android的移植, 因为android ndk提供的mountab ...

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

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

  5. 引擎设计跟踪(九.14.3.2) Deferred shading的后续实现和优化

    最近完成了deferred shading和spot light的支持, 并作了一部分优化. 之前forward shading也只支持方向光, 现在也支持了点光源和探照光. 对于forward sh ...

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

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

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

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

  8. 引擎设计跟踪(九.14.2c) 最近一些小的更新

    1. bump map与normal map 昨天拿了crytek sponza(http://www.crytek.com/cryengine/cryengine3/downloads)场景测试, ...

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

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

随机推荐

  1. iOS 数据模型 的 一般设计

  2. iOS数据持久化-SQLite数据库使用详解

    使用SQLite数据库 创建数据库 创建数据库过程需要3个步骤: 1.使用sqlite3_open函数打开数据库: 2.使用sqlite3_exec函数执行Create Table语句,创建数据库表: ...

  3. Objective-C 【autorelease基本使用】

    ------------------------------------------- NSString中的内存管理问题 由于autoreleasepool的存在,对于内存管理就会很复杂,retain ...

  4. AMQ学习笔记 - 10. Spring-JmsTemplate之浏览

    概述 浏览只是针对Queue的概念,Topic没有浏览.浏览是指获取消息而消息依然保持在broker中,而消息的接收会把消息从broker中移除. 浏览可以用来实现对Queue中消息的监控. JMS ...

  5. linux 系统运行级别及修改[转]

    Linux运行级别从0-6,共7个. 0:关机.不能将系统缺省运行级别设置为0,否则无法启动. 1:单用户模式,只允许root用户对系统进行维护. 2:多用户模式,但不能使用NFS(相当于Window ...

  6. (转)RabbitMQ消息队列(三):任务分发机制

    在上篇文章中,我们解决了从发送端(Producer)向接收端(Consumer)发送“Hello World”的问题.在实际的应用场景中,这是远远不够的.从本篇文章开始,我们将结合更加实际的应用场景来 ...

  7. Windows Phone 7 ListBox 列表项渐显加载动画学习笔记

    在wp7程序中,当程序功能越来越复杂时,性能问题是我们不得不考虑的一个问题.在聊天列表中,如果聊天项过多,而且项目UI组件足够复杂时, 我们不得不想尽办法让UI尽快加载.所以有一种可行的方案,就是像Q ...

  8. zedboard 构建嵌入式linux

    本文通过五部完成zedboard的嵌入式LINUX搭建,所谓磨刀不五砍材工嘛 1:系统环境搭建 要准备好交叉编译环境 见http://blog.csdn.net/xiabodan/article/de ...

  9. 转:关于Apache与Nginx的优势比较(经典)

    不断有人跟我说Nginx比Apache好.比Apache快之类.Nginx更主要是作为反向代理,而非Web服务器使用.我翻译过一本关于反向代理的技术书籍,同时精通Apache API开发,对Nginx ...

  10. C++安装失败解决办法

    法一:删除注册表中的HKY_LOCAL_MACHINE\\SYSTEM|ControlSet001\\Services\\VSS,卸载重装.法二:点击 setup目录下的 wpie15.exe ..  ...