3

UPDATE: Issue was that texData object was recreated each time and thus reference for DataTexture was lost. Solution by WestLangley was to overwrite the data in texData instead of recreating texData object.

I have a simple threejs scene with a DataTexture in a ShaderMaterial. The data array passed to it once during initialization is updated on mouse events. However the DataTexture does not seem to update.

Did i assign uniforms or texture data wrongly? Or using the needsUpdate flags wrongly? It does work when deleting and recreating the texture, material, mesh and scene objects each time, but this shouldnt really be necessary as i have seen from many examples which i could however not reproduce.

Note that the data itself is updated nicely, just not the DataTexture.

// mouse event triggers request to server
// server then replies and this code here is called
// NOTE: this code **is** indeed called on every mouse update!

// this is the updated data from the msg received
// NOTE: texData **does** contain the correct updated data on each event
texData = new Float32Array(evt.data.slice(0, msgByteLength));

// init should happen only once
if (!drawContextInitialized) {

    // init data texture
    dataTexture = new THREE.DataTexture(texData, texWidth, texHeight, THREE.LuminanceFormat, THREE.FloatType);
    dataTexture.needsUpdate = true;

    // shader material
    material = new THREE.ShaderMaterial({
        vertexShader: document.querySelector('#vertexShader').textContent.trim(),
        fragmentShader: document.querySelector('#fragmentShader').textContent.trim(),
        uniforms: {
            dataTexture: { value: dataTexture }
        }
    });

    // mesh with quad geometry and material
    geometry = new THREE.PlaneGeometry(width, height, 1, 1);
    mesh = new THREE.Mesh(geometry, material);

    // scene
    scene = new THREE.Scene();
    scene.add(mesh);

    // camera + renderer setup
    // [...]

    drawContextInitialized = true;

}

// these lines seem to have no effect
dataTexture.needsUpdate = true;    
material.needsUpdate = true;
mesh.needsUpdate = true;
scene.needsUpdate = true;

renderer.render(scene, camera);
Nikole
  • 322
  • 3
  • 17
  • Are you setting `dataTexture.needsUpdate = true;` whenever you update the data? – WestLangley Jan 15 '17 at 00:38
  • yes, see at the very bottom of the code (scroll down all the way). this is in the same function as the `texData` assignment – Nikole Jan 15 '17 at 00:39
  • Show where you are updating the data on mouse events. – WestLangley Jan 15 '17 at 00:50
  • the data update is working well, i see the updated texture when i recreate all the texture and material objects in each call of the above. on mousemove a request to the server is sent and this above is the callback on received response message. – Nikole Jan 15 '17 at 01:02
  • With out-of-context code fragments, I can 't help you. Perhaps someone else can. – WestLangley Jan 15 '17 at 01:10
  • there is not much other code, the relevant code is the above, everything outside that works. but thank you :) – Nikole Jan 15 '17 at 01:13
  • You say you it is updated with mouse events, but have no code to do so? Even in the comments in your code it says "init should happen only once", so how do you expect it to update with mouse events? – 2pha Jan 15 '17 at 06:02
  • i can include the code, but it would just make things more confusing. the thing is: the data *is* updated, i can guarantee that. and the code above *is* being called on the mouse events. the "init should happen only once" stuff is simply only executed on the first such event. – Nikole Jan 15 '17 at 11:56
  • 1
    @Mangostaniko When updating `texData`, do not instantiate a new array, use `texData.set( javascript_array )` instead. Remove all `needsUpdate` flags except `dataTexture.needsUpdate = true; `. – WestLangley Jan 15 '17 at 22:05
  • @WestLangley makes sense..! that solved it!! thanks so much for your research!! :) would you like to write an answer or should i? – Nikole Jan 16 '17 at 00:41

2 Answers2

4

When updating the DataTexture data, do not instantiate a new array. Instead, update the array elements like so:

texData.set( javascript_array );

Also, the only flag you need to set when you update the texture data is:

dataTexture.needsUpdate = true;

three.js r.83

WestLangley
  • 102,557
  • 10
  • 276
  • 276
-1

I had a real hard time for some reason seeing any change to modifactions . In desperation i just made a new DataTexture . Its important to set needsUpdate to true

imgData.set(updatedData)
var newDataTex = new THREE.DataTexture( imgData,...     
var newDataTex.needsUpdate = true

renderMesh.material.uniforms.texture.value = newDataTex
yeahdixon
  • 6,647
  • 1
  • 41
  • 43