03
Nov 13

Last of Us的光照技术

最近一年异常的忙碌,博客更新就耽搁下来了,现在总算有时间了。还是继续保持每周一篇的分享吧。先来一篇SIGGRAPH2013中比较实用的,由Naughty Dog的二号工作室带来的Last of Us中用到的小技巧分享。这个游戏前不久也买了数字版,虽然也许是不喜欢打僵尸,个人觉得游戏性上不如Uncharted,但是画面还是非常漂亮的,技术和美术的结合非常好。

写一下最感兴趣的部分,解决光照图接缝问题的Trick

Last of Us也大量使用了预烘培光照图技术,并且也遇到一个经典问题,就是一个模型在3D空间连续的面,实际上在2D的UV空间里面是不连续的,这样烘培之后的光照图就会有硬边出现。
Photo & Video Sharing by SmugMug
解决办法出人意料的简单,虽然不是物理正确的,但是也足够了。就是在这种会被分离的三角形边上定义一系列的焊接点,由于需要的是让纹理空间中相同的焊接点位于不同位置的采样点的值相同,所以定义一个Error Function为

\(E_i=(C_{i0}-C_{i1})^2\)

接下来的工作就是如何让整个光照图中所有E最小化。用经典的最小二乘法即可,有很多现成的库可以用。比如这个Eigen。大致想了一下实现方法,因为我们现在的贴图平铺算法也是自己实现的,而大部分模型美术都是依赖工具自动平铺的,人工干预的并不多。所以这个焊接点的标记也可以在平铺算法中自动标记,这样集成这个算法到我们现在的GI烘培流程中并不太困难。以后也许还可以分享一下具体实现的效果。
Photo & Video Sharing by SmugMug
相同的思想也能用来减少3D LUT后期算法的量化误差,通过对PS中的图像和实际的IN-GAME图像使用最小二乘法修正用于后期处理的Volume Texture。可以保证IN-GAME效果和PS中差别不大。
Photo & Video Sharing by SmugMug
总结一下,光照图和静态烘培技术对提高画面品质作用非常大,但是必须要技术和美术的密切结合才能做到出效果,并且需要一套能够实现这些定制渲染算法的工具。虽然开发和维护成本很高,但是确实是衡量一个团队是否有自己的核心技术的标准。现在的通用引擎非常多了,像Unity3D之类的更是以极低的价格集成了大量的中间件。但是从另一个角度来说,能否用好这种引擎,还是要看团队的内功。建立自己的工具管线才是提高制作效率保证效果的王道。


10
Aug 12

SIGGRAPH 2012 PPT 发布链接

今年SIGGRAPH的PPT也开始陆续放出来了,现在看到的有三个,后面再继续更新:

周日就要和我家领导出发去日本旅行了,算是Gap Year的完美结束吧!估计博客更新会暂停两周。因为没有跟团,两个不懂日语的人自由行所以要准备的东西很多,不过好处是活动范围可以很大(日本高铁专门对外国人短期旅行的通票还是非常划算的)。行程也很自由,希望不要碰上大台风什么的。回来更新游记和照片~~

08
Jul 12

Real Time Shading Model (4)

这周写点实际游戏中用的ShadingModel。目前的趋势是越来越多的PBS(基于物理的模型),BRDF越来越复杂的情况下,PBS确实会好调些。

先从Uncharted系列的头发渲染模型开始

Thorsten Sheuermann Hair Shading

基于Kajiya-Kay和Marschner模型改进。04年的Siggraph Sketch。头发渲染效果还是不错的,海域2就是直接用的这个模型。同样的,分为Diffuse和Specular两部分。先说Specular。

我们都知道头发是一种各向异性(Anisotropic)的材质,一般来说,人的头发由10w到15w根发丝构成,这样的表面充满了细小的沟槽(grooves or strands)。这样的表面不能用传统的各向同性的模型来计算,会显得非常不真实,所以我们需要引入不同的假设来解决这个问题,由于构成表面的每一个Strand都有无数的法线方向,当光线和这样的表面发生交互的时候,只能假定(否则就要对法线方向进行积分了)产生最大反射的法线向量就是和光线的入射向量在Strand法线平面上的投影重合的法线。这样问题就简化很多了,不过Kajiya-Kay模型使用的不是N,而是半法线H,如下图所示:

T为Strand的切线向量,N为当前Strand的最大法线向量,V是视点方向,L是光照方向。所以Specular分量为:

\(J_s= C_s \cdot (\sqrt{1 – (T\cdot H)^2})^e\)

而03年Marschner提出的模型中,对头发材质高光的模拟更进了一步,注意到实际上有两种类型的高光,一种是直接反射的,一种是穿过最初的进入点又被反射出来的,这种Secondary的Specular是带头发颜色的,并且位置上向发根偏移,并且有闪烁的感觉。

