My question is how can I bind texture to a particle in
use of THREE.ParticleCanvasMaterial ?
I mean what is the syntax to bind texture to particle?
You should try to use a ParticleBasicMaterial and pass in your Texture as the map property of the material:
var material = new THREE.ParticleBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'yourTexture.png' ) } );
Also, have a look at the canvas_particle_sprites example. Notice that it's generating a texture on the fly, but you can load your own texture as described above. From experience, the CanvasRenderer is slow with many/large textures.
Update 2019: ParticleBasicMaterial is deprecated
ParticleBasicMaterial has been renamed to PointsMaterial.
https://threejs.org/docs/#api/en/deprecated/DeprecatedList
You need to use PointsMaterial instead of ParticleBasicMaterial
var snowMaterial = new THREE.PointsMaterial({
size: 7,
blending: THREE.AdditiveBlending,
map: new THREE.TextureLoader().load("./assets/snowflake.png"),
//createCircleTexture("#ffffff", 20),
transparent: true,
depthWrite: false
});
Alternatively you can use canvas to draw Circular shapes for particle texture as suggest by George:
export const createCircleTexture = (color, size) => {
var matCanvas = document.createElement("canvas");
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext("2d");
// create texture object from canvas.
var texture = new THREE.Texture(matCanvas);
// Draw a circle
var center = size / 2;
matContext.beginPath();
matContext.arc(center, center, size / 2, 0, 2 * Math.PI, false);
matContext.closePath();
matContext.fillStyle = color;
matContext.fill();
// need to set needsUpdate
texture.needsUpdate = true;
// return a texture made from the canvas
return texture;
};
Test Image
Result
Related
I made mesh with PlanGeometry and BasicMaterial.
function createMesh(width, height) {
let geometry = new THREE.PlaneGeometry(width, height);
let mat = new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: true,
side: THREE.DoubleSide,
opacity: 0.5
});
return new THREE.Mesh(geometry, mat);
}
And I used this mesh in other place and make transformed this mesh.
So
mesh.matrix.identify();
mesh.applyMatrix(matrix); // make some transform.
Now, I want to get size of plane geometry
So I tried with following method.
let boundingBox = new THREE.Box3().setFromObject(mesh);
let size = new THREE.Vector3(0,0,0);
size = boundingBox.getSize(size);
console.log('size', size);
But size is not correct.
How can I get width, height value when created PlaneGeometry (width, height) before?
let geometry = new THREE.PlaneGeometry(width, height);
I want to know width, height value upper code.
Please anyone help.
You will probably have better results by checking the bounding box, geometry.parameters is not a reliable object - it's only created for primitives, and is not updated when the object is manipulated, so it won't reflect any scale changes.
mesh.geometry.computeBoundingBox()
const size = mesh.geometry.boundingBox.getSize()
console.log('size', size);
I found a answer.
let parameters = mesh.geometry.parameters;
let size = {
width: parameters.width,
height: parameters.height
};
console.log('size', size);
Thanks #prisoner849.
Applying a texture to a cylinder geometry in THREE JS causes some weird distortion of the texture as can be seen in this image:
The shape is created like so:
var cylinderGeo = new THREE.CylinderGeometry(0.1, 1, 1, 4, 1, false, Math.PI / 4);
cylinderGeo.computeFlatVertexNormals();
var mesh = new THREE.Mesh(cylinderGeo);
mesh.position.x = 10;
mesh.scale.set(10, 5, 10);
mesh.material = new THREE.MeshLambertMaterial();
// LOAD TEXTURE:
textureLoader.load("/textures/" + src + ".png", function (texture) {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(2,2);
texture.needsUpdate = true;
mesh.material.map = texture;
mesh.material.needsUpdate = true;
});
The texture seems to be applied per polygon and not per face? How can i make it wrap around the cylinder without any such artifacts?
EDIT: The texture is 256x256
Each side of your pyramid is composed of two triangles. You can see this quite clearly in the example on the CylinderGeometry documentation page.
Each triangle has UVs which are created based on the assumption that both triangles will be the same scale, like they are in the example. By making one end of your cylinder smaller, you're changing the scale of the triangles, but your UVs are remaining the same.
You can either edit the UVs to make up for the difference, or (and I recommend) create your own geometry with proper UVs defined.
I am using threejs and trying to create a star system by using the following code:
// create the particle variables
//var particleCount = 180000,
var particles = new THREE.Geometry();
var multiplyingFactor = 50;
// now create the individual particles
for (var p = 0; p < array.length; p++) {
//the star from the csv file
star = array[p];
// initialize the particle with the star's information.
particle = new THREE.Vector3(star.x * multiplyingFactor, star.y * multiplyingFactor, star.z * multiplyingFactor);
// add it to the geometry
particles.vertices.push(particle);
}
// var pMaterial = new THREE.PointsMaterial({
// color: 0xFFFFFF,
// size: 20,
// map: THREE.ImageUtils.loadTexture("http://localhost:8080/images/circle.png"),
// blending: THREE.AdditiveBlending,
// transparent: true
// });
// instantiate a loader
var loader = new THREE.TextureLoader();
//allow cross origin loading
loader.crossOrigin = '';
// load a resource
loader.load('http://localhost:8080/images/circle.png',
// Function when resource is loaded
function (texture) {
var pMaterial = new THREE.PointsMaterial({
color: 0xFFFFFF,
size: 20,
map: texture,
blending: THREE.AdditiveBlending,
transparent: true
});
// create the particle system
particleSystem = new THREE.Points(
particles,
pMaterial);
// also update the particle system to
// sort the particles |which enables
// the behaviour we want
particleSystem.sortParticles = true;
scene.add(particleSystem);
}
);
It works correctly, however the texture is loaded as a square even though the image I am using for it is a white circle (not visible here in stack overflow but you can click over it):
However, once it loads, every vector in the system has black edges visible when over imposed:
My question is:
How can I get rid of those black edges? is it possible?
You can use alphaTest to discard unwanted fragments like so:
var pMaterial = new THREE.PointsMaterial( {
color: 0xffffff,
size: 20,
map: texture,
alphaTest: 0.5,
transparent: false // only set to true if it is required for your texture
} );
Also, only set the material blending property if you specifically want to change it from the default.
three.js r.85
I'm a three.js beginner. Trying to apply an html canvas as texture to plane geometry. Works fine when there is no rotation. When rotated, a) outside edges of the mesh become jagged (edges/lines within the image are fine) and b) text becomes blurry.
What do I have to do to keep outside edges and text crisp?
My texture is power-of-two (128 x 512). Turning antialiasing on doesn't help.
Here is a screenshot without rotation
And here with rotation.
Code looks like this:
var eltTexture = toTexture2(d, this, go.w, go.Res.ow[0]);
// map texture to material
var material = new THREE.MeshBasicMaterial(
{ map : eltTexture } );
//define sub image of texture to be applied to mesh
var cutout = [
new THREE.Vector2(0, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, (128 - go.Res.ow[0])/128),
new THREE.Vector2(go.w/512, 1),
new THREE.Vector2(0, 1)];
// geometry and UV mapping
var geometry = new THREE.PlaneGeometry (go.w, go.Res.ow[0]);
geometry.faceVertexUvs[0] = []; // initialize
geometry.faceVertexUvs[0][0] =
[cutout[3], cutout[0], cutout[2]];
geometry.faceVertexUvs[0][1] =
[cutout[0], cutout[1], cutout[2]];
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(d.threeX, d.threeY, d.threeX);
mesh.rotation.set(0,0.6,0);
scene.add( mesh );
});
renderer.render( scene, camera );
function toTexture2 (d, svgNode, svgWidth, svgHeight){
// step 1: serialize eltSVG to xml
var eltXML = new XMLSerializer().serializeToString(svgNode);
eltXML = 'data:image/svg+xml;charset = utf8,' + eltXML;
// step 2: draw eltXML to image
var eltImage = document.body.appendChild(
document.createElement("img"));
eltImage.id = "eltImage";
eltImage.style.display = "none";
eltImage.width = svgWidth;
eltImage.height = svgHeight;
eltImage.src = eltXML;
// step 3: draw image to canvas
// NOTE: define canvas parameters position, width and
// height in html, NOT IN CSS, otherwise image
// will become blurry - don't ask why!
var eltCanvas = document.body.appendChild(
document.createElement("canvas"));
eltCanvas.id = "eltCanv";
eltCanvas.style.display = "none";
eltCanvas.width = 512;
eltCanvas.height = 128;
// get context
var ctx = eltCanvas.getContext("2d", {alpha: false});
// draw svg element to canvas, not including portrait image
ctx.drawImage(eltImage, parseInt(0), parseInt(0),
svgWidth, svgHeight);
// draw portrait image to canvas
var portrait = document.getElementById(d.nameConcat + "Img");
ctx.globalAlpha = 0.6; // opacity of portrait image
ctx.drawImage(portrait, go.Res.strw[0], go.Res.strw[0],
go.Res.iw[0], go.Res.iw[0]);
var texture = new THREE.Texture(eltCanvas);
texture.needsUpdate = true;
return texture;
} // function toTexture2
Many thanks in advance for your help!
Even though it's been a long time since you've posted this, I have the solution in case anyone else is experiencing the same issue.
Add this to your renderer:
const renderer = new THREE.WebGLRenderer({antialias: true});
var arcShape = new THREE.Shape();
arcShape.moveTo( 50, 10 );
arcShape.absarc( 10, 10, 40, 0, Math.PI*2, false );
var map1 = new THREE.ImageUtils.loadTexture( 'moon.jpg' );
var geometry = new THREE.ExtrudeGeometry( arcShape, extrudeSettings );
var new3D = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: map1 } ) );
new3D.receiveShadow = true;
obj3Dmassive.add( new3D );
Texture (512x512): http://f3.s.qip.ru/cMfvUhNj.png
Result: http://f3.s.qip.ru/cMfvUhNh.png
How to fill a texture figure?
If you just have a straight extrusion path, you can apply textures to extruded shapes without the need for a custom UV generator. e.g.
var extrudeSettings = {
bevelEnabled: false,
steps: 1,
amount: 20, //extrusion depth, don't define an extrudePath
material:0, //material index of the front and back face
extrudeMaterial : 1 //material index of the side faces
};
var geometry = shape.extrude(extrudeSettings);
var mesh = new THREE.Mesh(geometry,
new THREE.MeshFaceMaterial([materialFace, materialSide]));
This is handy for cookie-cutter type shapes.
EDIT: Answer outdated. See Extruding multiple polygons with multiple holes and texturing the combined shape instead.
You are lucky. What you are trying to do has been done in the following example:
https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_extrude_uvs2.html
You have to specify your own UV generator function. This example shows you how to do that.
Remember, this is just an example. It may not be correct -- or easy to implement in your case.