如何在WebGL中实现像隧道动画这样的隧道? [英] How to implement this tunnel like animation in WebGL?

查看:127
本文介绍了如何在WebGL中实现像隧道动画这样的隧道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在WebGL中实现像隧道一样的隧道?

How to implement this tunnel like animation in WebGL?

来源: http: //dvdp.tumblr.com/

参见:如何在WebGL中实现这种旋转螺旋?

推荐答案

<嗯,这很有趣。 :)

Well, this was fun. :)

这里有一个WebGL演示: http://boblycat.org/~knute/webgl/tunnel/

A WebGL demo is available here: http://boblycat.org/~knute/webgl/tunnel/

EDIT :不再可用,但我创建了一个ShaderToy版本: https://www.shadertoy.com/view/XdKfRD

(EDIT: no longer available, but I created a ShaderToy version: https://www.shadertoy.com/view/XdKfRD)

主要算法在片段着色器中。基本思想是for循环迭代黑圈/圆圈,从大到小,也偏移中心以产生类似隧道的效果。

The main algorithm is in the fragment shader. The basic idea is a for loop iterating over the black rings/circles, from large to small, also offsetting the center to produce a tunnel-like effect.

给定任何像素,我们可以检查像素是否足够接近环以成为黑色像素的候选者。如果它在环外,打破循环以避免通过较大的环看到较小的环。

Given any pixel, we can check if the pixel is close enough to the ring to be a candidate for a black pixel or not. If it is outside the ring, break the loop to avoid seeing smaller rings through the larger ones.

与前一个(外部)圆的距离用于挤压当戒指接近时,图案会一起形成3D表面的幻觉。

The distance from the previous (outer) circle is used to "squeeze" the pattern together when rings are close, this helps create the illusion of a 3D surface.

每个戒指的波浪形图案当然是正弦曲线。像素的角度(与圆心相比)与统一的时间参数相结合,为每个环的波浪图案设置动画。

The wavy pattern of each ring is of course a sine curve. The angle of the pixel (compared to the circle center) is combined with a uniform time parameter to animate the wavy pattern for each ring.

最后,有很多尝试使用不同的参数和转换函数(如pow())来获得接近目标动画的结果。它并不完美,但非常接近。

And finally, there was lots of experimentation with different parameters and transformation functions like pow() to get the result close to the target animation. It's not perfect, but pretty close.

片段着色器代码:

#ifdef GL_ES
precision highp float;
#endif

const float PI = 3.14159265358979323846264;
const float TWOPI = PI*2.0;

const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);

const vec2 CENTER = vec2(0.0, 0.0);

const int MAX_RINGS = 30;
const float RING_DISTANCE = 0.05;
const float WAVE_COUNT = 60.0;
const float WAVE_DEPTH = 0.04;

uniform float uTime;
varying vec2 vPosition;

void main(void) {
    float rot = mod(uTime*0.0006, TWOPI);
    float x = vPosition.x;
    float y = vPosition.y;

    bool black = false;
    float prevRingDist = RING_DISTANCE;
    for (int i = 0; i < MAX_RINGS; i++) {
        vec2 center = vec2(0.0, 0.7 - RING_DISTANCE * float(i)*1.2);
        float radius = 0.5 + RING_DISTANCE / (pow(float(i+5), 1.1)*0.006);
        float dist = distance(center, vPosition);
        dist = pow(dist, 0.3);
        float ringDist = abs(dist-radius);
        if (ringDist < RING_DISTANCE*prevRingDist*7.0) {
            float angle = atan(y - center.y, x - center.x);
            float thickness = 1.1 * abs(dist - radius) / prevRingDist;
            float depthFactor = WAVE_DEPTH * sin((angle+rot*radius) * WAVE_COUNT);
            if (dist > radius) {
                black = (thickness < RING_DISTANCE * 5.0 - depthFactor * 2.0);
            }
            else {
                black = (thickness < RING_DISTANCE * 5.0 + depthFactor);
            }
            break;
        }
        if (dist > radius) break;
        prevRingDist = ringDist;
    }

    gl_FragColor = black ? BLACK : WHITE;
}

这篇关于如何在WebGL中实现像隧道动画这样的隧道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