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



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

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

这是我的片段着色器:

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

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

着色

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

您自己已经找到了正确的解决方案 - 在 CPU 上以足够大的类型进行真正的大算术。计算 CPU 上经过的时间,并将其作为统一传递给着色器。

最新更新