今天仔细研究了 Shaowgun 示例中那个金黄色雕像所使用的光照纹理烘焙工具:“Render To Texel Baker”。因为要在移动设备展现比较逼真的光照效果,但是实时使用法线贴图并大量用于场景建筑中,对于移动设备还是有些力不从心。于是原作者写了这个工具,使用法线贴图和多个光源来对模型的贴图进行光照烘焙并保存烘焙结果。

  作者直接读取模型的所有三角形,顶点,uv,法线和切线数据,以及提供的模型法线贴图(最终转换到世界坐标系,计算过程证明了我之前对于tbn矩阵相关计算的理解是正确的),然后针对每个三角形中的每个像素,都通过插值和权重来计算出这个像素的世界坐标位置和世界坐标法线,并分别将每个像素的位置和法线各自存编码储到纹理里面,纹理的大小都和提供的法线贴图相同。最后将这些所有的数据以及模型的主要贴图都赋给材质,运用多个光源和观察者的位置来多次渲染这张主贴图,每次一个光源,每个光源多个观察者位置,但是每个光源的光照强度都已经根据光源个数做了平均,这样最终的渲染结果是各个光源渲染效果的加权平均值。

  其中作者的有些算法比较有意思,比如每个三角形中某个像素的顶点位置如何根据三角形的三个顶点的权重来计算呢?作者根据面积来计算的,对于三角形abc的面积若为s,其中一点p,p点对于顶点a的权重ma为:三角形pbc面积/s,以此类推计算mb,mc,这样点p的位置vp为: a*ma+b*mb+c*mc。我并不知道dx和ogl里对每个像素的位置如何差值计算,是否就是使用的这个算法还要再去查阅资料,不过这个算法很有意思,三角形面积的计算使用的是“海伦公式”。

  对于每个三角形的uv坐标,作者找出u和v方向的最小和最大值,构成一个四边形,然后逐个像素遍历看该像素是否在三角形内才处理,判断是否在三角形内的方法也很简单,对三角形abc,任意一点p,如果向量pa,pb的夹角,pb,pc的夹角,pc,pa的夹角之和为360度,则p点在三角形内部,如果在外部,夹角之和是小于360度的。

  还有作者如何将世界坐标的位置编码到纹理里面也比较有意思,作者找出整个模型的所有顶点中的x,y,z的最大最小值,这样对于任意一点p,就可以作为最大最小值之间对于参数t的差值结果,即:p = slerp(min, max, t); 如此可知 0<= t <= 1,计算出t就可以直接写到纹理中。

  关于接口 void Graphics.Blit(source : Texture, dest : RenderTexture, mat : Material, pass : int = -1),开始始终不明白为何作者使用时第一个参数source使用的null,对于官方的说明:“Blit sets dest to be active render texture, sets source as _MainTex property on the material, and draws a full-screen quad.” 也没怎么看懂,尤其是 _MainTex 和 source 的关系,后来经过反复修改测试明白,source 这个参数不是直接就被拷贝到 dest 中,而是说,如果你填充了 source 参数,那么该接口会把你使用的材质 mat 中的 _MainTex 修改为 source。我将 mat 中的 _MainTex 设置为空,运行后 _MainTex 果然被自动设置为了 source,而当我把 mat 所使用的 shader 中的主纹理 _MainTex 的名称改成随意的名称比如 _MyTex,同时讲纹理设置为空后,运行 Blit,发现 _MyTex 丝毫未动并未被修改为 source,因为 Blit 没有找到 mat 中有名为 _MainTex 的纹理变量,修改失败同时所设置的 source 将无任何效果,所以也就明为了作者代码的含义:Blit(null, dst, mat, -1) 将 source 设置为 null 后该参数无效,mat 中的 _MainTex 不会被修改(其实在编辑器中已经手动指定了一张纹理)。

  对于烘焙所使用的 shader 没什么特别,里面跟一个 Bumped Specular 的 shader 没啥两样。当然你可以自己根据想要的效果扩展或重写。

  烘焙所使用的法线贴图导入格式作者要求是 ARGB32 (选择 Automatic TrueColor),我试验后发现,这个格式仅在编译目标是 PC&Mac 时是这样,我切换到 IOS 下,选择 Automatic TureColor 后,实际的格式变成了 RGBA32。

  最后无意中看到一个关于"_MainTex_ST"的问答帖子

  还有一点:pixel space - (0,0) is lower left.

  作者对于工具的使用建议:

  1.加入尽可能多的光源,同时使用多个观察者位置;

  2.对于烘焙完毕的纹理还可以拿到 PhotoShop 中修理调整;

  3.可以同时烘焙多个不同参数的目标,还可以对不同的烘培结果之间再次烘焙洪培混合,以及运行时动态调整 shader 中的颜色等参数,不断试验以便寻找到满意的结果。

  工具目前存在的问题:

  1.不支持多层 uv 和 阴影;

  2.目前仅包含一个 Bumped Specular 的 shader;

  3.目前仅支持点光源;

  4.有的模型烘焙起来可能需要的时间较长;

  5.烘焙完毕的纹理可能会产生缝隙(尤其是贴在模型上以后比较明显,我后面的例子中会看到)。

  最后附上一张我试验的结果:

  

  左:烘焙前;右:烘焙后

 

