zoukankan      html  css  js  c++  java
  • Unity3d 屏幕空间人体皮肤知觉渲染&次表面散射Screen-Space Perceptual Rendering & Subsurface Scattering of Human Skin

    之前的人皮渲染相关

    前篇1:unity3d Human skin real time rendering 真实模拟人皮实时渲染

    前篇2:unity3d Human skin real time rendering plus 真实模拟人皮实时渲染 plus篇

    SSS:Unity3d shader之次表面散射(Subsurface Scattering)

    PBR:Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF

     

    Screen-Space Perceptual Rendering & Subsurface Scattering of Human Skin其实就是Screen-Space Subsurface Scattering与Subsurface Scattering 简称SSSSS&SSS,8S,博主自创,,哈哈也不是,结合了许多资料弄出了看的更顺眼的人皮。。是不是要写篇论文了呢= =。。。

    本来是录了视频的,但是视频降质,色差太大,就没有上传。。。

    先上肉质鲜嫩的两张图



     夜光引擎(Luminous Studio)的新demo->witch,能明显看到SSS和PBR效果,文章的最后也有对比,最终幻想的引擎渲染就是棒

    想 要人皮肤更加真实,人皮肤上的细节成了一个关键问题,包括褶皱、毛孔、毛囊,甚至是伤疤,这既可以造成我们的障碍,也可以帮助我们使皮肤看起来更真实。如 果只是用普通的Lambert,甚至是PBR得到的效果也是不真实的,非常生硬、干燥,塑料质感。如下图所示,下图(No SSSSS)是博主用unity5 的standard PBR shader来渲染的。我们缺的就是次表面散射,之前的文也说过了,皮肤其实是有些轻微的半透明的,大多数的漫反射光来自次表面散射 ,光线接触到皮肤时,有大约96%被皮肤各层散射了,只有大约4%被反射了,所以我们实现了SSS再加上PBR,就给予皮肤渲染一个非常真实的结果,如下 图所示,(SSSSS ON)是unity5 的standard PBR shader再加上屏幕空间的SSS的处理,比之前的更加真实,柔软(博主在此处用 unity的PBR仅作对比,下文要讲local SSS与SSSSS的结合)。
     
     


    我们把皮肤看成三层,油脂层(微量,很薄),表皮层,真皮层。正是因为有油脂层,因为油脂层直接把光反射出去,所以皮肤上才会有高光产生,我们使用PBR的高光完美模拟皮质层,稍后讲解。下图为多层皮肤模型。
     

    没有被反射的光通过折射进入子表面层,光进入这些层之后部分被吸收(获得颜色)和散射,再从皮肤中入射点附近的出射点射出。这个过程就产生了次表面散射的效果。

    local SSS

    先讲解local SSS

    油脂层

    只讲解一下油脂层的反射产生的specular
    首先实现一下GPU Gem3提到的Beckmann 分布函数和Fresnel Reflectance。
    它使用了一个贴图来模拟Beckmann 分布
     
    这是GPU Gem3的代码

     1 float fresnelReflectance( float3 H, float3 V, float F0 )
     2  {
     3 float base = 1.0 - dot( V, H );  
     4 float exponential = pow( base, 5.0 );  
     5 return exponential + F0 * ( 1.0 - exponential );  
     6 }
     7     float PHBeckmann( float ndoth, float m )  
     8   {  
     9     float alpha = acos( ndoth );  
    10     float ta = tan( alpha );  
    11     float val = 1.0/(m*m*pow(ndoth,4.0))*exp(-(ta*ta)/(m*m));  
    12     return val;  
    13   }  
    14   // Render a screen-aligned quad to precompute a 512x512 texture.  
    15      float KSTextureCompute(float2 tex : TEXCOORD0)  
    16   {  
    17     // Scale the value to fit within [0,1] – invert upon lookup.  
    18      return 0.5 * pow( PHBeckmann( tex.x, tex.y ), 0.1 );  
    19   }  
    20      float KS_Skin_Specular( float3 N, // Bumped surface normal  
    21      float3 L, // Points to light  
    22      float3 V, // Points to eye  
    23      float m,  // Roughness  
    24      float rho_s, // Specular brightness  
    25      uniform texobj2D beckmannTex )  
    26   {  
    27     float result = 0.0;  
    28     float ndotl = dot( N, L );  
    29   if( ndotl > 0.0 )  
    30   {  
    31      float3 h = L + V; // Unnormalized half-way vector  
    32      float3 H = normalize( h );  
    33      float ndoth = dot( N, H );  
    34      float PH = pow( 2.0*f1tex2D(beckmannTex,float2(ndoth,m)), 10.0 );  
    35      float F = fresnelReflectance( H, V, 0.028 );  
    36      float frSpec = max( PH * F / dot( h, h ), 0 );  
    37      result = ndotl * rho_s * frSpec; // BRDF * dot(N,L) * rho_s  
    38    }  
    39    return result;  
    40   } 


    博主的实现结果:

     


    然后是之前写的文章Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF

     

    的光照模型的specular效果

     

    Specular Occlusion高光遮蔽

    这里我们可以使用Specular Occlusion高光遮蔽的方法遮蔽我们不想要的高光,比如我们不想要眉毛也有油脂层的高光,就需要做一个高光遮蔽贴图,把眉毛等处遮蔽。
    下图右侧的鼻孔,眉毛等处都是不想要的高光。
     
    还有遮蔽高光的毛孔
     

    微观细节

     
    关于细节部分可以自己生成second specular lobe
    下图是使用3ds Max的 noise functions生成的微观细节
     

     
    再把细节高光和高光线性混合

     

    最后注意:

    由于油脂层的油和皮肤最外层的组织细胞为电介质材质,它们在反射光线时不会对光进行着色(如金这种金属会赋予光金色,因为其在可见光波长段极大地改变了折射序号),因此,基于物理的皮肤着色在反射应使用白色

    表皮层

    然后处理表皮层
    还是blur6次达到表皮层的次表面散射效果,皮肤的颜色基本来自于表皮层
     
    上表的结果如下图
     

    上表为为了在texture-space diffusion图片空间的漫反射的权重,也就是在不同的颜色通道以不同的范围和程度进行blur,博主在ps 中进行高斯blur,也可以用代码来高斯blur
     

    真皮层

    光 线经过真皮层带出了血液的颜色,这就皮肤会有血色的原因。我们使用颜色查找贴图Look up Texture的方式来模拟在真皮层的散射,如下图,图中右上角是一张 brdf查找贴图,我们要通过曲率curvature(球半径1/r,求法见图中左上部分)和N•L,得到结果如图中下半部分。
     

    截止到这里local SSS已经基本成型,结果如下
     
     
     
     



    次表面散射的阴影与自阴影

    在阻挡光散射的边界也不只是愣愣的黑影,如下图
     
    unity的片段着色器支持自阴影,在阴影部分也使用查找贴图映射颜色,
    这是博主实现结果
     
     
     
    截止到这里local SSS的次表面散射效果已经很不错了,如果再加上屏幕空间次表面散射,效果更加真实


    SSSSS屏幕空间次表面散射

    上一个步骤之后我们已经得到一个次表面散射皮肤了,屏幕空间SSS之后效果plus。
    也是需要用blur来模拟多层散射,像大理石等只散射一次的就不需要这么多次blur。
    我们需要进行4次pass,共4次blur,前三次是 Subsurface Scattering Pass,最后一次需要降采样blur-> Boom Pass。
    博主懒了,用grid暴力采样9次blur,效果还是可以。
    四次pass如下图所示
     

     

     

    最后一次pass的模糊需降采样到size/2然后在blur
     
    最后要切记色彩空间要是linear空间。
    左图为linear空间,右图为gamma空间,在gamma空间,次表面效果直接消失了。。。
     

    最终结果展示

    夜光引擎(Luminous Studio)的新demo->witch

    博主的local SSS&SSSSS

    unity standard shader&SSSSS

    更多效果图请看:Unity5 Screen-Space Subsurface Scattering屏幕空间次表面散射SSSSS


    实现参考:
    1.    Screen-Space Sub Surface Scattering for real-time skin rendering
    2.    Review of Screen-Space Subsurface Scattering
    3.    GPU Pro - Screen-Space Perceptual Rendering of Human Skin
    4.    GPU Pro2 - Real-Time Approximation of Light Transport in Translucent Homogenous Media
    5.    GPU Pro2 - Pre-Integrated Skin Shading
    6.    Gpu Gems1 -Real-Time Approximations to Subsurface Scattering
    7.    Gpu Gems3 - The Importance of Being Linear

    8.    Gpu Gems3 - Advanced Techniques for Realistic Real-Time Skin Rendering

    之前的人皮渲染相关

    前篇1:unity3d Human skin real time rendering 真实模拟人皮实时渲染

    前篇2:unity3d Human skin real time rendering plus 真实模拟人皮实时渲染 plus篇

    SSS:Unity3d shader之次表面散射(Subsurface Scattering)

    PBR:Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF

    博主近期渲染:最近用unity5弄的一些渲染

     

                                  ---- by wolf96 

     


  • 相关阅读:
    redis 安装配置
    ORM 效率补充
    function*
    路由器
    nodejs开发辅助工具nodemon
    npm淘宝镜像配置
    Node中的模块系统
    artTemplate不仅可以在浏览器中使用,还可以在node中使用
    代码风格JavaScript standard style与Airbnb style
    osChina.net工具
  • 原文地址:https://www.cnblogs.com/zhanlang96/p/4941531.html
Copyright © 2011-2022 走看看