Whenever a user clicks, I am replacing the position data to create a point cloud that alternates between a tall cloud and a wide cloud. On the first render, it displays correctly as a tall cloud, but after clicking, all the point positions seem to reset to 0,0 instead of forming a wide cloud. What could be causing this issue?
Take a look at some snippets for debugging:
function makeCloud() {
var cloudWidth, cloudHeight;
if ( isTallCloud ) {
cloudHeight = 100;
cloudWidth = 25;
} else {
cloudHeight = 25;
cloudWidth = 100;
}
isTallCloud = !isTallCloud;
var positions = new Float32Array( particles * 4 );
var offsets = new Float32Array( particles * 4 );
for ( var i = 0, i4 = 0; i < particles; i ++, i4 +=4 ) {
positions[ i4 + 0 ] = ( Math.random() * 2 - 1 ) * cloudWidth; // x
positions[ i4 + 1 ] = ( Math.random() * 2 - 1 ) * cloudHeight; // y
positions[ i4 + 2 ] = 0.0; // velocity
positions[ i4 + 3 ] = 0.0; // velocity
offsets[ i4 + 0 ] = positions[ i4 + 0 ]; // width offset
offsets[ i4 + 1 ] = positions[ i4 + 1 ]; // height offset
offsets[ i4 + 2 ] = stateChange; // this will hold the change state ( 0.0 or 1.0 )
offsets[ i4 + 3 ] = 0.0; // not used
}
cloudData = {
"positions" : positions,
"offsets" : offsets
}
}
function updateStateChange() {
for ( var i = 0, i4 = 0; i < particles; i ++, i4 +=4 ) {
cloudData.offsets[ i4 + 2 ] = stateChange; // this will hold the change state ( 0.0 or 1.0 )
}
}
function updateOffsets() {
offsetsTexture = new THREE.DataTexture( cloudData.offsets, width, height, THREE.RGBAFormat, THREE.FloatType );
positionUniforms.tOffsets.value = offsetsTexture;
positionUniforms.tOffsets.needsUpdate = true;
}
function onDocumentClick() {
event.preventDefault();
stateChange = 1.0;
makeCloud();
updateOffsets();
}
function animate() {
requestAnimationFrame( animate );
update();
render();
}
function render() {
renderer.render( scene, camera );
}
function update() {
positionUniforms.uTime.value += 0.01;
gpuCompute.compute();
particleUniforms.tPositions.value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
if ( stateChange === 1.0 ) {
stateChange = 0.0;
console.log("swapped state!");
updateStateChange();
updateOffsets();
}
}
A snippet from the shader code:
vec4 offsets = texture2D( tOffsets, uv ).xyzw;
float swapState = offsets.z;
vec4 nowPos;
vec2 velocity;
if ( swapState == 0.0 ) {
nowPos = texture2D( tPositions, uv ).xyzw;
velocity = vec2(nowPos.z, nowPos.w);
} else { // if swapState == 1.0
nowPos = vec4( offsets.x, offsets.y, 0.0, 0.0 );
velocity = vec2(0.0, 0.0);
}
Background:
Instead of updating all clouds with each click, I aim to selectively alter specific clouds by passing in offset values via a texture. This prevents disrupting the physics controlled by the shader in other unselected clouds within my larger program.