要实现Marschener的模型也比较简单,计算公式和Kajiya-Kay是一样的,只是我们用一张Shift Tangent Texture来对T分量进行偏移就可以打破由于T在表面完全一致造成的相似性,这对提升渲染效果是很重要的。如下图所示:

而要获得Secondary高光闪烁的感觉,可以简单的用一张噪声纹理对颜色进行Modulate:

而Diffuse分量没有使用原始的Kajiya-Kay模型,而是用了Warp Lighting,这是一种模拟次表面散射材质的廉价算法。原始的公式是这样的:

\(J_d = saturate( \frac{ N\cdot L + w }{ (1 + w )^2 }\)

其中w是0-1的一个参数,用来加亮远离光线方向的面。而Thorsten Sheuermann用的是这样的近似方程:

\(J_d=max(0,0.75*N\cdot L + 0.25)\)

所以最终的Shader代码是这样的:

 
float HairDiffuseTerm(float3 N, float3 L)
{
    return saturate(0.75 * dot(N, L) + 0.25);
}
 
float HairSingleSpecularTerm(float3 T, float3 H, float exponent)
{
    float dotTH = dot(T, H);
    float sinTH = sqrt(1.0 - dotTH*dotTH);
    return pow(sinTH, exponent);
}
 
float3 ShiftTangent(float3 T, float3 N, float shiftAmount)
{
    return normalize(T + shiftAmount * N);
}
 
float4 main(PS_INPUT i) : COLOR
{
    // shift tangents
    float shiftTex = tex2D(tSpecularShift, i.texCoord) - 0.5;
 
    float3 N = normalize (i.normal);
 
    float3 T1 = ShiftTangent(i.tangent, N, specularShift.x + shiftTex);
    float3 T2 = ShiftTangent(i.tangent, N, specularShift.y + shiftTex);
 
    // diffuse term
    float3 diffuse = hairBaseColor * diffuseLightColor *
                     HairDiffuseTerm(N, i.lightVec);
 
    // specular term
    float3 H = normalize(i.lightVec + i.viewVec);
    float3 specular = specularColor0 *
                      HairSingleSpecularTerm(T1, H, specularExp.x);
 
    float3 specular2 = specularColor1 *
                       HairSingleSpecularTerm(T2, H, specularExp.y);
 
    // modulate secondary specular term with noise
    float specularMask = tex2D(tSpecularMask, i.texCoord * 10.0f);
    specular2 *= specularMask;
 
    // specular attenuation for hair facing away from light
    float specularAttenuation = saturate(1.75 * dot(N, i.lightVec) + 0.25);
 
    specular = (specular + specular2) * specularLightColor *
               specularAttenuation;
 
    // read base texture
    float base = tex2D(tBase, i.texCoord);
 
    // combine terms for final output
    float4 o;
 
    o.rgb = (diffuse + ambientLightColor * hairBaseColor) * base;
    base = 1.5 * base - 0.5;
    o.rgb += specular * base;
    //o.rgb *= i.ambOcc;
    o.a = tex2D (tAlpha, i.texCoord);    // read alpha texture
 
    return o;
 
    return i.ambOcc;
}

参考文献

1.Hair Rendering and Shading

2.Uncharted2 Character Lighting


01
Jul 12

Real Time Shading Model (3)

总结一下基于物理的模型实现上的主要特点:

  • Energy Conserving Model,能量必须守恒,也就是反射的能量不能大于入射的。大部分经验模型这点都是不满足的,通过加入一些Normalization项可以进行修正,获得更可控的Shading Model
  • Punctual Light,假定光源是无穷远无穷小的,这样只用光源颜色和方向就可以完全定义了。
  • HDR Lighting,光照的结果必须有足够高精度,某种基于物理模型就没有意义了
  • Linear Pipeline,必须使用线性渲染管线,Gamma的处理必须正确,参数纹理的颜色空间要统一。

Normalized Blinn-Phong

原始的Blinn-Phong高光并不符合能量守恒,看下面两张图,上面是没有Normalized的,下面是相同的高光参数下符合能量守恒的效果。可见基于物理的模型更容易调整效果,而不用借助各种奇怪的参数。

\(I_{o}=I_{i}((N\cdot L) k_dC_d + k_sC_s(N\cdot H)^e) )\)

其中\(k_s\le\frac{e+8}{8\pi} \)就是保证能量守恒的因子

Ashikhmin-Shirley

各向异性模型。用来表现一些特殊的金属材质。相比其他的模型,可以更好的控制高光的形状。虽然不是基于物理的模型,但是使用了Fresnel函数来获得更真实的反射系数。同时Diffuse项也脱离了Labertian模型,保证了能量守恒,效果还是很不错的,不过计算代价确实很大。如果要用到游戏里面,肯定要做一些简化。

