Im working with Three.js particles , and trying to map multiple png textures, (my png images are juste différent colors stars to create a sky full of stars)
my code looks like this :
const loader = new THREE.TextureLoader();
const cross = loader.load ('./cross1.png');
const cross2 = loader.load ('./cross3.png');
.
.
.
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross,
transparent: true
})
// Mesh
const sphere = new THREE.Points(geometry,material)
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial)
scene.add(sphere, particlesMesh)
it works fine with only maping one elmement "cross" .
my question is, how can i MAP multiple images to get like a random mix please ?
something like :
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross, cross2, cross3
transparent: true
})
THANKS !
If you are looking to make stars with multiple colors I would just create 3 instances of points mesh with each one containing their respective textures.
const particlesMaterial = new THREE.PointsMaterial({
size: 0.02,
map: cross,
transparent: true
})
const particlesMaterial2 = new THREE.PointsMaterial({
size: 0.02,
map: cross2,
transparent: true
})
const particlesMaterial3 = new THREE.PointsMaterial({
size: 0.02,
map: cross3,
transparent: true
})
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial)
const particlesMesh2 = new THREE.Points(particlesGeometry, particlesMaterial2)
const particlesMesh3 = new THREE.Points(particlesGeometry, particlesMaterial3)
scene.add(particlesMesh, particlesMesh2, particlesMesh3)
this works as long as your point coordinates are randomized
Related
I created a 3D Earth using three.js that rotates, but the problem is that it starts spinning over the ocean.
i triedto change starting position using matrixWorld but didn't change anything
can someone help plz
here is my js:
...
const earthgeometry = new THREE.SphereGeometry(0.344,64,32);
const eatrhmaterial = new THREE.MeshPhongMaterial({
roughness: 1,
metalness:0,
map: THREE.ImageUtils.loadTexture('static/img/earthmap1k.jpg'),
bumpMap: THREE.ImageUtils.loadTexture('static/img/earthbump.jpg'),
bumpScale: 0.3,
});
const earthmesh = new THREE.Mesh(earthgeometry,eatrhmaterial);
earthmesh.position.set (0.49,0.035,0.58);
earthmesh.matrixWorld.setPosition(new THREE.Vector3(100, 100, 100));
...
The same way you set a position, you can set a rotation of your object.
const earthgeometry = new THREE.SphereGeometry(0.344,64,32);
const earthmaterial = new THREE.MeshPhongMaterial({
//material definition here
});
const earthmesh = new THREE.Mesh(earthgeometry,earthmaterial);
earthmesh.position.set (0.49,0.035,0.58);
earthmesh.rotation.set (0,1.1,0);//or any other values
remember :
rotation are in radians: 360° = 2*Math.PI
Y axis is the vertical one
I have a BufferGeometry object and I want to be able to assign a different texture to each face.
In my example here: https://jsfiddle.net/2ay716mz/ (working example)
I have setup a cube (using custom BufferGeometry not BoxGeometry seeing as I need other objects that are not cubes).
I have passed an array of materials to the mesh, one side is a texture and the other sides are all different colors.
This all works correctly...however if I try to put the texture material on any face group , other than the group[0] and group[1], then it doesn't work and just shows a color instead.
See in this example where I have set the texture to be the third material; it no longer works: https://jsfiddle.net/2ay716mz/1/
How can I solve this? Or is this a bug and should be reported to three.js github?
It works fine on my end. You just have to assign a new material to each texture you want to use:
const texLoader = new THREE.TextureLoader();
const texURL1 = 'https://upload.wikimedia.org/wikipedia/commons/9/93/Gfp-jagged-rock-texture.jpg';
const texURL2 = 'https://threejs.org/examples/textures/patterns/circuit_pattern.png';
const texURL3 = 'https://threejs.org/examples/textures/decal/decal-normal.jpg';
const texURL4 = 'https://threejs.org/examples/models/gltf/LeePerrySmith/Map-COL.jpg';
const texURL5 = 'https://threejs.org/examples/models/gltf/LeePerrySmith/Map-SPEC.jpg';
const texURL6 = 'https://threejs.org/examples/textures/cube/pisa/px.png';
const mat1 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL1)});
const mat2 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL2)});
const mat3 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL3)});
const mat4 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL4)});
const mat5 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL5)});
const mat6 = new THREE.MeshBasicMaterial({color: 0xffffff, map: texLoader.load(texURL6)});
var material = [
mat1,
mat2,
mat3,
mat4,
mat5,
mat6,
];
Click here for live demo
I'm using THREE.WebGLRenderer and I would like to draw a few same-sized white dots at specific positions in 3D space.
Should I use sprites, calculate the 2D screen coordinates and use SpriteMaterial.useScreenCoordinate?
Should I simply recalculate the size of the sprites using the distance of them to the camera?
Can I use SpriteMaterial.scaleByViewport or SpriteMaterial.sizeAttenuation? Is there any documentation for this?
Is there something like GL_POINTS? It would be nice to just define 1 vertex and get a colored pixel at that position. Should I experiment with PointCloud?
Thanks for any hints!
Edit: All points should have the same size on the screen.
Using .sizeAttenuation and a single-vertex PointCloud works, but it feels a bit… overengineered:
var dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push(new THREE.Vector3( 0, 0, 0));
var dotMaterial = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } );
var dot = new THREE.Points( dotGeometry, dotMaterial );
scene.add( dot );
For r125
The excerpt is taken from threejs official example. After some modification here how made it to work.
var dotGeometry = new BufferGeometry();
dotGeometry.setAttribute( 'position', new Float32BufferAttribute( [0,0,0], 3 ) );
var dotMaterial = new PointsMaterial( { size: 0.1, color: 0x00ff00 } );
var dot = new Points( dotGeometry, dotMaterial );
scene.add( dot );
Yet another update: The interface for attribute has changed somewhat:
For r139
const dotGeometry = new THREE.BufferGeometry();
dotGeometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([0,0,0]), 3));
const dotMaterial = new THREE.PointsMaterial({ size: 0.1, color: 0xff0000 });
const dot = new THREE.Points(dotGeometry, dotMaterial);
scene.add(dot);
I am trying to use two or more point clouds, but it just does not work - there are colr/transparency artifacts. How to fix, please?
My code so far looks like this:
var geometry = new THREE.Geometry ();
...
var material = new THREE.PointCloudMaterial ({
var material = new THREE.PointCloudMaterial ({
size: 60,
//size: 20, sizeAttenuation: false,
map: texture,
vertexColors: THREE.VertexColors, transparent: true
});
var particles = new THREE.PointCloud (geometry, material);
particles.sortParticles = true;
Try it live at jsbin
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)