弧形磨砂玻璃着色器?
Curved Frosted Glass Shader?
好吧,制作透明的东西并不难,但我需要根据对象的曲线使透明度有所不同,以使其看起来不仅仅是一个平面对象。像下图这样的东西。
中心比圆柱体的两侧更透明,它更黑,这是背景色。然后是边框,顶部似乎有某种镜面照明以使其更闪亮,但我不知道在那种情况下如何实现透明度。使用相对于眼睛位置的表面法线来确定透明度值?任何帮助将不胜感激。
(将评论移至答案中并添加了更多详细信息)
使用(Sub Surface) scattering代替透明度。
你可以简化很多事情,例如假设光源在整个过程中是恒定的 surface/volume ...所以你只需要视图光线积分而不是每条光线的整个体积积分...我做它在我的大气着色器中,它看起来仍然非常棒,几乎与真实事物无法区分,请参阅 ...将它与地球和火星的照片进行比较,结果非常接近,没有任何真正复杂的数学。
有更多选项可以实现:
体素图(体积渲染)
在体积渲染引擎中实现散射很容易,但需要大量内存和电源。
使用2个深度缓冲区(正面和背面)
这需要 2 次通过剔除面和 CW/CCW 设置。这也很容易实现,但这不能处理沿相机视图 Z 轴的同一视图中的多个对象。这个想法是将两个深度缓冲区都传递给着色器,并沿其路径 cumulating/absorbing 从光源发出的光整合像素光线。像这样:
- 将几何图形作为 2 个纹理渲染到两个深度缓冲区。
- 渲染覆盖整个屏幕的四边形
- 为每个片段计算射线(绿色)
- 计算摊位深度缓冲区中的交点
获得'length,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
After/durring 您应该将颜色归一化的集成...以便生成的颜色在渲染的真实视图深度周围饱和 material。有关更多信息,请参阅下面的大气散射 link(这段代码是从中提取的)
分析对象表示
如果您知道表面方程,那么您可以在着色器内计算光路交点,而无需深度缓冲区或体素贴图。 Simple GLSL Atmospheric shader of mine 使用这种方法,因为这样处理椭球体真的很容易。
光线追踪器
如果您需要精确度并且不能使用体素贴图,那么您可以尝试使用光线追踪引擎。但是所有散射 renderers/engines(包括 #1、#2、#3)无论如何都是光线追踪器……如您所见,所有 技术这里讨论的是一样的唯一的区别是获取ray/object边界交点的方法。
好吧,制作透明的东西并不难,但我需要根据对象的曲线使透明度有所不同,以使其看起来不仅仅是一个平面对象。像下图这样的东西。
中心比圆柱体的两侧更透明,它更黑,这是背景色。然后是边框,顶部似乎有某种镜面照明以使其更闪亮,但我不知道在那种情况下如何实现透明度。使用相对于眼睛位置的表面法线来确定透明度值?任何帮助将不胜感激。
(将评论移至答案中并添加了更多详细信息)
使用(Sub Surface) scattering代替透明度。
你可以简化很多事情,例如假设光源在整个过程中是恒定的 surface/volume ...所以你只需要视图光线积分而不是每条光线的整个体积积分...我做它在我的大气着色器中,它看起来仍然非常棒,几乎与真实事物无法区分,请参阅
有更多选项可以实现:
体素图(体积渲染)
在体积渲染引擎中实现散射很容易,但需要大量内存和电源。
使用2个深度缓冲区(正面和背面)
这需要 2 次通过剔除面和 CW/CCW 设置。这也很容易实现,但这不能处理沿相机视图 Z 轴的同一视图中的多个对象。这个想法是将两个深度缓冲区都传递给着色器,并沿其路径 cumulating/absorbing 从光源发出的光整合像素光线。像这样:
- 将几何图形作为 2 个纹理渲染到两个深度缓冲区。
- 渲染覆盖整个屏幕的四边形
- 为每个片段计算射线(绿色)
- 计算摊位深度缓冲区中的交点 获得'length,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
After/durring 您应该将颜色归一化的集成...以便生成的颜色在渲染的真实视图深度周围饱和 material。有关更多信息,请参阅下面的大气散射 link(这段代码是从中提取的)
分析对象表示
如果您知道表面方程,那么您可以在着色器内计算光路交点,而无需深度缓冲区或体素贴图。 Simple GLSL Atmospheric shader of mine 使用这种方法,因为这样处理椭球体真的很容易。
光线追踪器
如果您需要精确度并且不能使用体素贴图,那么您可以尝试使用光线追踪引擎。但是所有散射 renderers/engines(包括 #1、#2、#3)无论如何都是光线追踪器……如您所见,所有 技术这里讨论的是一样的唯一的区别是获取ray/object边界交点的方法。