Specular和Diffuse如下:

\(J_s=\frac{\sqrt{(n_u+1)(n_v+1)}}{8\pi}\frac{N\cdot H\frac{n_u (H\cdot T)^2+n_v(H\cdot B)^2}{1-(H\cdot N)^2}}{(V\cdot H)\cdot max(N\cdot L,N\cdot V)}F_r((V\cdot H),C_s)\)

\(J_d=\frac{28}{23}C_d(1-C_s)(1-(1-\frac{N\cdot V}{2})^5)(1-(1-\frac{N\cdot L}{2})^5)\)

下面是原始论文里面的不同的\(n_u,n_v\)值的效果:

当\(n_u = n_v\)时,A.S模型就退化成了各向同性的模型,下面是原始论文里面的效果比较:

\(J_s=\frac{n+1}{8\pi}\frac{(N\cdot H)^n}{V\cdot H \cdot max(N\cdot L,N\cdot V)}F_r(V\cdot H,C_s)\)

注意Diffuse项现在是和视点相关的,Fresnel的加入使得在不同的角度,Diffuse和Specular的比例有所区别,Fresnel采用的是Schlick的简化函数:

\(F_r(u,\rho_s)=\rho_s + ( 1-\rho_s)(1-u)^5\)

加入Fresnel的效果,看下面这张原始论文的图就很直观了:


23
Jun 12

Real Time Shading Model (2)

继续基于物理的光照模型,先从Oren-Nayar开始,这个模型从一开始就是为了改进对Diffuse分量的计算,所以并没有包含Specular分量的计算。也是基于微表面模型,但是和Cook Torrance模型的假设有一些区别:

  • 假定表面是由一些连续的对称的V型凹槽构成的,每一个凹槽由两个对立的面构成
  • 每一个微表面的面积远大于光的波长,所以不用考虑衍射之类的问题
  • 每一个微表面是一个Lambertian面,有相同的Diffuse反射系数
  • 微表面的面积相比物体整个表面积非常小,所以每个像素可以覆盖足够多的微表面,可以使用统计分布模型建模

Oren-Nayar有分析模型,但是由于计算过于复杂,一般使用的是简化模型:

