Three.js: scaling and offset image textures

Created on 1 May 2012  ·  10Comments  ·  Source: mrdoob/three.js

I have one large image that I am loading as a texture. I then have several cubes that I am trying to apply this texture to. The problem is that when the texture is applied, it scales the image to the width and height of the cube. What i want to do is to ensure that no scaling happens, then I can move the "offset" of the texture to pick the portion I want to show.

Can anyone point me in the right direction?

For example , if my texture is 800x2000. And I have a 100x100 cube, I want to show a 100x100 portion of that big texture, offset at like 300x400. So something like:

tex = THREE.ImageUtils.loadTexture('texture.png');
tex.left = 300
tex.top = 400

var pictureMaterial = new THREE.MeshBasicMaterial({map: tex});

Do I need to leverage canvas textures for this?

Question

Most helpful comment

Ah, true. Texture doesn't have .scale, it has .repeat. Try this:

tex.repeat.x = 100 / 800;
tex.repeat.y = 100 / 2000;
tex.offset.x = ( 300 / 100 ) * tex.repeat.x;
tex.offset.y = ( 400 / 100 ) * tex.repeat.y;

All 10 comments

Ok I am getting there, but I need to find documentation for how to use the offset and repeat parameters. They seem to need to be between 0 and 1, and not sure how to get a value that converts to pixels.

tex = THREE.ImageUtils.loadTexture('texture.png');

tex.offset.x = ?
tex.offset.y = ?
tex.repeat.x = ?
tex.repeat.y = ?

Posting my solution in case it is helpful to anyone else. I ended up using canvas for the texture and loading/cropping the image on there instead. Seems to work fine so far.


canvas = document.createElement('canvas');
canvas.height=200;
canvas.width=200;

ctx = canvas.getContext('2d');
ctx.fillStyle = '#FFFFFF';  
ctx.fillRect(0, 0, 200, val.200);

//this is where we set the "offset"
offx = -1 * 200;
offy = -1 * 200;

//img is a standard loaded image object
ctx.drawImage(img,offx,offy);

tex = new THREE.Texture(canvas);

That's a way of doing it, but if you want to use the GPU you can do this:

tex.scale.x = 800 / 100;
tex.scale.y = 2000 / 100;
tex.offset.x = ( 300 / 100 ) * tex.scale.x;
tex.offset.y = ( 400 / 100 ) * tex.scale.y;

Or something along the lines :)

Cool! Thanks for the follow up

Doing this on the gpu is certainly more performant. However when i try to set the scale.x property of the texture I keep getting "cannot set property of x" errors. Any ideas? I tried it using the tex.scale.set(w,h) method as well with the same result.

tex = THREE.ImageUtils.loadTexture(img.src);

scalex = img.width / 100;
scaley = img.height / 100;

tex.scale.x = scalex;
tex.scale.y = scaley;
tex = THREE.ImageUtils.loadTexture(img.src);

That's weird, if the image already has a src, means that it has already been loaded. Why load it again?

I think you want to do this instead:

tex = new THREE.Texture( img );

Thanks, yes just using THREE.Texture() directly on the img object seems to have sped things up. Still getting an error on tex.scale operations though. Anyway to translate scaling using tex.repeat? I can tweak those values no problem.

Ah, true. Texture doesn't have .scale, it has .repeat. Try this:

tex.repeat.x = 100 / 800;
tex.repeat.y = 100 / 2000;
tex.offset.x = ( 300 / 100 ) * tex.repeat.x;
tex.offset.y = ( 400 / 100 ) * tex.repeat.y;

I came here to figure out how to scale a texture only to learn about the repeat and offset properties.. but how can I scale them?

@nightlifelover As stated in the guidelines, help requests should be directed to stackoverflow.

Was this page helpful?
0 / 5 - 0 ratings