更新数据纹理均匀时,所有点都转到0,0

时间:2017-01-06 21:18:49

标签: javascript three.js textures shader

当用户点击时,我会更换新的位置数据以形成点云(在高云和宽云之间交替)。我已经制作了这个fiddle,到目前为止我可以让第一次正确渲染云(高云),但是在点击事件中,所有点位置看起来都变为0,0而不是成为一片广阔的云。我在这里错过了什么?

以下是一些需要检查的片段:

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

着色器代码中的代码段

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

背景

我意识到只需点击一下点击所有数据并获得我正在寻找的结果就足够了;但是,我通过在纹理中传递这些偏移值来尝试更新的原因是,在我的大型程序中,还有更多的点云,我只想改变选定的云(如{{1}所示)在着色器中),同时让物理着色器继续控制剩余的未选择的。更新所有云会混淆着色器控制的物理连续性。

1 个答案:

答案 0 :(得分:1)

我在代码中发现了错误 - 缺陷在于我如何为needsUpdate设置DataTexture属性。查看固定小提琴here。这是使其最终按预期工作的修订版:

function updateOffsets() {
    offsetsTexture = new THREE.DataTexture( cloudData.offsets, width, height, THREE.RGBAFormat, THREE.FloatType );
    offsetsTexture.needsUpdate = true; // **using this way of updating the texture produced the behavior I expected
    positionUniforms.tOffsets.value = offsetsTexture;
    // positionUniforms.tOffsets.needsUpdate = true; **this form of updating caused the faulty behavior
}