\(J_{d}=C_{d}(A+B\cdot \max(0,(V^{‘},L^{‘}))\cdot\sin\alpha\tan\beta\)

\(A=1-\frac{1}{2}\frac{\sigma^{2}}{(\sigma^2+0.33)}\)

\(B=0.45\frac{\sigma^{2}}{\sigma^2+0.09}\)

\(\alpha=\max(\theta_i,\theta_o),\beta=\min(\theta_i,\theta_o)\)

\(V^{‘},L^{‘}\)分别是视点向量和光照方向向量在切平面的投影。

最重要的可控参数只有一个就是表示粗糙程度的\(\sigma\)。如果这个参数是统一的,那么计算量最大的A和B两个参数都可以用预计算的方式存储在纹理中。当然也可以以参数纹理的方式,让美术可以精确的控制材质表现,对于某些种类的Diffuse材质,Oren-Nayar效果还是不错的,不过大家基本都是做了各种简化(比如战锤40000,以及这里的一个优化,以及GPU Gems的Warp Lighting)。可见了解这些有数学和物理基础的模型的思想,对解决自己游戏中特定的效果需求还是很有帮助的,凑也得有基础啊。

Strauss

这个模型也是很有影响力的,特别是在金属高光材质上。上面这个右边的角色就是用Strauss模型的。顺便说一下作者后来去了Pixar做工具开发,现在在做Google Earth。主要的目的是在达到和Cook-Torrance类似的效果基础上降低计算开销,并提供更直观的材质调节参数:Smoothness(s),Metalness(m),以及Transparency(t)。和Cook-Torrance一样,也包含了Fresnel系数和几何衰减系数,不过算法略有区别。Strauss包含了Diffuse,Specular以及Ambient项。下面逐项来看。

\(J_d=r_d (1-ms)C, r_d =(1-s^3)(1-t)\)

Diffuse分量会随Smoothness,Transparency,Metalness增大而减小.这在物理上是正确的,但是一个缺点是美术会发现自己画的Diffuse纹理色和最后实际的Diffuse颜色差别很大,不好控制。

下面是Specular了:

\(J_s=\frac{1}{(N,L)}r_s C_s\)

其中\(r_s\)是一个Phong+Fresnel+Gemoetry的混合系数,也是这个模型中最复杂的部分。

\(r_s=r_j(V,R)^e,e=\frac{3}{1-s}\)

\(r_j=\min(1,r_n+(rn+k_j)j\)

\(k_j=0.1,r_n=(1-t)-r_d\)

j是Fresnel系数和几何衰减系数的近似函数,注意都是直接以角度为函数参数的。

\(j=F(\theta_i)G(\theta_i)G(\theta_o)\)

其中\(\theta_i=acos(N\cdot L),\theta_o=acos(N\cdot V)\)

\(F(\alpha)=\frac{\frac{1}{(2\alpha/\pi-k_f)^2}-\frac{1}{k_{f}^2}}{\frac{1}{(1-k_f)^2}-\frac{1}{k_{f}^2}},G(\alpha)=\frac{\frac{1}{(1-k_g)^2}-\frac{1}{(2\alpha/\pi-k_g)^2}}{\frac{1}{(1-k_g)^2}-\frac{1}{k_{g}^2}}\)

这部分计算代价很大,估计只能预计算或者做简化吧。不然只能用作Demo里面。

\(C_s=C_w+m(1-F(\theta_i))(C-C_w)\)

最后是高光色的计算,根据Fresnel系数和Metalness系数,在白色和固有色直接做插值获得。

今天写到这里,下周继续。越发觉得遍历一次学术界的各种模型和原始论文,还是很有必要的。参考文献到最后再来整理吧。


10
Jun 12

Real Time Shading Model (1)

暗黑3到炼狱了,作为一个全身乞丐装的巫医已经打不下去了,等1.0.3版本调低炼狱难度和调高掉率之后再继续吧。这个周末可以继续写博客了,这次想写写Shading Model。不像离线渲染,尽可能的使用精确的物理模型,实时渲染的光照方程一般都比较简单,毕竟一帧只有十几毫秒的渲染时间,当然,随着计算能力的增强,实时渲染也在不断的把离线渲染的算法移植过来,追求物理真实的光照方程。下面先从基本的概念和建模方式开始,然后是一些重要的模型。这次没有时间写代码,不过最近正好想学JavaScripts,所以有时间会把这些模型用WebGL做一个交互Demo。应该会比较有意思。

1.基本模型

在去年的一篇基本概念短文中,提到了图形学采用的光的物理模型,物体的材质属性可以用BRDF函数来表示,这个函数决定了入射光和反射光的关系,求解渲染方程可以获得最终被人眼感知的Radiance。BRDF再细化还有用来建模反射的BTDF,建模散射的BSDF,次表面散射的BSSDF….因为后面不准备写太多公式并且实时渲染的Shading Model就是对BxDF的各种简化。所以下面准备从简单的直观模型和术语入手。能把思想说明白就行了。

BxDF是从数学上给出材质的精确描述,但是如果不要求太精确的描述,我们可以把光线照射物体后的Radiance分为高光分量(Specular)和漫反射分量(Diffuse)。不同的Shading Model的区别就在于这两种分量分别是如何计算,如何线性插值获得最终结果。其中Specular是被物体表面直接反射的光照分量,也就是一个白光照射到蓝色的表面,Specular依然是白色的。因为并没有在粒子层面发生作用。而Diffuse则是光线和物体发生微观层面的物理作用后,被散射和吸收之后再反射出来的,两者的重要区别是Specular依然保持极化(Polarized),而Diffuse由于经过电子被激发等物理作用,反射方向随机,极化方向也是随机的,所以也就可以说失去极化特征了。为了比较直观的理解这两种分量,推荐大家看UDK的一个文档和John Hobble的这篇博客,下面的图片是来自John的博客,里面描述了怎样用单反相机+偏振镜+后期处理获得真实物体的Specular和Diffuse,这样也可以帮助我们更好的理解某种材质。很多直接用照片做贴图的美术同学恐怕对这种处理方式早就很熟练了吧。下面来看看:

a.Original

b. Diffuse Only:

c. Specular Only:

之所以我们能够分离出Specular和Diffuse,就在于偏振滤镜(linear polarizing filter)的作用,玩摄影的同学可能都用过这种滤镜,可以有效降低明亮日光下的高光反射,获得更好的质感。分离算法原理也比较简单,大家可以看原贴。从上面分离的Specular和Diffuse可以看到,金属部分基本是没有Diffuse的,全部颜色都来自Specular。因此我们可以把通用的Shading Model表示成这样:

\(I_{o}=I_{i}(N\cdot L)( k_sJ_s+k_dJ_d ) \)

其中\(J_{s}\)是Specular分量,\(J_{d}\)是Diffuse分量。下面来看看对这两种分量的各种计算方法。

2.Empirical Shading Model

Lambert:最古老的模型,只是建模理想漫反射表面,即假定物体表面全部是平滑的,每个方向的Diffuse反射量是一致的。没有Specular分量。

公式:\(I_{o}=I_{i}(N\cdot L)C_{d}\)

注意N.L其实不是LambertBRDF模型的一部分,只是反射方程的几何因子,\(C_{d}\)是DiffuseColor。Lambert模型一般不会单独使用。通常都是其他模型的一部分。

Phong:1975年发布,属于简单的经验模型,加入了高光分量的计算。Phong模型的高光有强烈的塑料感。并且会有强度突变的问题。不能很好的兼容法线贴图。

\(I_{o}=I_{i}((N\cdot L) k_dC_d + k_sC_s(V\cdot R)^e) )\)

Blinn-Phong:用N.H替代了V.R来计算高光强度。H是半角向量,即入射光方向和观察者视线方向的平均值,Blinn-Phong效率更高,因为H只用每盏光计算一次,而R则是每一点都需要重新计算,并且\((N\cdot H)^{4e} \approx (V\cdot R)^{e}\)。Blinn-Phong的理论基础是Microfacet理论,即认为物体表面分布的大量微表面会向视点方向反射光线,这些微表面的法线和H方向一致的时候反射光线才是有效的。

\(I_{o}=I_{i}((N\cdot L) k_dC_d + k_sC_s(N\cdot H)^e) )\)

