1

I have a javascript piece which loads an image:

var loader = new THREE.TextureLoader();
loader.load( 'textures/canvas1.png', function ( texture ) {
    var geometry = new THREE.SphereGeometry( 200, 20, 20 );
    var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
    var mesh = new THREE.Mesh( geometry, material );
    group.add( mesh );
} );

and works fine. Now, however, I do not want to load an image but a dynamically created image map, created as follows:

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var image = context.createImageData(map_width, map_height);
var data = image.data;               
var scale = 5.18;
for (var x = 0; x < map_width; x++) {                  
    for (var y = 0; y < map_height; y++) {
        var nx = x/map_width-0.5;
        var ny = y/map_height-0.5;                    
        var value = Math.abs(noise.perlin2(scale*nx, scale * ny));
        value *= 256;

        var cell = (x + y * map_width) * 4;                    
        data[cell] = data[cell + 1] = data[cell + 2] = Math.pow(1.2, value);                              
        data[cell + 3] = 255; // alpha.                                    
    }
}

I tried the following piece of code (including to create a Uint8Array as suggested in the comments), but all I get is a complete black sphere:

var buffer = new ArrayBuffer(data.length);
var udata = new Uint8Array(buffer);
for (var i=0; i<data.length; i++) {
    udata[i] = data[i];     
}

var geometry = new THREE.SphereGeometry( 200, 20, 20 );
var texture = new THREE.DataTexture(udata, map_width, map_height, THREE.RGBAFormat );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );

Maybe the data must be given in a different format?

Alex
  • 41,580
  • 88
  • 260
  • 469
  • [This guy](http://stackoverflow.com/questions/16370617/is-it-possible-to-use-a-2d-canvas-as-a-texture-for-a-cube) seems to managed to do what you're trying to do. – tforgione Nov 05 '15 at 16:04
  • According to [this answer](http://stackoverflow.com/questions/12586353/three-js-texture-to-datatexture), you need to pass an Uint8Array, not an ImageData object. – Kaiido Nov 05 '15 at 17:54
  • I create an `Uint8Array` and filled it with my data, and still get a black sphere. – Alex Nov 09 '15 at 12:10
  • I updated my question with the new array. – Alex Nov 09 '15 at 13:46
  • 1
    @Alex (1) Add `texture.needsUpdate = true;` (2) Why are you setting `overdraw`? – WestLangley Nov 09 '15 at 15:56
  • No idea what `overdraw` means. I will experiment with it tomorrow... – Alex Nov 09 '15 at 18:36
  • That finally works! But what does `overdraw` mean. There does not seem something in the documentation: http://threejs.org/docs/#Reference/Materials/MeshBasicMaterial – Alex Nov 10 '15 at 07:15
  • `overdraw` is used by `CanvasRenderer` only. See http://threejs.org/docs/#Reference/Materials/Material – WestLangley Nov 14 '15 at 05:09

1 Answers1

2

Here is the pattern to follow to create a DataTexture and use it as the map for your material:

var data = new Uint8Array( 4 * size );

// initialize data. . .

var texture = new THREE.DataTexture( data, width, height, THREE.RGBAFormat );

texture.type = THREE.UnsignedByteType;

var material = new THREE.MeshBasicMaterial( { map: texture } );

var mesh = new THREE.Mesh( geometry, material );

scene.add( mesh );

three.js r.128

WestLangley
  • 102,557
  • 10
  • 276
  • 276