简体   繁体   English

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

[英]GLSL Fragment Shader: control color by time passed

I am trying to write a simple shader (with the help of THREE.js), where the colour will update as time passes (from black to white). 我正在尝试编写一个简单的着色器(在THREE.js的帮助下),其中颜色将随着时间的流逝而更新(从黑色到白色)。

Using examples I am calculating the time passing, and then using this to set my gl_FragColor, however it is not working: The particles stay black, and then suddenly pop to 100% some time in (approx 10seconds). 通过示例,我正在计算时间的流逝,然后使用它来设置我的gl_FragColor,但是它不起作用:粒子保持黑色,然后突然在大约10秒的时间内突然弹出到100%。

Here is my fragment 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);
}

Here is how I set up my material: 这是我设置材料的方式:

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

And here is how I'm updating the uniforms (in a loop) 这是我更新制服的方法(循环)

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

My vertex shader is working fine: 我的顶点着色器工作正常:

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

Really can't see what I'm doing wrong. 真的看不到我在做什么错。

The shader's highp float type, which is 32-bit, is not large enough to represent accurately values as big as Date.now(). 着色器的highp float类型为32位,不足以准确表示与Date.now()一样大的值。 In fact, the last integer that is accurately representable as a 32-bit float is 16,777,217 , which is 5 orders of magnitude smaller than Date.now() today. 实际上,可以精确表示为32位浮点数的最后一个整数是16,777,217 ,比今天的Date.now()小5个数量级。 That is to say, this type is not large enough to meaningfully be able to calculate (Date.now()+10) - Date.now()) . 也就是说,此类型的大小不足以有意义地计算(Date.now()+10) - Date.now()) Javascript engines represent numbers as 64-bit floats, which has the necessary range for the arithmetic to work sufficiently precisely. JavaScript引擎将数字表示为64位浮点数,该数字具有使算法足够精确地工作所需的范围。

You have found the correct solution yourself - do the really big arithmetic on the CPU in big enough types. 您自己找到了正确的解决方案-以足够大的类型在CPU上执行真正的大运算。 Calculate the elapsed time on the CPU and pass it as a uniform to the shader. 计算CPU上经过的时间,然后将其作为均匀值传递给着色器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM