Opengl es 用于纹理的GLSL着色器';烟雾';效应

Opengl es 用于纹理的GLSL着色器';烟雾';效应,opengl-es,glsl,opengl-es-2.0,Opengl Es,Glsl,Opengl Es 2.0,我环顾四周,没有发现任何相关的东西。我正在创建一个着色器,以提供纹理烟雾效果动画,如下所示: 不是要求一个完整/完整的解决方案(尽管那将是非常棒的),而是我可以从哪里开始实现这个效果的任何指针。我是否需要绘制图形的顶点,或者如果我只有纹理,这是可能的?在图中的示例中,它们似乎有顶点。可能是花形的“画”被记录下来,然后不断地回放。然后,效果将基于绘制顶点时的时间偏移击中顶点。那里的效果似乎主要是运动模糊 因此,要复制这种效果,需要顶点。看看花的顶部是如何在底部之前消失的吗?如果你仔细观察,你会发

我环顾四周,没有发现任何相关的东西。我正在创建一个着色器,以提供纹理烟雾效果动画,如下所示:


不是要求一个完整/完整的解决方案(尽管那将是非常棒的),而是我可以从哪里开始实现这个效果的任何指针。我是否需要绘制图形的顶点,或者如果我只有纹理,这是可能的?

在图中的示例中,它们似乎有顶点。可能是花形的“画”被记录下来,然后不断地回放。然后,效果将基于绘制顶点时的时间偏移击中顶点。那里的效果似乎主要是运动模糊

因此,要复制这种效果,需要顶点。看看花的顶部是如何在底部之前消失的吗?如果你仔细观察,你会发现模糊效果的计时实际上是沿着花的逆时针方向进行的。即使是在gif的第一帧上,您也可以看到花朵形状的末端比开头更亮的黄色

随着时间的推移,运动模糊的角度似乎也会发生变化,从更向左的方向变为更向上的方向

而且片段的亮度也随着时间的推移而变化,从淡黄色开始,到黑色或透明结束

我无法从中分辨出效果是否是相加的,这意味着他们将效果应用于整个帧,然后应用于每个帧的效果结果,或者是否在每个帧重新创建效果。如果重新创建每一帧,您将能够反向执行效果,并显示图像

如果您希望在位图纹理而不是线对象上获得这种效果,这也是可行的,尽管方法会有所不同

让我们从line对象开始,假设您有顶点。我的方法是将衰减百分比作为属性添加到顶点数据中。然后,渲染的每个帧都会首先基于该顶点的时间更新衰减百分比。稍微错开

然后,着色器将使用运动模糊着色器绘制线段,其中运动模糊量、模糊角度和线段颜色由“衰退”属性指定的可变变量控制。我还没有测试这个着色器。将其视为伪代码。但我会这样做。。。顶点着色器:

 uniform mat4 u_modelViewProjectionMatrix;
 uniform float maxBlurSizeConstant;  // experiment with value and it will be based on the scale of the render

 attribute vec3 a_vertexPosition;
 attribute vec2 a_vertexTexCoord0;
 attribute float a_decay;

 varying float v_decay;
 varying vec2 v_fragmentTexCoord0;
 varying vec2 v_texCoord1;
 varying vec2 v_texCoord2;
 varying vec2 v_texCoord3;
 varying vec2 v_texCoord4;
 varying vec2 v_texCoordM1;
 varying vec2 v_texCoordM2;
 varying vec2 v_texCoordM3;
 varying vec2 v_texCoordM4;

 void main()
 {
    gl_Position = u_modelViewProjectionMatrix * vec4(a_vertexPosition,1.0);

    v_decay = a_decay;

    float angle = 2.8 - a_decay * 0.8;  // just an example of angles

    vec2 tOffset = vec2(cos(angle),sin(angle)) * maxBlurSizeConstant * a_decay;

    v_fragmentTexCoord0 = a_vertexTexCoord0;

    v_texCoordM1 = a_vertexTexCoord0 - tOffset;
    v_texCoordM2 = a_vertexTexCoord0 - 2.0 * tOffset;
    v_texCoordM3 = a_vertexTexCoord0 - 3.0 * tOffset;
    v_texCoordM4 = a_vertexTexCoord0 - 4.0 * tOffset;
    v_texCoord1 = a_vertexTexCoord0 + tOffset;
    v_texCoord2 = a_vertexTexCoord0 + 2.0 * tOffset;
    v_texCoord3 = a_vertexTexCoord0 + 3.0 * tOffset;
    v_texCoord4 = a_vertexTexCoord0 + 4.0 * tOffset;
 }
