Creating a particle using an image as a map - javascript

I'm having trouble creating a particle using an image as a map on a texture. Below is my code:
var camera, scene, renderer, material, img, texture;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 8000;
scene.add(camera);
img = new Image();
texture = new THREE.Texture(img);
img.onload = function() {
texture.needsUpdate = true;
makeParticle();
};
img.src = "http://www.aerotwist.com/tutorials/creating-particles-with-three-js/images/particle.png";
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function makeParticle() {
material = new THREE.ParticleBasicMaterial({
color: 0xE60000,
size: 20,
map: texture,
blending: THREE.AdditiveBlending,
transparent: true
});
// make the particle
particle = new THREE.Particle(material);
particle.scale.x = particle.scale.y = 1;
scene.add(particle);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
A fiddle with this code is here: jsfiddle
I am aware I can use the Three Image Helper as follows:
map: THREE.ImageUtils.loadTexture(
"FILE PATH"
),
But I am implementing my own asset loader and so do not wish to use it on an individual basis. Currently my code above shows no errors but no particle is displayed.

The particle is being displayed, but the camera is very far of it.
Change this line:
camera.position.z = 8000;
To something like this:
camera.position.z = 50;

Related

How to scale a three.js sprite?

I am trying to display a sprite in three on javascript and make it bigger. I tried the following:
THREE.ImageUtils.crossOrigin = '';
var spriteMap = THREE.ImageUtils.loadTexture( "https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png" );
var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap } );
var sprite = new THREE.Sprite( spriteMaterial );
sprite.width = 10;
sprite.height = 10;
scene.add( sprite );
and
THREE.ImageUtils.crossOrigin = '';
var spriteMap = THREE.ImageUtils.loadTexture( "https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png" );
var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap } );
var sprite = new THREE.Sprite( spriteMaterial );
sprite.size = THREE.Vector3(10,10,10);
scene.add( sprite );
but the sprite was very very tiny in the middle of the browser window. I saw no error on the console.
What am I doing wrong?
Sprite.size does not exist. Try to modify Sprite.scale instead. Check out the following live example:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 5;
scene = new THREE.Scene();
var loader = new THREE.TextureLoader();
var map = loader.load("https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png");
var material = new THREE.SpriteMaterial({
map: map
});
var sprite = new THREE.Sprite(material);
sprite.scale.set( 5, 5, 1 );
scene.add(sprite);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.119.1/build/three.js"></script>
If you want the scaling to happen based on the camera distance, you need to add a parameter to your material variable:
sizeAttenuation: false
Like this:
var material = new THREE.SpriteMaterial({
map: map,
sizeAttenuation: false});
This will make your sprite big when to camera is far away and smaller when the camera gets closer to it (based on the sprite.scale.set() values).

How to make visible edges that are intersects other objects' surfaces?(THREE.js)

I am working in a three.js project. In the project I have to show all edges of geometries even those edges are intersecting with other objects' surfaces.
Here is the snippet code that illustrates my problem.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create material
material = new THREE.MeshBasicMaterial();
wireframeMaterial=new THREE.LineBasicMaterial( { color: 0x000000, side:THREE.FrontSide ,transparent:false,opacity:1,linewidth: 1 })
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var mesh1 = new THREE.Mesh(geometry, material);
group.add(mesh1);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var mesh2 = new THREE.Mesh(geometry2, material);
group.add(mesh2);
mesh2.position.fromArray([0,150,0])
var edges = new THREE.EdgesGeometry( geometry );
var line = new THREE.LineSegments( edges, wireframeMaterial );
mesh1.add( line );
var edges2 = new THREE.EdgesGeometry( geometry2 );
var line2 = new THREE.LineSegments( edges2, wireframeMaterial );
mesh2.add( line2 );
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
In fiddle code you can see there are two cubes top of each other. I want bottom edges of small cube to become visible. One solution is making mesh basic material transparent. However in that situation edges that are behind cubes it self will be visible too which is not allowed in the project.
So are there any alternative solution for this issue?
Found a good solution, you need to use the polygonOffset parameters of the basic material.
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
Found it on this question: three.js EdgesHelper showing certain diagonal lines on Collada model
EdgesGeometry will render the hard edges only.
WireframeGeometry will render all edges.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create materials
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
var wireframeMaterial= new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2 } );
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var edges = new THREE.EdgesGeometry(geometry);
var line = new THREE.LineSegments( edges, wireframeMaterial );
var mesh = new THREE.Mesh(geometry, material);
group.add(mesh, line);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var wire = new THREE.EdgesGeometry(geometry2);
var line2 = new THREE.LineSegments( wire, wireframeMaterial );
var mesh2 = new THREE.Mesh(geometry2, material);
line2.position.fromArray([0,150,0]);
mesh2.position.fromArray([0,150,0]);
group.add(mesh2, line2);
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// Add stats to page.
stats = new Stats();
document.body.appendChild( stats.dom );
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
stats.update();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
<script type="text/javascript" src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/mrdoob/stats.js/r17/build/stats.min.js"></script>

three.js horizontal PlaneGeometry at x=0 y=0 z=0

