我一直在寻找一些有关如何使用GLSL着色器复制photoshop斜角效果的信息。
我找到了一些着色器示例,但似乎无法将其包裹住。我偶然发现了这个问题https://dsp.stackexchange.com/questions/530/bitmap-alpha-bevel-algorithm, 可以达到预期的效果,但是我不知道如何将其转换为着色器。
任何建议将不胜感激。
答案 0 :(得分:0)
首先,我会警告您,根据GPU和所需的质量,将其放入着色器可能会有些棘手,但您可以尝试一下。
我将这个问题分为两个单独的问题:
广告。 1。
您要查找具有低于某个阈值的alpha值的最近像素。您先测试着色器开始的像素,然后再测试其相邻像素(3x3网格,无中心),然后测试其相邻像素(5x5),依此类推...继续进行此操作,直到找到像素或超出像素大小为止。你的斜角。
这是棘手的部分。数学运算不多,但是您有大量的纹理读取信息,而if-else
是GPU不喜欢的。当您增加边框大小时,性能会很快下降。 GPU在执行着色器时似乎具有某种“超时”功能,因此,如果花费太长时间,即使是工作正常的GPU也可能会被静默杀死。这些限制可能在GPU和/或驱动程序之间有所不同,因此很难说机器上的代码是否可以在其他机器上使用。很难确定要测试,但是可以做到。
广告。 2。
有了距离和方向,您几乎完成了。如果距离大于边框大小,则当前像素不是边框,否则,将您的方向与某个light-dir(在示例中为左上)进行比较,然后确定边框应变亮还是变暗。 您还可以使用距离来影响明暗强度,这样您就可以获得圆滑的坡度而不是平坦的坡度。
所有这些只是最简单的方法。您可以尝试将其拆分为渲染过程,进行一些预计算,缩小纹理,将mip贴图用作四叉树等,以加快代码的速度。
编辑以供您评论:
只要您不打算每帧修改数据,就可以进行很多预计算。
假设您有一个纹理,其中孔为白色,其余为黑色,并且您想柔化该图像。您编写了一个对当前像素进行采样的着色器(我们将其称为pix
),并对它的8个邻居进行采样并对其求平均值(我们将其称为avg
),然后调用:
result = max( pix, avg );
这样,您将在周围涂抹白色,但不要使已经是白色的像素变暗。您可以连续运行此着色器几次以获得更大的涂抹效果。现在,如果您反转颜色,您将获得距离值之类的东西,对:)吗?
(无需反转即可完成,您可以使用alpha
通道和min
而不是max
,我只是觉得这种方式更容易描述)。
此涂片的形状取决于avg
值的样本图案。我告诉过您采用3x3网格,但是您可以在此处进行实验并使用更多的圆形。
此距离值的梯度将为您提供方向。
您甚至可以进一步了解并预先计算阴影数据。您可以使用每个像素要添加或减去的值来计算纹理。将此纹理打包到0-255范围内。然后,在渲染过程中,您将对该纹理进行采样,从中减去0.5(移至[-0.5,0.5]范围),然后添加至源纹理。