GLSL片段着色器:按时间过去控制颜色

时间:2018-01-31 12:46:18

标签: three.js glsl webgl fragment-shader

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

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

这是我的片段Shader:

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);
}

以下是我设置材料的方法:

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,
    });

以下是我如何更新制服(循环中)

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

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

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 );
        }

真的看不出我做错了什么。

1 个答案:

答案 0 :(得分:1)

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

你自己找到了正确的解决方案 - 在足够大的类型上对CPU进行非常大的算术运算。计算CPU上的经过时间并将其作为制服传递给着色器。