如何在GLSL中编写“纹理呼吸”着色器?

时间:2014-08-14 21:52:38

标签: opengl glsl shader

我正在开发一款2D视频游戏,在互联网上搜索与其无关的内容时,我发现了这段视频:http://vimeo.com/67886447 我很喜欢。我想要它。

作者概述了这个过程:

  

通过计算源的矢量导数产生效果   照片然后沿结果轴应用迭代平流。一个   次级标量场控制和强度和幅度   平流并允许一系列有趣的效果,包括脉冲,   挥手和呼吸。

据我了解:计算梯度场,然后像素沿相应矢量的方向和幅度移动。时间是矢量幅度的乘数,我猜。

所以,我想,我理解这个过程,但由于我是GLSL的新手,而且一般是着色器,我不知道如何编写代码。

到目前为止,这是我看到代码大纲的方式:

迭代图像,用使用某种边缘检测算法产生的向量填充矩阵。 再次迭代图像并按矢量幅度*时间移动所有像素。

几个具体问题:

这是否有效,性能明智(当然是普通PC)?

是否可以使用简单的边缘检测算法(检查附近的8个像素,比较它们之间的差异,并将其保持为幅度,矢量的方向将由2个像素之间的角度决定差)。

我如何取代像素?我想移动一个像素会在它所在的位置留下一个空白区域,或者,如果我克隆像素,会有很多奇怪的重叠,图像会变坏。

编辑:

我刚刚意识到在一次通过中做得更好:计算向量,然后立即移动像素。你觉得怎么样?

我想,我使用错了,并将其视为迭代。

这是我到目前为止的代码。它很简单,它只沿着+ x轴。

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
varying vec2 vTexCoord;
uniform sampler2D u_texture; //diffuse map

void main( void ) {



vec2 pos = vec2(1,0);
vec4 px1 = texture2D(u_texture, vTexCoord+(pos/resolution));
vec4 dif =  px1 - texture2D(u_texture, vTexCoord);


vec4 color = texture2D(u_texture, vTexCoord+(vec2((dif.r+dif.g+dif.b)*time,0)/resolution));


    gl_FragColor = vec4(color.xyz,1.0);

//gl_FlagColor = color;
}

现在我只需要为其余的轴做这件事。效果实际上看起来像是应该做的。

我为Y轴做了这个,这就是我得到的,我如何修复工件,所以看起来颜色实际上是扩展的,而不仅仅是移动。

breathing thing http://rghost.ru/57475312/image.png

(着色器仅应用于背景图像)

1 个答案:

答案 0 :(得分:5)

你需要更像是GLSL中的函数式程序员。你不会迭代任何东西;您提供的函数在给定适当的输入的情况下将提供输出的片段。 GPU处理在适当的地方应用该功能。根据特定于供应商的扩展,输入需要完全不同于输出 - 因此输入是不可变的。此外,GPU还会组织您输出的位置。

所以,不,你不会迭代任何东西。而且你不能写一个着色器来选择它要输出的位置,只能输出它要输出的内容。

你可能想要研究的是Stam's Advection,它几​​乎可以解决这个问题。对于每个输出P,您将查找有助于它的颜色来自何处的记录。由于您可以自由地对输入进行采样(不考虑性能问题),因此您可以收集适当的输出。