Hi I have this code that draws the image below
window.onload = function()
{
// init renderer
var renderer=new THREE.WebGLRenderer();
canvas_width=side; canvas_height=side;
renderer.setSize(canvas_width,canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(90,canvas_width/canvas_height,1,100);
camera.position.y=5;
camera.position.z=25;
var texture = new THREE.TextureLoader().load( 'arrow.png' );
var img = new THREE.MeshBasicMaterial( { map: texture } );
// mesh
mesh = new THREE.Mesh(new THREE.PlaneGeometry(25,25),img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light=new THREE.HemisphereLight(0xffffff,0x000000,1.5);
light.position.set(1,1,1);
scene.add(light);
// render
requestAnimationFrame(function animate(){
requestAnimationFrame(animate);
renderer.render(scene,camera);
})
}
but I want to draw the PlaneGeometry horizontally instead of vertically, not rotating it with mesh.rotation.x=THREE.Math.degToRad(-90);, to get this at x=0 y=0 z=0:
so that with
mesh.rotation.x=THREE.Math.degToRad(-90);
the arrow will pointing down
and with:
mesh.rotation.x=THREE.Math.degToRad(90);
the arrow will pointing up
can you help me?
You can do it, rotating the geometry with .rotateX():
// init renderer
var renderer = new THREE.WebGLRenderer();
canvas_width = window.innerWidth;
canvas_height = window.innerHeight;
renderer.setSize(canvas_width, canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, canvas_width / canvas_height, 1, 100);
camera.position.y = 5;
camera.position.z = 25;
var texture = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
var img = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
});
// mesh
geom = new THREE.PlaneGeometry(25, 25);
geom.rotateX(-Math.PI * 0.5); // this is how you can do it
mesh = new THREE.Mesh(geom, img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light = new THREE.HemisphereLight(0xffffff, 0x000000, 1.5);
light.position.set(1, 1, 1);
scene.add(light);
// render
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
})
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>

square textures for circular particles in three.js

I'm having trouble rendering particles properly in three.js. I'm trying to follow this tutorial to set up particles. Unfortunately, while they're placed correctly and are displayed, they are clearly rectangular, rather than circular.
Here's the code for the material
var texture = new THREE.TextureLoader().load(
"textures/disc.png",
function(texture) {
var material = new THREE.PointsMaterial({
color: 0xFFFFFF,
size: 16,
map: texture,
transparent: true,
blending: THREE.AdditiveBlending,
});
particles = new THREE.Points( geometry, material );
});
and here's a pen with complete code.
I honestly have no idea why they're rendered like that, when it's working perfectly in the example in the tutorial.
The issue is the fog is being added to your particles. Set fog to false in the PointMaterial
var scene,
camera, fieldOfView, aspectRatio, nearPlane, farPlane, HEIGHT, WIDTH,
renderer, container;
function createScene() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0xf7d9aa, 100, 950)
aspectRatio = WIDTH / HEIGHT;
fieldOfView = 60;
nearPlane = 1;
farPlane = 10000;
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane
);
camera.position.x = 10;
camera.position.z = 290;
camera.position.y = 25;
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setClearColor(new THREE.Color(0, 0, 0));
renderer.setSize(WIDTH, HEIGHT)
renderer.shadowMap.enabled = true;
container = document.getElementById('world');
container.appendChild(renderer.domElement);
window.addEventListener('resize', handleWindowResize, false);
}
function handleWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
var hemisphereLight, shadowLight;
function createLights() {
}
var sphere;
function createSphere() {
var geometry = new THREE.SphereGeometry( 150, 32, 32 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
sphere = new THREE.Mesh( geometry, material );
sphere.visible = false;
scene.add( sphere );
}
function createParticles() {
var loader = new THREE.TextureLoader();
var texture = loader.load(
"https://i.imgur.com/9fW07EI.png",
function(texture) {
editGeometry = sphere.geometry;
var geometry = new THREE.Geometry();
for ( i = 0; i < editGeometry.vertices.length; i ++ ) {
geometry.vertices.push(editGeometry.vertices[i]);
}
var material = new THREE.PointsMaterial({
color: 0xFFFFFF,
size: 16,
map: texture,
transparent: true,
blending: THREE.AdditiveBlending,
fog: false,
depthTest: false,
});
particles = new THREE.Points( geometry, material );
particles.sortParticles = true;
scene.add( particles );
});
}
function loop() {
renderer.render(scene, camera);
requestAnimationFrame(loop);
}
function init() {
createScene();
createLights();
createSphere();
createParticles();
loop();
}
init()
body {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.min.js"></script>
<div id="world">
</div>
Note that if your image is not on the same domain as your webpage then you can't use the image in WebGL unless you both request cross origin access and the server serving the image gives permission.
Also you can't use images from a 3rd party domain unless the server sends CORS headers for permission to use the image. The postimg.org server did not give permission for the image. imgur's server did.
You must also turn off the depthTest otherwise points drawn in front will end up blocking out points drawn in back. Since you're drawing with transparency and additive blending that's probably what you want.
It's not work for me, maybe I use a ShaderMaterial, but depthTest: false works.
let material = new THREE.ShaderMaterial({
uniforms: {
uColor: { value: new THREE.Color(0xffffff) },
uPointTexture: { value: new THREE.TextureLoader().load(require('./res/spark1')) }
},
vertexShader: _me.vertex_shader,
fragmentShader: _me.fragment_shader,
depthTest: false,
transparent: true,
// fog: false
})

Three.js wont render on canvas

I loaded the script in index.html but when I open the page it shows the rendered but nothing inside, nothing renderer, I can't find the problem
Here is the code of external .js:
var wdt = $('.design').width();
var hgh = $('.design').height();
var scene = new THREE.Scene();
var camera = new THREE.Camera(75, wdt/hgh, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(wdt, hgh);
document.getElementById('designer').appendChild(renderer.domElement);
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
var render = function () {
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
Can anybody help please?
Camera issues
Here's a jsfiddle of a working version.
Camera in Three.js is abstract, so I picked the common one to construct:
var camera = new THREE.PerspectiveCamera (75, wdt / hgh, 0.1, 1000);
The camera's viewpoint doesn't line up by default, so explicit calls eliminate confusion:
camera.lookAt(cube.position);
And adding the camera to the scene:
scene.add(camera);

Categories