我正在尝试编写一个简单的着色器(在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 );
}
真的看不出我做错了什么。
答案 0 :(得分:1)
着色器的highp float
类型(32位)不足以准确表示与Date.now()一样大的值。实际上,可以准确表示为32位浮点数的最后一个整数是16,777,217,比今天的Date.now()
大5个数量级。也就是说,这种类型不够大,无法有意义地计算(Date.now()+10) - Date.now())
。 Javascript引擎将数字表示为64位浮点数,它具有足够精确地运算的必要范围。
你自己找到了正确的解决方案 - 在足够大的类型上对CPU进行非常大的算术运算。计算CPU上的经过时间并将其作为制服传递给着色器。