38

I'm creating a cube and I apply 6 different textures to each of it's faces. Each texture is a .png file and contains transparent parts. I'm also applying a color to the cube - I want to see that color trough png transparency.

Problem: Transparency renders as white color so I cannot see the base color of the cube (which renders ok if I remove the png texture)

How can I make the png transparency work? I tried playing with some material settings but none make it transparent.

Code for creating the cube and materials:

var geometry = new THREE.CubeGeometry(150, 200, 150, 2, 2, 2);
var materials = [];

// create textures array for all cube sides
for (var i = 1; i < 7; i++) {
   var img = new Image();
   img.src = 'img/s' + i + '.png';
   var tex = new THREE.Texture(img);
   img.tex = tex;

   img.onload = function () {
      this.tex.needsUpdate = true;
   };

   var mat = new THREE.MeshBasicMaterial({color: 0x00ff00, map: tex, transparent: true, overdraw: true });
   materials.push(mat);
}
cube = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
cube.position.y = 150;
scene.add(cube);

EDIT:

Picture below shows the problem - with senthanal solution the left texture now renders ok - it is a png image without transparency - I set the transparency in code with

materialArray.push(new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture('img/s2.png'), transparent: true, opacity: 0.9, color: 0xFF0000 }));

The right texture is also a png image - only that it has a transparent area (all that renders white should be pure red since it is transparent and should take the color from the cube?). How can I make that white part transparent?

enter image description here

easwee
  • 15,757
  • 24
  • 60
  • 83
  • 1
    Duplicate of http://stackoverflow.com/questions/12368200/displaying-background-colour-through-transparent-png-on-material (if you want the background color to be opaque) – WestLangley Jul 05 '13 at 16:57
  • @WestLangley - yeah - dunno how I missed that question since I've been reading answers about three.js whole day. Fixes my problem - closing as duplicate. – easwee Jul 12 '13 at 14:38

2 Answers2

42

the opacity attribute of material does the trick for you. Follows, example code snippet:

var materialArray = [];

materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/xpos.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/xneg.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/ypos.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/yneg.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/zpos.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));
materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/zneg.png' ), transparent: true, opacity: 0.5, color: 0xFF0000 }));

var MovingCubeMat = new THREE.MeshFaceMaterial(materialArray);
var MovingCubeGeom = new THREE.CubeGeometry( 50, 50, 50, 1, 1, 1, materialArray );

MovingCube = new THREE.Mesh( MovingCubeGeom, MovingCubeMat );
MovingCube.position.set(0, 25.1, 0);

scene.add( MovingCube );    

http://threejs.org/docs/#Reference/Materials/Material The key is to set transparent attribute true and set opacity to 0.5(for example). Add the second the cube which fits inside exactly with no transparency, idea from @WestLangley ( Three.js canvas render and transparency )

backCube = new THREE.Mesh( MovingCubeGeom, new THREE.MeshBasicMaterial( { color: 0xFF0000 }) );
backCube.position.set(0, 25.1, 0);
backCube.scale.set( 0.99, 0.99, 0.99 );
scene.add( backCube );
andreas.herz
  • 85
  • 1
  • 1
  • 10
senthanal
  • 548
  • 5
  • 9
  • This works, but only if I use the WebGLRenderer - how could I make it work with a CanvasRenderer? I need to support IE9 and tablets. Basically all I want to do is apply a png image to the cube and see the cube color trough the transparent parts of the png? I uploaded an image of what I have now with your solution implemented. – easwee Jul 05 '13 at 15:09
  • 5
    note that you don't actually need to set `opacity` to anything; you just need `transparent` to be true – Eevee Dec 21 '16 at 02:00
  • no matter what I do my alpha maps never work :( really getting on my nerves. – Tyguy7 May 31 '17 at 18:59
6

for those looking for a simple transparent png import helper:

import { MeshBasicMaterial, TextureLoader } from 'three'

export const importTexture = async(url, material) => {
    const loader = new TextureLoader()
    const texture = await loader.loadAsync(url)
    material.map = texture
    material.transparent = true
    material.needsUpdate = true
    return texture
}


//usage
const geo = new PlaneGeometry(1, 1)
const mat = new MeshBasicMaterial()
const mesh = new Mesh(geo, mat)
scene.add(mesh)
//this is asynchronous
importTexture('path/to/texture.png', mat)
chantey
  • 4,252
  • 1
  • 35
  • 40