弯曲的磨砂玻璃着色器?

时间:2015-11-05 22:40:47

标签: glsl shader transparency light-scattering

制作透明的东西并不困难,但我需要根据物体的曲线使透明度不同,使其看起来不仅仅是一个扁平的物体。如下图所示。

中心比圆柱体的侧面更透明,更黑,这是背景颜色。然后有一个挡板似乎在顶部有一些镜面光,使它更有光泽,但我不知道如何在这种情况下采取透明度。使用表面相对于眼睛位置的法线来确定透明度值?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

(将评论移到答案中并添加了更多细节)

使用(Sub Surface) scattering代替透明度。

你可以通过假设光源在整个表面/体积上保持不变来简化很多事情...所以你只需要视图光线集成而不是每条光线的整个体积积分......我在大气层中这样做着色器,它看起来非常棒,几乎与真实的东西无法区分some newer screenshots ...将它与地球和火星的照片进行比较,结果非常接近,没有任何真正复杂的数学。

如何实现这一目标有更多选择:

  1. 体素贴图(体积渲染)

    很容易实现散射到体积渲染引擎,但需要大量内存和电源。

  2. 使用2个深度缓冲区(正面和背面)

    这需要2次通过Cull face on和CW / CCW设置。这也很容易实现,但是这不能沿着摄像机视图的Z轴处理同一视图中的多个对象。我们的想法是将两个深度缓冲器传递到着色器,并沿着其路径积累像素光线,累积/吸收来自光源的光。像这样:

    SSS 2 Depth buffers

    1. 将两个深度缓冲区的几何体渲染为2个纹理。
    2. 渲染四边形覆盖整个屏幕
    3. 为每个片段计算光线(绿色)
    4. 计算展位深度缓冲区中的交叉点 获得' length,ang'
    5. 使用散射沿长度积分以计算像素颜色

      我使用这样的东西:

         vec3 p,p0,p1; // p0 front and p1 back face ray/depth buffer intersection points
         int n=16; // integration steps
         dl=(p1-p0)/float(n); // integration step vector
         vec3 c=background color;
         float q=dot(normalize(p1-p0),light)=fabs(cos(ang)); // normal light shading
      
         for (p=p1,i=0;i<n;p1-=dp,i++)                // p = p1 -> p0 path through object
              {
              b=B0.rgb*dl;  // B0 is saturated color of object
              c.r*=1.0-b.r; // some light is absorbed
              c.g*=1.0-b.g;
              c.b*=1.0-b.b;
              c+=b*q;       // some light is scattered in
              } // here c is the final fragment color
      
    6. 在积分之后,您应该对颜色进行标准化...以使得到的颜色在渲染材质的实际视图深度周围饱和。有关更多信息,请参阅下面的大气散射链接(这段代码是从中提取的)

    7. 分析对象表示

      如果您知道表面方程,则可以计算着色器内的光路交点,而无需深度缓冲区或体素图。这个Simple GLSL Atmospheric shader of mine使用这种方法,因为椭圆体很容易以这种方式处理。

    8. 光线追踪器

      如果您需要精确度并且无法使用体素贴图,那么您可以尝试使用光线跟踪引擎。但是所有散射渲染器/引擎(包括#1,#2,#3 )都是射线追踪器...正如您所看到的,所有技术 都是相同唯一的差异 获取光线/​​物体边界交叉点的方法。