Phong vs Blinn-Phong

3.Physically Based Shading Model

前面的模型都是基于经验凑的,下面介绍一些基于物理的模型,这些模型计算上更复杂,但是能更方便调试和修改,对真实的材质表现也更好。现在很多游戏都在积极的使用了,这方面有很多文献可以看,比如使命召唤的SIGGRAPH PPT,Tri-Ace的PPT。先从基于微表面模型最有名的Cook-Torrance开始,这个模型重点也是Specular分量的计算。

关于微表面性质的一些假定是,每一个微表面是一个完美的Specular Reflector,只有朝向半角向量的微表面会对BRDF有贡献。公式如下:

\(J_{s}=\frac{F(L,H)G(L,V,H)D(H)}{4(N\cdot L)(N\cdot V)}\)

其中F是菲尼尔函数,用来代表每一个微表面的反射量。G则是几何衰减系数,用来表示微表面之间的Shadowing和Masking。或者说是Visibility函数,即给定L(入射光方向),V(视点方向)和H,哪些微表面是可见的。D则是表示朝向半角向量方向的微表面的概率分布函数,比较流行的是用Beckmann分布函数,Phong NDF。而菲尼尔函数用的比较多的近似是Schlick的简化函数:\(F(L,H)=F_{0} + (1 – F_{0})(1-L\cdot H)^{5}\)


14
May 12

Vision and Art ,The Biology of Seeing 读书笔记(2)

继续上周的读书笔记,今天主要讲色彩的感知原理,为什么战地3可以用Chroma SubSampling来提高渲染效率同时又不对效果有很严重的影响?人眼的感光细胞只有10倍左右的动态范围的情况下,为什么我们能同时看清反差如此之大的各种细节?在颜料能够表现的动态范围很有限的情况下,画家们是如何表现高动态场景的?


色彩的感知原理-三原色(Trichromatic) vs 补色(Color Opponent)


就像光具有波粒二相性一样,对颜色是如何构成的,也有两种理论:
  • 三原色,三色中的任何一色,都不能用另外两种原色混合产生,而其他色可由这三色按一定的比例混合出来,这三个独立的色称之为三原色(或三基色)。视网膜上确实有三种感光细胞,分别对三原色敏感。
  • 补色,这种理论认为人对色彩的感知并不是直接编码三种感光细胞的响应,用三原色合成颜色,而是编码某两种原色的差异,所以叫补色原理,在神经生物学的研究中发现,由于三种感光细胞对光线的反应曲线是有重叠的,所以这种编码差异而不是完整的曲线的方式,信息量更小,通过大脑的处理即可还原所有的信息。
一开始这两种理论被认为是不相容的,并且各自都有实验证据,很有点波粒二相性之争的感觉。后来的科学发展证实,这两种理论适用于人脑处理颜色信息的不同阶段,在第一阶段,感光细胞确实是提供了三原色的响应信号。但是在接下来的Bipolar细胞的处理中,就应用了补色的机制。把三原色信号变成了两元补色(two opponent signals)和亮度(luminance)信号。从处理效率和进化的角度来讲,人类还在低等生物的阶段时,只需要亮度信号就可以进行很多有用的信息处理了(Where系统).这样补色信号和亮度信号的分辨率或者说信息量是不同的,并且由于我们先进化出Where系统,后进化处理对颜色信息进行处理的What系统,所以这样划分也很自然,毕竟对进化来说,推翻重构的成本太高,添加功能式演化是比较自然的。有了这样的认识,很多视觉现象就好解释了,后面很多地方会提到。
比如目前应用非常广的图像压缩算法:Chroma SubSampling。从2011年的SIGGRAPH PPT里面我们可以看到战地3也用了这种算法,通过渲染低分辨率的颜色Buffer来提高效率。所以说,Vision and Art就是做渲染的原点,任何严肃的图形程序员都得好好掌握这些知识。


如何在2D的平面上呈现出3D的效果