片段着色器:

 uniform sampler2D u_textureSampler;

 varying float v_decay;
 varying vec2 v_fragmentTexCoord0;
 varying vec2 v_texCoord1;
 varying vec2 v_texCoord2;
 varying vec2 v_texCoord3;
 varying vec2 v_texCoord4;
 varying vec2 v_texCoordM1;
 varying vec2 v_texCoordM2;
 varying vec2 v_texCoordM3;
 varying vec2 v_texCoordM4;

 void main()
 {
     lowp vec4 fragmentColor = texture2D(u_textureSampler, v_fragmentTexCoord0) * 0.18;

     fragmentColor += texture2D(u_textureSampler, v_texCoordM1) * 0.15;
     fragmentColor += texture2D(u_textureSampler, v_texCoordM2) * 0.12;
     fragmentColor += texture2D(u_textureSampler, v_texCoordM3) * 0.09;
     fragmentColor += texture2D(u_textureSampler, v_texCoordM4) * 0.05;
     fragmentColor += texture2D(u_textureSampler, v_texCoord1) * 0.15;
     fragmentColor += texture2D(u_textureSampler, v_texCoord2) * 0.12;
     fragmentColor += texture2D(u_textureSampler, v_texCoord3) * 0.09;
     fragmentColor += texture2D(u_textureSampler, v_texCoord4) * 0.05;

     gl_FragColor = vec4(fragmentColor.rgb, fragmentColor.a * v_decay);
 }
当然,技巧在于根据时间上的微小偏移改变每个顶点的衰减量

如果你想对一个精灵做同样的事情,你将做一些非常相似的事情,除了每个顶点的衰减之间的差异必须被处理才能得到正确的结果,因为只有4个顶点

抱歉-编辑

对不起。。。上面的着色器模糊传入纹理。它不一定会模糊正在绘制的线的颜色。这可能是你想要做的,也可能不是。但是,如果你不知道你真正想要完成什么,很难给你一个完美的答案。我觉得你更愿意在精灵上做这件事,而不是在基于线顶点的对象上。因此,不,您不能按原样将此着色器复制并粘贴到代码中。但它展示了你如何做你想做的事情的概念。尤其是在纹理上而不是在基于顶点的直线上执行此操作时

此外,上面的着色器不完整。例如,它不会展开以允许模糊超出纹理的边界。它从精灵在精灵表中的区域外部获取纹理信息。要解决此问题,您必须从一个大于精灵的边界框开始,并将顶点中的精灵缩小到正确的大小。而且你不必在精灵的边界之外从怨恨单上抓取textels。有很多方法可以做到这一点,而不必在精灵表中的精灵周围包含一堆空白

更新

再看,它可能是基于粒子的。如果是,则它们再次具有所有顶点,但作为粒子位置。我比较喜欢直线段,因为我看不到任何间隙。因此,如果是粒子,那么有很多粒子,它们被紧密地放置在一起。这些粒子仍然在从顶部花瓣到最后一片花瓣层叠衰减。即使是线段,也可以将顶点视为粒子来应用风和重力

至于烟雾效果是如何工作的,请通过71 squared查看此helper应用程序:


它的工作方式是你购买Mac应用程序,用来设计和保存你的粒子。然后你去他们的github获取iOS代码。但是这个特殊的代码创建了一个粒子发射器。用粒子做一个形状将是不同的代码。但粒子的演化过程是相同的。

在图中的示例中,它们似乎具有顶点。可能是花形的“画”被记录下来,然后不断地回放。然后,效果将基于绘制顶点时的时间偏移击中顶点。那里的效果似乎主要是运动模糊

因此,要复制这种效果,需要顶点。看看花的顶部是如何在底部之前消失的吗?如果你仔细观察,你会发现模糊效果的计时实际上是沿着花的逆时针方向进行的。即使是在gif的第一帧上,您也可以看到花朵形状的末端比开头更亮的黄色

随着时间的推移,运动模糊的角度似乎也会发生变化,从更向左的方向变为更向上的方向

而且片段的亮度也随着时间的推移而变化,从淡黄色开始,到黑色或透明结束

我无法从中分辨出效果是否是加性的,这意味着他们将效果应用于整个帧,然后应用于
//p = uv coord, o = random offset for per-pixel noise variation, t = time
vec3 smoke(vec2 p, vec2 o, float t)
{
    const int steps = 10;
    vec3 col = vec3(0.0);
    for (int i = 1; i < steps; ++i)
    {
        //step along a random path that grows in size with time
        p += perlin(p + o) * t * 0.002;
        p.y -= t * 0.003; //drift upwards

        //sample colour at each point, using mipmaps for blur
        col += texCol(p, float(steps-i) * t * 0.3);
    }
    return col.xyz / float(steps);
}