Glsl 曲面磨砂玻璃着色器?

Glsl 曲面磨砂玻璃着色器?,glsl,shader,transparency,light-scattering,Glsl,Shader,Transparency,Light Scattering,好吧,使某些东西透明并不是那么困难,但我需要透明度根据对象的曲线而有所不同,使它看起来不仅仅是一个平面对象。有点像下面的图片 中心比圆柱体的侧面更透明,它更黑,这是背景色。然后是挡板,它的顶部似乎有一些镜面照明,使它更闪亮,但我不知道如何在这种情况下进行透明度。使用曲面相对于眼睛位置的法线来确定透明度值?任何帮助都将不胜感激。(将评论移到答案中,并添加更多细节) 使用而不是透明。 你可以简化很多事情,比如假设光源在整个表面/体积上是恒定的。。。所以你只需要查看光线积分,而不是每个光线的整体体积积

好吧,使某些东西透明并不是那么困难,但我需要透明度根据对象的曲线而有所不同,使它看起来不仅仅是一个平面对象。有点像下面的图片

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

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

使用而不是透明。

你可以简化很多事情,比如假设光源在整个表面/体积上是恒定的。。。所以你只需要查看光线积分,而不是每个光线的整体体积积分。。。我在我的大气着色器中做了这件事,它看起来仍然非常棒,几乎无法与真实的东西区分开来。。。我们将它与地球和火星的照片进行了比较,结果非常接近,没有任何复杂的数学运算

如何实现这一点还有更多选项:

  • 体素贴图(体绘制)

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

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

    这需要2次通过,并启用消隐面和CW/CCW设置。这也很容易实现,但无法处理同一视图中沿摄影机视图Z轴的多个对象。其思想是将深度缓冲区传递给着色器,并沿其路径积分像素光线,从而累积/吸收来自光源的光。大概是这样的:

       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
    

  • 将两个深度缓冲区中的几何体渲染为2个纹理
  • 渲染覆盖整个屏幕的四边形
  • 为每个碎片计算射线线(绿色)
  • 计算展位深度缓冲区中的交点 获取“长度,ang”
  • 使用散射沿长度积分以计算像素颜色

    我用这样的方式:

       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
    
    vec3p,p0,p1;//p0正面和p1背面光线/深度缓冲区交点
    int n=16;//集成步骤
    dl=(p1-p0)/float(n);//积分步长向量
    vec3 c=背景色;
    浮点q=点(归一化(p1-p0),光)=晶圆(cos(ang));//正常明暗处理
    对于(p=p1,i=0;i p0)通过对象的路径
    {
    b=B0.rgb*dl;//B0是对象的饱和颜色
    c、 r*=1.0-b.r;//有些光被吸收了
    c、 g*=1.0-b.g;
    c、 b*=1.0-b.b;
    c+=b*q;//有些光散射进来
    }//这里c是最后的片段颜色
    
  • 在积分后/积分过程中,你应该对颜色进行规格化…以便得到的颜色在渲染材质的真实视图深度周围饱和。有关更多信息,请参阅下面的大气散射链接(这段代码是从中提取的)

  • 分析对象表示法

    如果你知道曲面方程,那么你可以计算着色器内部的光路交点,而不需要深度缓冲区或体素贴图。这种方法使用这种方法,因为椭球体很容易用这种方法处理

  • 光线跟踪器

    如果您需要精度并且无法使用体素贴图,那么您可以尝试使用光线跟踪引擎。但所有散射渲染器/引擎(#1、#2、#3都包括在内)无论如何都是光线跟踪器……正如您所看到的,这里讨论的所有技术都是相同的唯一的区别是获取光线/对象边界交点的方法。


  • 您不需要透明,而是需要光散射…简言之,光发射取决于穿过对象的视图光线长度及其倾斜度或光源的总覆盖率…这里是另一个散射示例(GLSL中的矿井大气)@Spektre我喜欢深度贴图的想法,idk,如果它与您链接到的实现不同,那么您将如何选择一个点来确定距离?例如,对于灯光位于顶部的圆柱体。深度贴图本质上是一个圆。但是如果说相机是从侧面,那么您将有效地渲染一个矩形,如何你能从光源的角度将其映射到深度缓冲区吗?没有GPU Gems的源吗?移动注释以回答…为你的问题添加了相关标记,为有趣的问题添加了+1(有趣的是,需要为此添加2个新标记)如何获得光线方向?如果我要渲染整个视图,我必须使用摄影机+投影矩阵的倒数将UV坐标转换为空间中的三维位置,然后将其规格化以用作计算方向?然后用于计算灯光的角度?@user240713你得到了屏幕空间吗碎片的坐标,…光线方向是点-相机焦点…光线也是一个矢量,不需要角度-点积就足够了…只要确保你在同一坐标系下进行所有计算。正如我写的,看看我的大气散射着色器,所有的东西都在那里(包括光线计算)唯一的区别是,由于空气密度随高度的变化,计算了
    p0,p1
    点和稍微复杂的散射方程…我看了看,似乎你只是使用顶点位置作为像素位置。对吗?那么对于圆柱体,我认为这不起作用,因为所有顶点都处于相同的位置顶部或底部。如果要绘制中间部分,则选择其中一个顶点效果不太好。@user240713否我使用“片段位置”…当您使用
    varyin时