Three.js png texture - alpha renders as white instead as transparent - three.js
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?
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 );
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)
Related
texturing ExtrudeGeometry
I have a problem when I am drawing a canvas texture in THREE.ExtrudeGeometry. The following image is what I want But it seems to not work well. It appears a black scene. This is my project scene.The Texture is work fine to left PlaneGeometry, but no work well to right ExtrudeGeometry. var shape = new THREE.Shape(points); var extrudeSettings = { size: 1, amount: 8, bevelEnabled: false, material: 0, extrudeMaterial: 1 }; var geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); var canvas = document.querySelector('.heatmap-canvas'); var texture = new THREE.Texture(canvas); texture.needsUpdate = true; texture.minFilter = THREE.LinearFilter; var material = new THREE.MeshLambertMaterial({ map: texture, color: 0xffffff, transparent: true, opacity: 0.7 }); var mesh = new THREE.Mesh(geometry, material);
ThreeJS: Some material texture faces / triangles not rendering
I have a .obj and .mtl which load textures from .tga files. This all seems to work / look fine in 3D modeling software, but when loaded with three.js (THREE.WebGLRenderer({ antialias: true })) some of the object's children, (specifically between the knees and the calves, but not, for example, the pockets and legs), seem to have a transparent jagged gap / empty triangles. (Tried turning on antialiasing, changing the overdraw value, turning off transparency, etc.) Loader function: threejsHelper.helpers.loadObject('objects/pants/MaleBaggyPants.obj', 'objects/pants/MaleBaggyPants.mtl', { blinn1SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/button.tga') })), blinn2SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })), blinn4SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') })), blinn5SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/pocket.tga') })), blinn6SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })), blinn7SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') })) }, function (object) { object.rotation.x = (-90*Math.PI/180); object.rotation.z = (-90*Math.PI/180); app.scene.add(object); app.ready = true; }); Helper functions: ... loadTexture: function (manager, path) { var texture; if (path.split('.').pop() == 'tga') { var loader = new THREE.TGALoader(); texture = loader.load(path); } else { texture = new THREE.Texture(); var loader = new THREE.ImageLoader(manager); loader.load(path, function (image) { texture.image = image; texture.needsUpdate = true; }); } return texture; }, loadMaterial: function (mtlPath, textures, complete) { var loader = new THREE.MTLLoader(); loader.load(mtlPath, function (materials) { materials.preload(); if (!!materials.materials) { for (var key in materials.materials) { if (key in textures) { materials.materials[key] = textures[key]; } } } complete(materials); }); }, loadObject: function (objPath, mtlPath, textures, complete) { app.helpers.loadMaterial(mtlPath, textures, function (materials) { var loader = new THREE.OBJLoader(); loader.setMaterials(materials); loader.load(objPath, function (object) { complete(object); }); }); }, ...
You seem to have extra vertices along the seem on both the objects which I think will screw with the triangulation. Remove these vertices that are not needed and I'm 99% sure it will fix your problem. I also noticed the model is at a very small scale.
I had the same problem. Some triangle didn't properly render on Threejs while it properly rendered on my OpenGL app. I solved this trouble by using Uint32Array instead of Uint16Array to define the index of the geometry. I just put this line of code and everything worked like a charm. const indices = new Uint32Array(faceDict.index);
STL file read using three.js issue
I am able to read successfully stl file by three.js but problem is that is not showing exact color which is defined in the stl file. My code looks like: var loader = new THREE.STLLoader(); loader.addEventListener( 'load', function ( event ) { var geometry = event.content; var material = new THREE.MeshPhongMaterial( { ambient: 0x555555, color: 0xAAAAAA, specular: 0x111111, shininess: 200 } ); if (geometry.hasColors) { material = new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0x111111, ambient: 0x555555, opacity: geometry.alpha, vertexColors: THREE.VertexColors }); } var mesh = new THREE.Mesh( geometry, material ); mesh.position.x = x - w/2; mesh.position.y = y; mesh.position.z = - h + h/2 + z/2; //mesh.rotation.set( 0.5, 0, 0 ); mesh.castShadow = true; mesh.receiveShadow = true; board.add(mesh); } ); loader.load( fileName ); But its showing only black color after applying vertex color. Any suggestion?
How to set transparency to single face of the custom geometry using Three.js?
I've the custom geometry with sqaure-base and it looks like a cone. here is jsfiddle link: http://jsfiddle.net/suvKg/18/ I've obtained transparency to the whole object at here: var meshMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, opacity: 0.6, depthWrite: false, depthTest: false, vertexColors: THREE.VertexColors } ); But I don't want transparency to be applied to base of the cone, but only side faces should have it. How to do that?
you need to use THREE.MeshFaceMaterial() for your entire mesh. For example if your geometry have X faces and 2 differents materials : var materials = [ new THREE.MeshLambertMaterial( { color: 0xffffff, opacity: 0.6, depthWrite: false, depthTest: false, vertexColors: THREE.VertexColors } ), new THREE.MeshLambertMaterial( { color: 0xffffff, opacity: 1, depthWrite: false, depthTest: false, vertexColors: THREE.VertexColors } ) ]; // the two materials var mesh = new THREE.Mesh(yourGeometry, new THREE.MeshFaceMaterial(materials)); //tell three.js that you will have several materials in your geometry Then, you will need to determine materialIndex manualy in each of your faces based on the materials indexes yourGeometry.faces[0].materialIndex = 0; yourGeometry.faces[1].materialIndex = 0; yourGeometry.faces[2].materialIndex = 1; // <= the cone base ... yourGeometry.faces[lastFaceIndex].materialIndex = 0; NB: default parameter for materialIndex is 0 so you will need to determine only one face to its material index in your case
Using imageData for texture in ThreeJS
I try to load a imageData to create texture in threeJS. I try like this, but it does not work. pMaterial = new THREE.ParticleBasicMaterial({ color: 0xFFFFFF, size: 20, map: THREE.DataTexture( myimageData ), blending: THREE.AdditiveBlending, transparent: true }); Thanks for your help.
It works with the following code. var texture = new THREE.Texture(myImageData); texture.needsUpdate = true; particles = new THREE.Geometry(), pMaterial = new THREE.ParticleBasicMaterial({ size: 20, map: texture, blending: THREE.AdditiveBlending, transparent: true });