视网膜需要从两只眼睛获得的2D图像还原出3D的世界,所以需要不少规则去辅助判定
  • 透视(Perspective)
  • Shading(主要是靠物体的亮度差异,而不是颜色)
  • Occlusion(遮挡关系)
  • Haze(远处的物体会由于雾和大气散射而变得模糊)
  • Steropsis(立体视觉)
  • Relative Motion(相对运动)
对画家来说,需要克服已经被大脑处理好的3D图像,而从中去还原出2D图片,然后让其他有着2D视网膜的人觉得这些平面的画很有3D的效果。而克服直觉是需要花很多功夫的,一些画家借助辅助网格,而一些人本身就是由于生理缺陷,缺乏立体视觉。反而成为画家的一大优势。
而为了增加画作的立体感,也需要模拟人眼感知世界的各种规则。下面列举一些我觉得挺有意思的。


透视

人眼因为要从2D图像重建3D的立体世界,所以透视原理也是被硬编码了。就是我们会认为物体必然是近大远小的,比如下面这个著名的Ames’ Window和Ames’ Room。视频演示在这里。如果想自己做一个纸上模型,可以把这个打印出来


Chiaroscuro(明暗法)


这个术语是来自意大利语,直译就是Light-Dark,是绘画的一种技法,用明暗对比来表现物体的体积感。前面提过,人眼的感光细胞对局部的亮度变化很敏感,并且这部分是古老的高分辨率Where系统所掌管的,所以亮度的对比可以给Where系统很强烈的物体轮廓提示,从而让平面的画作获得立体感。而且由于太阳光总从我们头顶射下,所以“光来自上面”这个规则已经被我们的Where系统硬编码了,所以让物体上部亮,下部暗的时候,我们会觉得这个物体很有立体感,反之则是完全不同的深度感觉,比如下面这些球体:
而一旦我们把球体旋转一个角度,上下的明暗对比没有了:
我们就不会有凹凸的感觉了。
再看一个印象派画家的作品,Monet的Rouen Cathedral:The Portal(in sun)。通过刻意的增加局部的明暗对比,教堂的立体感得到非常大的加强。
再来一张安格尔的:Princess Albert de Broglie,对亮度对比的控制已经牛的不行了。


画家是如何表现HDR(高动态范围)的效果


自然界中,不同的物体之间的亮度差异可能会有成百上千倍,但是我们的眼睛可以毫不费力的同时看到这些东西,而实际上,神经生物学家们发现,感光细胞能够编码的亮度差异也就是10倍左右!(这个我以前还真不知道)人眼会通过局部的对比来自动的调整(上一篇文章提到过的Center/Surround原理)。而对画家们来说,使用的颜料动态范围是非常有限的,显然不可能模拟物理真实的世界如此高的反差,于是画家们也逐渐学会了利用局部的对比来匹配人眼的局部性规则。比如伦勃朗的这幅Philosopher in Meditation。通过使用局部的大反差,用低动态范围的颜料模拟了高动态范围的光照效果。实际上,这中技法在实时渲染里面也是后期效果的标配了。

06
May 12

Vision and Art ,The Biology of Seeing 读书笔记(1)

这本书入手也有一段时间了,术语比较多,读起来比较头疼,不过习惯了到后面就好了。印刷十分精美,各种插图设计也是一流的,看起来还是很享受的。全书的中心思想就是:Vision is information processing, and visual computations are SIMPLE, LOCAL, and OPPONENT。视觉并不是对外部世界的真实还原,在进化的过程中,人脑还形成了很多信息加工的功能,方便快速的获得某种重要信息,比如人脸的识别,深度的感知,颜色从2元到3元以便能识别出有毒的果实之类的。而很多画家其实就是利用了人脑的这些处理信息模式,创造出了经典作品。下面记录一些有意思的地方。

视网膜的构成

视网膜(Retina)的构成如上图所示,列一下从维基百科上拷贝过来的中英文的术语对照,这样后面好理解一些:

  • 视网膜色素上皮 (retinal pigment epithelium)
  • 感光层 (photoreceptor layer,rod,cone) ,包括视杆和视锥细胞
  • 神经节细胞层 (ganglion cell) ,这个层含有神经节细胞的细胞核,视神经从这里开始
  • 内核层 (inner nuclear layer),又称内颗粒层,由双极细胞(Bipolar Cell)、水平细胞(Horizontal Cell)、无长突细胞、Muller细胞的胞核组成
  • 神经纤维层 (nerve fiber layer),主要为神经节细胞的轴突

