Shading in Valve’s Source Engine

(抱歉一下,前面理解有错误,被误导的同学抱歉了)

本来想记录这个文章的:Image-based ambient lighting(比较属于作者拍脑袋想出来的,不是理论推出来的)

http://blog.wolfire.com/2010/03/Image-based-ambient-lighting

 

但是下面评论的这个给出的链接更好一些,所以反客为主了,:)

 

Shading in Valve’s Source Engine:

http://www.valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf

当时06年siggraph的一个course,但是这个是直接介绍valve的source engine的技术,工程性意义很大。

 

上来先分析面向硬件平台,06年时候我的x1600就这么点人用啊,:(

可以看出shading技术主要针对nv6到7系列,可见xbox360渲染能力当时优势有多大

Shading in Valve’s Source Engine_第1张图片

 

笔记主要包括lightmap和irradiance volume(动态物体从静态场景拿到的间接光照)。

lightmap,一般做法是直接offline计算从这个点出射的光(exit radiance),然后存在texture里。

valve目标是:

  • offline cook任意数量的diffuse lighting
  • 这些lighting是准确的(不是n个方向的光合成一个方向的光)
  • lightmap仍旧保持低精度
  • 和高精度的normal map作用,可以表达出高精度normalmap和周围任意静态光源作用出来的结果

理论推导:

这里做法本质上是把normal分解成3个正交向量。

考虑dot(n,l1)

n可以表达为a*base0 + b*base1 + c*base2----base0,base1,base2为正交单位向量

a == dot(base0,n);b == dot(base1,n);c==dot(base2,n);

so:

dot(n,l1)==

a*dot(base0,l1)+b*dot(base1,l1)+c*dot(base2,l1);

 

进一步考虑dot(n,l1)+dot(n,l2)->

a*dot(base0,l1)+b*dot(base1,l1)+c*dot(base2,l1)+a*dot(base0,l2)+b*dot(base1,l2)+c*dot(base2,l2)->

a*(dot(base0,l1)+dot(base0,l2)+

b*(dot(base1,l1)+dot(base1,l2)+

c*(dot(base2,l1)+dot(base2,l2)

 

上面l1,l2是入射光,n是normal,a,b,c是normal n在正交单位向量上的投影,可以看出对于2个光源和nromal n的dot的和可以分解成a*(dot(base0,l1)+dot(base0,l2)+b*(dot(base1,l1)+dot(base1,l2)+c*(dot(base2,l1)+dot(base2,l2)

 

这样每个入射光和base0,base1,base2做dot,然后加起来,存起来,实时计算的时候,取出normal map里的normal,和base0,base1,base2做dot算出a,b,c然后带入a*(dot(base0,l1)+dot(base0,l2)+b*(dot(base1,l1)+dot(base1,l2)+c*(dot(base2,l1)+dot(base2,l2)

就可以算出dot(n,l1)+dot(n,l2)了。

而且结果是没有折中的,理论正确的。

 

实现步骤:

每个lighting转到tangent space和三个basis vector做dot,结果乘以lighting rgb,和之前的lighting结果加起来,存入lightmap。

结果lightmap一共3张,每张rgb三个channel。

realtime计算的时候是result = light_map_color0*dot(normal,basis_vector0)+

    light_map_color1*dot(normal,basis_vector1)+

    light_map_color2*dot(normal,basis_vector2)

 

 

 

Shading in Valve’s Source Engine_第2张图片

最后的tradeoff是3倍普通lightmap消耗,但是得到了可以和normalmap交互的lightmap。

 

然后是irradiancevolume部分,也不是存sh系数,而是变成xyz方向上的lightingcolor(rgb)。

然后就是直接用。

 

后面locallighting,没什么意思,跳过。

 

最后一个hdr部分,是用rgba8的rendertarget,也没有特别的encoding,就是在lighting shader输出的时候做tonemapping,然后才输出,而不是存好floating的rendertarget,然后tonemapping的典型(也很费)的做法。

 

然后计算luminance来指导下一帧怎么做tonemapping那部分比较“怪”,是统计出来一个亮度的histogram,这个在其他engine里也见过类似做法,文中说是相比一个平均的luminance可以给designer更好的灵活性。这个没看出来有啥特别的灵活性,实际试验中换成一般的平均luminance也没啥不一样,怪怪!

 

反客为主到此告一段落,http://blog.wolfire.com/2010/03/Image-based-ambient-lighting这里说的一个是一种简化irradiancevolume做法,直接弄一个cubemap存储环境光(比如褐色的大地和蓝色的天空),然后model渲染的时候直接sample就好。

这个在室外场景的确很有实用价值。

 

 

 


原文链接: http://blog.csdn.net/ccanan/article/details/5430935

你可能感兴趣的:(Shading in Valve’s Source Engine)