Render To Texel Baker的更多相关文章

  1. React.render和reactDom.render的区别

    刚开始学习react.js.发现网上的资料,有些是写着react.render,有些写着reactDom.render.觉得很奇怪就查阅了一下资料.解释如下: 这个是react最新版api,也就是0. ...

  2. XF custom render 各平台实现类

    目前的XF还是非常简陋的,所以存在大量的自定义工作.一般情况下我们只是要需要派生原生的XF控件,然后在各平台下修改其呈现方法. 所以了解每个XF控件在不同平台上呈现使用的控件类是有所必须要的.以下别人 ...

  3. 塞翁失马,焉知非福:由 Styles.Render 所引发 runAllManagedModulesForAllRequests="true" 的思考

    最近在使用 MVC 开发的时候,遇到一个对我来说"奇怪的问题",就是使用 BundleTable 进行 CSS.JS 文件绑定,然后使用 Styles.Render.Scripts ...

  4. ReactJS分析之入口函数render

    前言 在使用React进行构建应用时,我们总会有一个步骤将组建或者虚拟DOM元素渲染到真实的DOM上,将任务交给浏览器,进而进行layout和paint等步骤,这个函数就是React.render() ...

  5. Cesium原理篇:6 Render模块(3: Shader)

    在介绍Renderer的第一篇,我就提到WebGL1.0对应的是OpenGL ES2.0,也就是可编程渲染管线.之所以单独强调这一点,算是为本篇埋下一个伏笔.通过前两篇,我们介绍了VBO和Textur ...

  6. Cesium原理篇:6 Render模块(4: FBO)

    Cesium不仅仅提供了FBO,也就是Framebuffer类,而且整个渲染过程都是在FBO中进行的.FBO,中文就是帧缓冲区,通常都属于高级用法,但其实,如果你了解了它的基本原理后,用起来还是很简单 ...

  7. Cesium原理篇:6 Render模块(5: VAO&RenderState&Command)

    VAO VAO(Vertext Array Object),中文是顶点数组对象.之前在<Buffer>一文中,我们介绍了Cesium如何创建VBO的过程,而VAO可以简单的认为是基于VBO ...

  8. render :template 和 render :parital

    1 .这两个都可以在controller和view中使用,而且好像可以替换,只是用:template,rails不会自动加下划线,用:partial,rails会自动添加下划线.而且规范的做法,:te ...

  9. AngularJs中,如何在render完成之后,执行Js脚本

    AngularJs是Google开源的前端JS框架.使用AngularJs, 我们能够容易地.健壮的开发出类似于Gmail一样的单页Web应用.AngularJs这个新兴的MVC前端框架,具有以下特点 ...

随机推荐

  1. Nico Game Studio 1.基本UI和地图编辑基础功能

    完成了基本界面. 本来想自画UI,但是考虑到工作量较大和美观程度有限,以及工具使用对象是比较初级玩家,处于性价比和最初目的,放弃了自绘.

  2. c语言学习之基础知识点介绍(十):数组

    本节主要介绍数组. 一.数组 /* 数组:一个变量可以存n个变量. 语法:类型 数组名[长度(正整数)]; 例如:int score[5];//定义了一个int类型的数组,长度为5,可以保存5个数据. ...

  3. github 上传或删除 文件 命令

    git clone https://github.com/onionhacker/bananaproxy.git cd ~/../.. git config --global user.email & ...

  4. 还原data block dumps实际值

    前天看了一个案例因为丢了表上的数据,从索引block中找回了值 转储了oracle block的值,如何得到它真正表中的值,也算 是dump(val,16)的逆运算 sys@ORCL>conn ...

  5. IE6 兼容问题总结

    1 IE6,IE7下设置body{overflow:hidden;}失效Bug

  6. codeblocks快捷键(转载)

    • 按住Ctrl滚滚轮,代码的字体会随你心意变大变小. • 在编辑区按住右键可拖动代码,省去拉(尤其是横向)滚动条之麻烦:相关设置:Mouse Drag Scrolling. • Ctrl+D可复制当 ...

  7. LESS快速入门

    Less 简介 简单来说,Less 就是让你在网页设计的时候,可以更方便地写 CSS 的工具. Less官网的说明: LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承,运算,函数. LES ...

  8. Js 获取 本周、本月起始时间

    涉及到显示本月或本周相关信息,又不想让php去判断,只好直接用js去计算,麻烦了好一阵,还是老老实实的看了下js的日期函数.现总结一下: //计算本周起始日期,并以 Y-m-d 形式返回.    fu ...

  9. 帝国cms7.0修改默认搜索模版中的分页[!--show.page--]

    修改默认搜索模版的分页是在e/class/connect.php下 搜索下function page1就是我们要修改的分页了 下面贴上我修改后的分页 //前台分页 function page1($nu ...

  10. C51应用 Modbs Rtu协议实现与KEPServerEx 通信

    最近一客户要求使用STC12C5A60S2实现Modbus Rtu协议与KEPServerEx V4.0软件通信,采集单片机P2口每位的状态,设置P0口每位的状态,实现三路AD转换其中一路采集的是C0 ...