比较有意思的地方:

  • 感光层居然在Retina的最外层,也就是最后才接收到光线的,也就是这个原因,在中心的Fovea区域,为了最大化分辨率,这里的三层神经节细胞都被移开了,露出了一小块区域,让光线经历的中间细胞少一些
  • 中间的几层神经元细胞会在感光层接受光线刺激产生信号后,对信号做整合预处理
  • 光感受体传递神经信号的方式和普通的神经并不相同,光感受体平时一直处于Potentiate的高电位状态,光线刺激出现的时候才降低电位
  • 视锥细胞工作在比较亮的环境下,而且可以分辨颜色。视杆细胞工作在比较暗的环境下,其分辨率比较低,而且不能分辨颜色

Center/Surround原理

在感光细胞送出神经元信号后,神经节细胞层会对信号进行横向整合,遵循的是著名的Center/Surround原理,也就是在中央区域的光线刺激是+信号,而在边缘区域的光线刺激是-信号。这样的组织下,人眼的中心视觉灵敏度很高,并且对运动和变化的物体反映十分灵敏,也就是对光的变化敏感,而不是总体的亮度。这恐怕也是进化过程中必需的。而且重点编码运动和变化的信息,而不是整体的信息,也是一种信息压缩的手段吧。下面这张图可以让我们直观的感受到Center/Surround预处理的效果,当把视觉焦点放在白线交汇处时,会发现周围的交汇处有黑点闪烁,并且离中心视觉焦点越远越黑,当视线移动时,还能明显感觉到闪烁,这是因为神经信号传递的时间延迟。

中心视觉和边缘视觉

人眼的中心视觉分辨率很高,相对的,边缘视觉则要粗很多,但是比较擅长分辨大的轮廓和重要的元素,比如人脸。下面这张对蒙娜丽莎的脸部分析图可以很直观的解释为什么她的微笑那么神秘。

当你聚焦到她的脸部之后,视觉分辨率很高,看到的都是细节,也就是最右边的效果,所以微笑并不明显,但稍微移动视线,由于边缘视觉是看轮廓的,看到的就是左边的两种效果,所以就会突然觉得笑容更明显了。很多画家都会运用人眼的这种视觉原理去创造出一种变化感和运动感。特别是印象派的。

莫奈的这张Rue Motorgueil in Paris,Festival of June 30 , 1878.也是运用这种原理制作的,创造动感并不是单单的Blur掉。而是精确的模拟人眼的Peripheral Vision的Spatially imprecise的特点。

What and Where System

如上图所示,大脑中有两套处理视觉信息的系统,其中where系统是比较古老的构造,特点是分辨率不高,对反差很敏感,色盲,主要依靠亮度信息来判定深度和物体的运动,人物和地面的分离。而what系统是后期进化出来的,分辨率高,对颜色敏感,低反差。用来进行对象识别,人脸识别和颜色感知。

利用这个特点,我们就有了Equiluminant Color,指色调(Hue)和饱和度(Satureate)不同,但是亮度(Luminance)相同的色彩,用这种色彩组成的画面,会导致人的Where系统无法对其中的形状进行定位,所以会有闪烁,漂浮不定的感觉,也是很多画家利用的一个特点,比如印象派的很多画家

莫奈的这幅日出印象就是典型,也包括梵高的很多作品。从图上可以看到莫奈的太阳有比较特别的动感,但是把颜色去掉之后,我们就发现太阳的Luminance和背景基本是一致的。不过我觉得网上找的图效果都不明显,因为Where系统灵敏度很高,只要有亮度差异,基本就识别出来了。而且和屏幕的校准也有关系,这里有个网站可以实时的调整看效果

今天先写到这里,剩下的下周继续。

Update 2012.5.16,第二部分在这里


29
Apr 12

支持多重触摸手势的场景制作工具

Pixar一直是我很喜欢的工作室,技术和艺术的结合堪称完美,他们的研究院主页上有很多有意思的Paper,最近有几篇和利用新一代人机交互技术来提高制作效率的,还比较有趣,随着支持多重触控的平板设备普及,也许在不久的将来,这些技术也能运用到游戏制作的编辑器里?虽然没有Pixar内部实际如何运用的信息,但是从09年开始,他们已经开始探索利用支持多重触摸手势功能的编辑器进行场景制作了。主要有两个项目EdenProton。都是和Berkeley合作的项目,主要解决的问题是电影中有大量物件的3D场景制作效率( set-dress 3d scenes)。Eden是多重触摸界面的编辑器,而Proton是为了支持大量复杂手势的定制和自动匹配的工具,可以说技术上已经比较成熟了。我们都知道目前不管是电影还是游戏的主流的场景制作工具还是类似Maya这样的,完全基于鼠标和键盘的传统UI交互。Eden就是想颠覆这个传统,Berkeley的研究人员+10年经验的Pixar场景美术的团队。09年首先是进行了科学的测试,证明多重触控的操作确实能够有效的提高效率,论文在这里。于是首先开发了Eden,论文里面列出的多重触控手势设计原则还是比较有意思的,以后做平板的软件说不定能用得上,记录一下:

  • Use simple gestures for frequently used operations
  • Conjoined touch as a modifier,引入Conjoiner Touch的概念,使得两个手指的触摸操作可以表示三种语义,方便操作
  • One operation at a time,两只手分别操作多个物体的需求很少,而且不直观
  • Split touches across both hands
  • Use at most two fingers from each hand,不是每个人都是练钢琴的,所以每只手最多用两个手指
  • Interchangeability of hands,手势是可以互换完成的
  • Motion of gesture reflects the operation,手势反映出操作的特点,方便记忆与实施
  • Combine direct and indirect manipulation,直接和间接操作需要结合使用
  • Control at most two spatial parameters at a time,每次最多控制两个空间参数,这也是和美术实际测试下来最方便的操作

