Reputation: 670
I am currently experimenting with three.js. I would like to change the code in the example below so the dots are round, not square.
I found another example called canvas particle random, which has round particles, and basically, the only difference in the script is the following:
var PI2 = Math.PI * 2;
var program = function ( context ) {
context.beginPath();
context.arc( 0, 0, 0.5, 0, PI2, true );
context.fill();
};
I thought that if I add this to the other script, then the particles would become round. However, when I added the above script to the first script, it doesn't work (I just get a blue screen).
Anyone know what I am doing wrong?
Upvotes: 5
Views: 6818
Reputation: 154
Even though this question has been asked more than 2 years ago, I thought it would be useful to add that you could always write your own fragment shader using a three.js ShaderMaterial:
let geom = new three.Geometry();
geom.vertices.push(new three.Vector3(0,0,0));
let material = new three.ShaderMaterial({
transparent: true,
uniforms: {
size: {value: 10},
scale: {value: 1},
color: {value: new three.Color('maroon')}
},
vertexShader: three.ShaderLib.points.vertexShader,
fragmentShader: `
uniform vec3 color;
void main() {
vec2 xy = gl_PointCoord.xy - vec2(0.5);
float ll = length(xy);
gl_FragColor = vec4(color, step(ll, 0.5));
}
`
});
let points = new three.Points(geom, material);
Upvotes: 11
Reputation: 10155
As others have said, you can use a texture as the map in your PointsMaterial.
But if you just want circles, an easier method may be to create the map dynamically with a canvas (which is what the code you posted seems to be trying to do).
HERE is a fiddle with your code updated to use a canvas as your texture map.
NOTE: I have changed the colors in your paramters object to make it more obvious that different colors are being used.
The function that creates a circle on a canvas for use as a map.
function createCanvasMaterial(color, size) {
var matCanvas = document.createElement('canvas');
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext('2d');
// create exture 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;
}
map canvas creation in the loop using the parameters object.
for (i = 0; i < parameters.length; i++) {
color = parameters[i][0];
size = parameters[i][1];
var hexColor = new THREE.Color(color[0], color[1], color[2]).getHexString();
materials[i] = new THREE.PointsMaterial({
size: 20,
map: createCanvasMaterial('#'+hexColor, 256),
transparent: true,
depthWrite: false
});
particles = new THREE.Points(geometry, materials[i]);
particles.rotation.x = Math.random() * 6;
particles.rotation.y = Math.random() * 6;
particles.rotation.z = Math.random() * 6;
scene.add(particles);
}
Have to set depthWrite to false on the marterial. see THIS issue.
I have now created a blog post on Three.js canvas particles
Upvotes: 7
Reputation: 17586
You can use a texture to your sprites:
var tex = new THREE.TextureLoader().load("https://threejs.org/examples/textures/sprites/disc.png");
// load the texture
for (i = 0; i < parameters.length; i++) {
color = parameters[i][0];
size = parameters[i][1];
materials[i] = new THREE.PointsMaterial({
size: size,
map: tex // apply the texture in your material
});
particles = new THREE.Points(geometry, materials[i]);
particles.rotation.x = Math.random() * 6;
particles.rotation.y = Math.random() * 6;
particles.rotation.z = Math.random() * 6;
scene.add(particles);
}
Upvotes: 1