关于three.js:GLSL片段着色器:通过时间控制颜色

GLSL Fragment Shader: control color by time passed

我正在尝试编写一个简单的着色器(在THREE.js的帮助下),其中颜色将随着时间的流逝而更新(从黑色到白色)。

使用示例,我正在计算时间的流逝,然后使用它来设置我的gl_FragColor,但是它不起作用:粒子保持黑色,然后突然在大约10秒的时间内突然弹出到100%。

这是我的片段着色器:

1
2
3
4
5
6
7
8
9
10
precision highp float;

uniform float uTime;
uniform float uStartTime;

void main() {
    float timePassed = (uTime - uStartTime) / 1000.0 * 0.1;

    gl_FragColor = vec4(fract(timePassed), fract(timePassed), fract(timePassed), 1.0);
}

这是我设置材料的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
const simulationMaterial = new THREE.ShaderMaterial({
        uniforms: {
            tPositions: { type: 't', value: positionsTexture },
            tOrigins: { type: 't', value: originsTexture },
            tPerlin: { type: 't', value: perlinTexture },
            uTime: { type: 'f', value: 0.0 },
            uStartTime: { type: 'f', value: Date.now() },
        },
        vertexShader: vertexSimulationShader,
        fragmentShader: fragmentSimulationShader,
        side: THREE.DoubleSide,
        transparent: true,
    });

这是我如何更新制服的方法(循环)

1
2
simulationMaterial.needsUpdate = true;
simulationMaterial.uniforms.uTime.value = Date.now();

我的顶点着色器工作正常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
precision highp float;

        uniform vec3 color;
        uniform sampler2D tPositions;

        uniform mat4 modelViewMatrix;
        uniform mat4 projectionMatrix;

        attribute vec2 uv;
        attribute vec3 position;
        attribute vec3 offset;
        attribute vec3 particlePosition;
        attribute vec4 orientationStart;
        attribute vec4 orientationEnd;

        varying vec3 vPosition;
        varying vec3 vColor;

        void main(){
            vPosition = position;
            vec4 orientation = normalize( orientationStart );
            vec3 vcV = cross( orientation.xyz, vPosition );
            vPosition = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + vPosition );

            vec4 data = texture2D( tPositions, uv );
            vec3 particlePosition = (data.xyz - 0.5) * 1000.0;

            vColor = data.xyz;

            gl_Position = projectionMatrix * modelViewMatrix * vec4(  vPosition + particlePosition, 1.0 );
        }

真的看不到我在做什么错。


着色器的highp float类型为32位,不足以准确表示与Date.now()一样大的值。实际上,可以精确地表示为32位浮点数的最后一个整数是16,777,217,比今天的Date.now()小5个数量级。也就是说,此类型的大小不足以有意义地计算(Date.now()+10) - Date.now())。 Javascript引擎将数字表示为64位浮点数,它具有使算术足够精确地工作所需的范围。

您自己找到了正确的解决方案-以足够大的类型在CPU上执行非常大的运算。计算CPU上经过的时间,然后将其作为均匀值传递给着色器。