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

时间:2022-09-17 19:45:48

1. bump map与normal map

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

一开始用的是这里的模型(http://graphics.cs.williams.edu/data/meshes.xml)发现里面用到了1通道的bumpmap, 但是blade的shader并不支持, 如果要支持的话又要加材质和shader了, 所以用了这种hack, 只为了跑一下这个场景.

bumpmap是单通道的灰度图, 实际上是一张高度图, 在shader里面可以根据高度差得到法线扰动. 而法线贴图是切空间的相量.

bump map是对法线的偏移和扰动, 而normal map则是对法线的完全的替换.

法线贴图可以有两种途径产生, 一是高模烘焙, 二是通过高度图生成.第二种方法nvidia的photoshop插件里面就有(https://developer.nvidia.com/nvidia-texture-tools-adobe-photoshop).

原理不多说了,这里有个链接:

凹凸贴图(Bump Map)实现原理以及与法线贴图(Normal Map)的区别

bump map到normal map转换的方法从上面链接中的shader里面可以看出来, 即用高度图中的的导数dx, dy来构造法线. 下面是一个参考(原帖是有错误的求助帖, 回复中有SOBEL filter的代码片段):

https://www.opengl.org/discussion_boards/showthread.php/168864-HeightMap-to-NormalMap

更多的参考在这里(GIMP的法线贴图插件, 各种各样的, nxn的filter啊):

https://code.google.com/p/gimp-normalmap/source/browse/trunk/normalmap.c

目前blade使用了3x3的SOBEL filter. 这个转换只有实时转换用到了, 但理论上后台工具也可以直接用.

下面是用blade的导出插件导出的cretek sponza场景, 并在model viewer里面查看的效果, 后面做场景渲染效果的时候可以暂时先拿它来测试:
 引擎设计跟踪(九.14.2c) 最近一些小的更新

这个场景比较复杂, 用它测试max导出插件, 也发现了在导出切空间时的某些bug, 比如计算切空间时, 三角形两个边的向量, 是带长度的向量, 不能单位化, 否则对于狭长的三角形, 计算错误会暴露出来.

另外,与话题无关的, 还有两个诡异的问题, 上面的两个模型(.obj)在max里都是这样: 一个材质sponza_bricks, 它的diffuse map和normal map是同一张diffuse贴图: spona_bricks_a_diff.tga, 但是明明有对应的法线贴图文件在啊, 而且用这个导出模型的话, 渲染结果明显不对, 害得又被坑了, 改成正确的贴图就好了.

而且贴图明明含有specular map, 但是材质里面又没有设置specular map, 这个我也暂时没管了.

2.通过上面的模型, 也测试出了几个material LOD的几个小bug:

a.虽然模型系统的材质是以单个子mesh为单位更新的,但是子mesh交给materialLOD updater的世界坐标, 是父model的坐标, 即所有的子mesh都使用的相同的坐标. 这样如果一个model太大, 位置的精度会有问题, 现已改为子mesh真正的世界坐标, 这样材质LOD的精度真正达到单个子mesh级别.

b.判断材质LOD的距离, 之前用的是相机和物体中心之间的距离.当物体非常大的时候, 相机已经在物体的内部了, 但是距离物体中心还很远, 导致LOD切换出了问题, 这个需要用距离减去物体半径(虽然接口已经定义了半径/AABB但是一直没有用).

c.有的submesh有多个部件, 而且相距很远(比如场景的两端),但是他们属于同一个submesh(共享同一个材质), 导致这个submesh非常大, 相机一直在其内部. 这样的材质LOD更新粒度太大, 导致材质LOD没有机会切换. 这个要改导出插件. 因为现在的导出方式是按材质划分submesh, 合并材质相同的object, 这个需要改为按material + object划分出submesh, 相同material的object分开导出而不合并. 只要material相同的object在导出时, 分开的多个submesh连续在一起, 同时在渲染时按顺序绘制. 这样与之前相比, 从一个材质对应一个drawcall, 变成一个材质对应多个连续drawcall, 结果将是多几个drawcall, 也没有多余的材质切换, 是可接受的折衷方案.

3.UV坐标系改用OGL坐标系.
因为blade使用的坐标系是右手系, 但是uv使用的是dx的坐标系(u向右v向下), 这导致"默认的"切空间是左手系, 有点不爽. 所以就改成OGL的坐标系, 即u向右v向上.

这样默认的切空间变成右手系, 不过在实际中切空间是使用左手系还是右手系, 同时要看normal map是哪一种了.windows下大多游戏的法线贴图都是左手系.

左手系和右手系的normalmap是不一样的,他们的G通道是相反的.记得在网上看过两张图片的对比,具体链接忘了.

所以也在导出插件里面添加了手相选项. 一般来说,对于一个项目, 这些参数(手相之类)都是预定好的规范, 然后根据规范制作对应的模型和贴图, 这个时候这个手相选项就是固定的, 没有太大用处.

但是对于想使用3方现有模型和贴图的时候(比如我目前在网络上下载的各种模型), 由于各种情况都有, 这个时候可能需要选择导出手相, 使切空间匹配法线贴图.

而对于上面的bump map 转的normal map, 因为是运行时生成, 所以导出时的切空间可以选择任意坐标系, 比如目前导出时选择右手系, bump转normal的时候也使用右手系就可以了.

另外,blade对于uv的处理, 之前的想法是这样的: 使用固定的uv坐标系, 如果使用的uv, 或者图像的内存布局(有的是从低向上, 有的是从上到下)跟渲染API期望的不一样, 就翻转纹理图像的内容, 这样对于不同的API, uv和shader都不用改了.
虽然这个想法理论上没有问题, 但是实际上非常二: 运行时翻转图像太耗时.. 现在已经改成加载时翻转模型的纹理坐标(v坐标)了, 这样最终效果也一样.

因为OGL的uv坐标系要求图像是倒着存放的(原点在左下角), 如果加载的纹理不是这种布局(原点在左上角), 那么就翻转纹理坐标的v值. 比如DDS图像格式,其原点在左上角而不是左下角.

在用MFC+GDI做编辑器的过程中, 学习到GDI的bitmap header, 或者通用的bitmap header可以根据图像高度biHeight的符号来动态区分其存放格式http://msdn.microsoft.com/en-us/library/aa930622.aspx),

而在使用FreeImage的过程中发现, FreeImage加载的位图都是垂直倒放的, 这对于OGL有着先天优势.

4.threading utility

因为C++11里面已经有简单的thread了, 但是blade是基于C++98/03写的, 没有使用任何新特性. 因为Blade内部已经使用了Intel TBB, 多线程这个功能因为一直没有直接用到(除了自己写的readwritelock用到了mutex lock), 所以没加.但是考虑到以后用户的可能需求, 所以先放上.

本来的思路是写成C++11兼容的接口, 这样用户可以在不支持C++11编译器上用blade自带的thread, 接口也能保持一致, 不用改代码.

但是发现thread的某些功能使用了C++11的语法新特性, 所以这种想法不可行, 于是就用blade当前的风格简单封装了condition variable, mutex, thread, 放在了foundation库里面.目前做了windows系列和*nix (pthread)两种实现.pthread对应的功能都有, 只是简单的封装, windows下新版本的crt也有, 但是为了兼容性, 是自己写的.

目前只做了简单的测试, 估计还有N多bug, 暂时先这样吧, 嗯.

5. IK预研

目前找到的参考有:

http://freespace.virgin.net/hugo.elias/models/m_ik.htm

http://freespace.virgin.net/hugo.elias/models/m_ik2.htm

http://billbaxter.com/courses/290/html/img0.htm

http://graphics.ucsd.edu/courses/cse169_w04/welman.pdf

http://graphics.ucsd.edu/courses/cse169_w05/CSE169_12.ppt

http://graphics.ucsd.edu/courses/cse169_w05/CSE169_13.ppt

循环坐标下降(CCD)算法中对骨骼动画中膝盖等关节的特殊处理 很高兴国内已经有人在做^^.

另外还有 DOOM3 source code, 里面有IK的代码.

据了解 IK常用的方案有: Jacobian Transpose, CCD( cyclic coordinate descent), 和Analytical Method.

前两者是迭代逼近的解法, 而其中CCD更简单易懂, 而且有效.

Jacobian Transpose: http://www.math.ucsd.edu/~sbuss/ResearchWeb/ikmethods/iksurvey.pdf

CCD: https://sites.google.com/site/auraliusproject/ccd-algorithm

Analytical Method: http://www.ryanjuckett.com/programming/analytic-two-bone-ik-in-2d/

最后一个是几何分析的方法, 适用于简单的情况. 目前从doom3的代码看, 它好像用的这种方式(貌似没看到迭代).

blade的计划支持腿部IK, 还有臂部IK, 必要时加上头发辫子等等, 这个类似doom3的IK_Walk和IK_Reach, 但是臂部IK应该要比doom3更复杂.

后面还是继续IK的研究, 工作很忙, 先抽空看看资料吧, 进度会很慢.

引擎设计跟踪(九.14.2c) 最近一些小的更新的更多相关文章

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

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

  2. 引擎设计跟踪(九.14.2i) Android GLES 3.0 完善

    最近把渲染设备对应的GLES的API填上了. 主要有IRenderDevice/IShader/ITexture/IGraphicsResourceManager/IIndexBuffer/IVert ...

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

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

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

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

  5. 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014

    Origin: http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/ 简译 translation: 作者在2012年写 ...

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

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

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

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

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

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

  9. 引擎设计跟踪(九.14.2b) 骨骼动画基本完成

    首先贴一个介绍max的sdk和骨骼动画的文章, 虽然很早的文章, 但是很有用, 感谢前辈们的贡献: 3Ds MAX骨骼动画导出插件编写 1.Dual Quaternion 关于Dual Quatern ...

随机推荐

  1. git submodule(转载)

    From:http://www.worldhello.net/2010/01/26/425.html 删除 git submodule (git 库子模组) 有两种情况会创建 git submodul ...

  2. JSTL自定义标签

    这节我们总结一下JSTL自定义标签相关内容. 1. 自定义标签简介 自定义标签主要用于移除JSP页面中的Java代码.Jsp页面主要是用来显示给前台的,如果里面有过多的java代码的话,会显得很乱,但 ...

  3. 矩阵乘法快速幂 codevs 1250 Fibonacci数列

    codevs 1250 Fibonacci数列  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 定义:f0=f1=1 ...

  4. js获取url中的参数对象、js生成带参数的url

    // 获取url中的参数,并返回一个对象 $.getRequestData = function() { var url = location.search; //获取url中"?&quot ...

  5. linux 通过pid寻找程序路径的最简单命令

    在linux实际操作命令中,查看pid的方式有很多种,通过pid找程序路径的方式也有好几个,但是可能大家都忽略的一个很简单也是很实用的命令:pwdx. 比如要查找某个java编写的程序运行情况可通过j ...

  6. Mongodb4.0副本集构建

    目前最新的mongodb4.0.2已经支持事务这个重要特性,需要使用的话必须是复制或副本集,这是第一篇先研发如何构建副本集,因为副本集是目前最低成本的高可用群集方式. 1.准备三台服务器,本次使用是的 ...

  7. IdentityServer4 中文文档 -16- (快速入门)使用 EntityFramework Core 存储配置数据

    IdentityServer4 中文文档 -16- (快速入门)使用 EntityFramework Core 存储配置数据 原文:http://docs.identityserver.io/en/r ...

  8. python Image resize 对iOS图片素材进行2X,3X处理

    通常在iOS上开发使用的图片素材1x,2x,3x三种 下面利用python Image 库 resize函数,由一个大图,自动生成1x,2x,3x的素材照片: 1. 首先你的python环境要安装有I ...

  9. win10 远程出现身份验证错误 要求的函数不受支持

    win10的一个更新的bug 解决方案 http://note.youdao.com/noteshare?id=68aa9de9fbf46c50a097b3ccf7994580&sub=5AF ...

  10. The Little Prince-12/08

    The Little Prince-12/08 今天来点中文的经典语录+内心独白好不好呢? 狐狸说:“对我来说,你只是一个小男孩,就像其他成千上万个小男孩一样没有什么两样.我不需要你.你也不需要我.对 ...