GPUPro360 Pre-Integrated Skin Shading

# brief
- 这个应该是对应了siggraph2011的一个PPT
- 卖点是消耗低、效果和texture space diffusion差不多
- 方法
    - 对dot(N,L)的变化(表面曲率的变化)造成的surface级别的scattering效果,用一个pre-integrated lookup texture(用curvature和NOL来查询)来修正NOL,效果上就是背光部分由于scattering有发红的效果
    - 对于法线上的小feature(wrinkle和bump),用filter过的bentnormal来搞(blur过,另外不同color有不同normal),效果上就是脸上的坑、痕迹没那么强了(更符合真实)
    - 对于shadow,用trick,在penumbra的部分做diffusion效果,效果是阴影过渡处会有scattering导致的变红


# 5.1 introduction
- 表面的漫反射和进入真皮层后的SSS
- 目前方法(TSD,SSSSS)
    - simulate light as it travels through skin
    - gather light from neighboring location
- this method
    - rather than gathering neighboring light, preintegrate the effect of scattered light
    - this allow us to achieve nonlocal effect using only locally stored info
    - 说是no extra pass, no blur


# 5.2 background and previous work
- texture-space diffusion(TSD)
    - 先把入射光存在texture space,然后用blur来模拟diffusion
    - 最早在Matrix:reload中用来搞人脸,当时甚至RGB通道使用不同的blur kernel
    - 由于blur很suit hardware,所以很快用来做实时渲染,但是simple blur的效果肯定不如film里那种
    - diffuse profile: 几个函数,输出是多少光离开了surface,输入是进入surface走的路径长度,有2种模型 dipole(simple)和multipole(多层)


# 5.3 Pre-Integrating the Effects of Scattering
- pre-integrate的优势是计算简化
- 专门针对skin、并且找到where and what to pre-integrate
- 带来subsurface效果的是
    - mesh curavature
    - bump in normal map
    - shadow


# 5.4 Scattering and Diffuse Light
- 只是surface上的curve就会导致incident light的变化,这就是N*L导致的
- 可以通过调整dot(N,L)来搞出scattering,比如在backfacing的地方做wrap(gpugems1上的方法 wrap lighting),让不同波长有不同的dot(N,L).但是这么搞事trick,所以不通用
- 为此要使用measured BRDF,一般BRDF是不会直接用dot(N,L)的,这里因为只关心diffuse light,所以用dot(N,L)作为输入
- 如何存这个measured brdf,考虑过用SH来光在各个方向时的BRDF数值,到那时SH只能存低频、否则要很多coefficient.最后决定用dot(N,L)和curvature作为查询的2个参数.个人感觉:不太明白这里用SH的意义,如果是只和Dot(N,L)有关的话SH明显存了很多重复的东西,因为有很多方向对应的Dot(N,L)是一样的
- 算lookup texture的时候用ring上的积分替代了sphere上的积分,说是效果也没啥大区别
- shader里算曲率:c = length(fwidth(N)) / length(fwidth(p));
    - 有个坑:这样算的话一个三角形上的C就是一样的了,这种时候考虑用曲率texture
- 局限:这个模型假设scattered light和物体本身的曲率有关,然而实际是也和shading的这个点周围的曲率有关,所以只适用于比较平滑的表面,当表面曲率变化非常大的时候就break了。好在可以把detail分2层,一层是geometry的,一层是normal的


# 5.5 Scattering and Normal Maps
- 一个很重要的观察:细小的crease的normal造成的scattering其实和把这个crease的normal给blur(flat surface)过造成的scattering差不多。
- 然后有一点很重要,这个效果对不同的波长是不同的.
- 看效果图,正常皮肤的皱纹不应该那么明显。不特殊处理normal会导致normal的部分由于曲率大而不对劲
- 要做的事情是对不同的波长来filter(blur) normal,让normal在小地方的剧烈变化被filter掉,不对scattering造成影响
    - 为了性能,不然你得周围采多点算光照然后平均
- 不能直接对normal blur,大概是因为想让光照效果是linear filtered,但是normal对lighting的影响不是linear的
- 总之是有一堆方法一堆研究如何filter normal的
- 说是其实用diffusion profiles来blur normal map也有不错的效果
- 用4个normalmap会耗,所以考虑用近似:
    - 方法1:用geometry normal和specular normal,把其他差值出来,work for certain art
    - 方法2:从书上和ppt上的描述不能完全理解。似乎是1个normal map,但是2个sampler,一个是spec,另外是clamp到糙mip,用来采red normal?
- 性能方面。因为每个wavelength有不同normal,所以lookup texture查找次数也增加


# 5.6 Shadow Scattering
- 要的是scatter into shadow的效果,用trick来做
- 就是把shadowmap的falloff部分的其中一部分拿来做红黑渐变
- 具体做法
    - 找个representative shadow penumbra P()
    - 用diffuse profile来pre-integrate这个P()
    - 这样对于一个shadow value,可以通过P的inverse函数找到position,再结合pre-integrate的lookup得到另外一个falloff
    - 最终还是用和diffuse产不多的一个falloff lookup(用penumbra(derivative of shadow value)和shadow value来查询)
- 一些问题,assumption不成立导致
    - assume shadow transition is sharp,说是如果有screen door这种就会导致大片的shadow value一样
    - assume flat surface,导致表面很倾斜时也不对
- 为了解决slant surface的问题,shadow的lookup texture也是2dimension, size of penumbra in world space
- 又有一堆细节

# 5.7 Conclusion and Future Work
- drawback
    - 当使用derivative来模拟curvature的时候,mesh的triangle edge会明显。总之就是curavature有时候算出来怪.
        - 提到geometry shader,因为geometry shader有primitive信息,但是也没给明确做法
        - 提到可以来个texture,存一下curvature
    - normalmap和diffuse lighting
        - 因为有3个wavelength有不同的falloff,所以要把dot(N, L)的3个分量分别用来查哪个红黑lookup 3次得出diffuse

# related
- Advanced Techniques for Realistic Real-Time Skin Rendering.” In GPU Gems 3, Chapter 14
- siggraph2011 Pre-integrated Skin Rendering(就是本文的作者写的,各有详略)

猜你喜欢

转载自blog.csdn.net/killer4747/article/details/80809803
今日推荐