更新数据纹理统一时,所有点都变为 0,0
All points go to 0,0 when updating a data texture uniform
当用户点击时,我正在交换新的位置数据以塑造点云(在高云和宽云之间交替)。我做了这个 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);
}
背景:
我意识到只需单击一下即可交换所有数据并获得我正在寻找的结果,这将非常容易;然而,我试图通过在纹理中传递这些偏移值来更新的原因是在我的较大程序中有更多的点云,我只想更改选定的云(如 swapState
中所示着色器),同时让物理着色器继续控制其余未选中的着色器。更新所有的云会扰乱由着色器控制的物理的连续性。
我在我的代码中发现了错误——错误在于我为 DataTexture
设置 needsUpdate
属性的方式。见固定fiddlehere。这是使它最终按预期工作的修订:
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
}
当用户点击时,我正在交换新的位置数据以塑造点云(在高云和宽云之间交替)。我做了这个 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);
}
背景:
我意识到只需单击一下即可交换所有数据并获得我正在寻找的结果,这将非常容易;然而,我试图通过在纹理中传递这些偏移值来更新的原因是在我的较大程序中有更多的点云,我只想更改选定的云(如 swapState
中所示着色器),同时让物理着色器继续控制其余未选中的着色器。更新所有的云会扰乱由着色器控制的物理的连续性。
我在我的代码中发现了错误——错误在于我为 DataTexture
设置 needsUpdate
属性的方式。见固定fiddlehere。这是使它最终按预期工作的修订:
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
}