最后Eden测试的结果是,制作效率提升20%,由于工作分摊到两只手上,可能可以减轻老美术的RSI(repetitive stress injury,就是鼠标手了…)。感兴趣的同学还可以去论文页面下载演示视频。

参考文献:

  1. Determining the Benefits of Direct-Touch, Bimanual, and Multifinger Input on a Multitouch Workstation

  2. Eden: A Professional Multitouch Tool for Constructing Virtual Organic Environments

  3. Proton: Multitouch Gestures as Regular Expressions


15
Apr 12

GDC2012 神秘海域系列的特效技术讲座笔记

UC1的特效系统是基于宏语言描述的数据脚本,采用了6000+行的UberShader,利用PPU和SPU进行计算。实际用下来感觉UberShader太难维护了,而且要美术去写特效脚本,不是非常直观。美术对这个系统的感觉是suck the soul out of me…所以说嘛,技术都是积累出来的。

所以新的特效系统做了完全的重写,以大幅度提高迭代效率为设计目标,更加的数据驱动,采用基于节点的Shader编辑器方便美术自己调效果

特效编辑器是嵌入在MAYA中的,这方面顽皮狗也是有很多积累的,感觉也是一个不错的工具思路。

美术在MAYA中直接编辑粒子的发射器,Expression脚本和曲线等属性,然后输出给用Scheme写的DataCompiler变成VM Byte,再由网络层传输给引擎进行可视化,用网络层隔离引擎和工具也是数据驱动的一个常用手段,这样工具选择什么语言跑在什么系统下都没什么关系了。

Shader编辑器是SONY ATG完成的,然后顽皮狗拿过来做了定制,基于节点的编辑方式,每一个节点是一个CG函数,也可以插入自定义的函数,美术自己管理Cycle预算,也就是美术会控制Shader生成的长度,严格的按照性能指标来进行

特效在游戏中发射方式

5种方式可以发射粒子:场景编辑器中摆放,脚本,动画中的关键帧和挂点,水面,以及代码中直接发射

在场景中摆放的发射器:

在动画序列中绑定的发射器:

在水面上绑定发射器:

特效的更新步骤:

在preupdate中进行碰撞检查

为了提高粒子碰撞效率,做了很多优化,每一个粒子保存一个碰撞平面,在每一帧选部分粒子进行碰撞检查,结果在下一帧返回并存储在粒子数据结构中,粒子的碰撞信息是Round Robin式更新的,保证每一帧的开销比较小,结果不太精确但实际上很难注意到

Update阶段执行DC从Expression脚本编译成的VM代码,改变粒子的颜色,位置,自定义属性

UC3的Decal的做法

简单的说就是用一个Bounding Box获得屏幕上需要绘制的像素范围,然后在PS中采样Depth Buffer获得世界坐标的位置,并变换到particle space(projection space of particle),同时在Light PrePass的时候把Decal的法线也渲染到Normal Buffer中去。感觉和Humus的这个Demo做法差不多

用Stencil Test去避免把粒子贴地投射到前景物体上去

UC3的大火的Trick

相信玩过神海3的人对大火的场景印象还是比较深的,他们一开始也是用常规的粒子来实现的,结果FPS只有12,实在跑不动,于是发展了一个比较有意思的技术,就是用很少的面片,但是用一张纹理来扰动Z深度,造成有前有后的效果,比如下面这张图片,其实就两个关闭Z Test的面片,但是感觉还不错:

这个技术要求所有的动态效果都通过纹理来控制,并且对纹理精度要求比较高,否则就糊了。灵感是从大家都很熟悉的软粒子实现机制来的,下面左边的就是Z-bias和Z-blend的效果,如果用一张纹理来给出Z-bias的值就会出现右边的效果,如果再把这张图加上动画就能有更丰富的效果

 

增强烟雾的体积感的方法

其实很简单,就是对法线图进行点乘,因为对法线的方向进行了修改,所以实际上就是控制高光和阴影

最后的效果是这样的:

原始的PPT在这里,和这里