Incremental rendering of particals in THREE.js - javascript

Newbie to 3D world. Trying to render particles as they are created so that these 2000 particles should render as they are created. But from below code it renders only once all particles are created.
Tried couple of variations but no luck. Any help is appreciated.
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 255;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
var particles = new THREE.Geometry;
for (var p = 0; p < 2000; p++) {
var particle = new THREE.Vector3(Math.random() * 500 - 250, Math.random() * 500 - 250, Math.random() * 500 - 250);
particles.vertices.push(particle);
}
var particleMaterial = new THREE.ParticleBasicMaterial({ color: 0xeeeeee, size: 2 });
var particleSystem = new THREE.ParticleSystem(particles, particleMaterial);
scene.add(particleSystem);
function render() {
requestAnimationFrame(render);
particleSystem.rotation.y += 0.01;
renderer.render(scene, camera);
}
render();
</script>

You can render a subset of you particles (now called THREE.Points) by using BufferGeometry and setting the draw range.
var geometry = new THREE.BufferGeometry();
geometry.setDrawRange( startIndex, count );
You can reset the draw range inside your animation loop.
See this answer for information on how to populate the geometry and a live demo.
three.js r.78

Related

Rendering to render target makes some of my graphics invisible

Hi I have been playing with render targets but I ran into some problems. I created a simplified example here:
init = function() {
// RENDERER
canvas = document.getElementById("mycanvas");
renderer = new THREE.WebGLRenderer({
antialias: true
});
document.body.appendChild( renderer.domElement );
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// SCENE
texscene = new THREE.Scene();
texcamera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
texcamera.position.z = 2;
// FRAMEBUFFER
var renderTargetParams = {
minFilter:THREE.LinearFilter,
stencilBuffer:false,
depthBuffer:false,
wrapS: THREE.RepeatWrapping,
wrapT: THREE.RepeatWrapping
};
rendertarget = new THREE.WebGLRenderTarget( 512, 512, renderTargetParams );
// CUBE
var cubeGeo = new THREE.BoxGeometry( 1, 1, 1, 1, 1, 1 );
var cubeMat = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
texcube = new THREE.Mesh( cubeGeo, cubeMat )
texscene.add(texcube);
var blueMaterial = new THREE.MeshBasicMaterial({color:0x7074FF})
var plane = new THREE.PlaneBufferGeometry( 100, 100 );
var planeObject = new THREE.Mesh(plane,blueMaterial);
planeObject.position.z = -15;
texscene.add(planeObject);
/////////////////////////////////
//SCENE
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
var boxMaterial = new THREE.MeshBasicMaterial({map:rendertarget.texture});
var boxGeometry2 = new THREE.BoxGeometry( 5, 5, 5 );
mainBoxObject = new THREE.Mesh(boxGeometry2,boxMaterial);
// Move it back so we can see it
mainBoxObject.position.z = -10;
// Add it to the main scene
scene.add(mainBoxObject);
animate();
}
animate = function() {
requestAnimationFrame(animate);
renderer.render(texscene, texcamera, rendertarget);
renderer.render(scene, camera);
texcube.rotation.y += 0.01;
texcube.rotation.z += 0.01;
mainBoxObject.rotation.x +=0.01;
mainBoxObject.rotation.y += 0.005;
mainBoxObject.rotation.z += 0.008;
}
init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>
I render a red cube and a blue plane to a render target then use it as a texture. Problem is the red cube is not visible in the final result.
Try for yourself to see the render target scene by changing
renderer.render(texscene, texcamera, rendertarget);
renderer.render(scene, camera);
to
renderer.render(texscene, texcamera);
Apparantly the problem is caused by turning off the depth buffer as I had done in the settings of my rendertarget
depthBuffer:false,
Removing this line makes my rendertarget render as it should with a red box on a blue background

Three.js particles move to the side instead toward the camera

I'm trying to create a clouds fly through similar to this, only with more maneuverability:
http://mrdoob.com/lab/javascript/webgl/clouds/
I had no problem creating that using sprites, but I want to improve the performance so I'm trying to use particles with THREE.PointCloud.
The problem is that when I fly toward the particles, instead of "colliding" in the camera there's some weird effect when the particle hangs in front of the camera and then slides to the side, I made an example here: http://jsfiddle.net/6avpd6me/36/
All the particles are moving toward the camera in a straight line, but non of them actually colliding in it, changing the size doesn't help.
Anybody knows what's causing this and maybe how can I fix that?
Thanks
JSFiddle code:
var geometry, renderer, scene, camera, cloud, uniforms, attributes;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
//camera
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 600;
var particleMaterial = new THREE.PointCloudMaterial({
color:0xffffff,
size: 100,
transparent:true,
opacity:0.5,
sizeAttenuation:false
});
particleMaterial.depthTest = true;
particleMaterial.depthWrite = false;
// point cloud geometry
geometry = new THREE.PlaneGeometry( 10, 10, 5, 5);
for( var i = 0; i < geometry.vertices.length; i++)
{
geometry.vertices[i].velocity = new THREE.Vector3(0, 0, random(50, 300) / 100);
}
cloud = new THREE.PointCloud(geometry, particleMaterial);
scene.add( cloud );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
for( var i = 0; i < geometry.vertices.length; i++ )
{
geometry.vertices[i].add(geometry.vertices[i].velocity);
if (geometry.vertices[i].z > 650) geometry.vertices[i].z = 0;
}
geometry.verticesNeedUpdate = true;
renderer.render( scene, camera );
}
function random(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}

Particles in three.js

Can someone kindly explain me why there are no particles visible in the following code?
Followed a tutorial and everything seems ok.
(function() {
var camera, scene, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(2,2,10);
camera.lookAt(scene.position);
console.log(scene.position);
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 );
var pGeometry = new THREE.Geometry();
for (var p = 0; p < 2000; p++) {
var particle = new THREE.Vector3(Math.random() * 50 - 25, Math.random() * 50 - 25, Math.random() * 50 - 25);
pGeometry.vertices.push(particle);
}
var pMaterial = new THREE.ParticleBasicMaterial({ color: 0xfff, size: 1 });
var pSystem = new THREE.ParticleSystem(pGeometry, pMaterial);
scene.add(pSystem);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
})();
fiddle
CanvasRenderer does not support ParticleSystem. You need to use WebGLRenderer.
If you need to use CanvasRenderer, then see http://threejs./examples/canvas_interactive_particles.html for how to use Sprites instead.
three.js r.64
Also, as a side note, as of the time of this answer, IE11's WebGL implementation has an issue with points and sizing them. Particles in Three.js shaders use points to draw the particles and so in IE11, you will see very small squares and if you're not paying attention, you might not see anything at all ;)
I do know that in the next version of IE (updates coming) that this is fixed and allows you not only to change the point size, but use bitmaps with them.

How to change one texture image of a 3d model(maya ) in three.js at runtime

This site is loading a maya model using three.js.
This model has Below texture pictures
Here is the JS
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container;
var camera, scene;
var canvasRenderer, webglRenderer;
var mesh, zmesh, geometry, materials;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var meshes = [];
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000);
camera.position.x = 400;
camera.position.y = 200;
camera.position.z = 400;
scene = new THREE.Scene();
// LIGHTS
var ambient = new THREE.AmbientLight(0x666666);
scene.add(ambient);
var directionalLight = new THREE.DirectionalLight(0xffeedd);
directionalLight.position.set(0, 70, 100).normalize();
scene.add(directionalLight);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
var loader = new THREE.JSONLoader(),
callbackKey = function (geometry, materials) {
createScene(geometry, materials, 0, 0, 0, 6)
};
loader.load("chameleon.js", callbackKey);
window.addEventListener('resize', onWindowResize, false);
}
function createScene(geometry, materials, x, y, z, scale) {
zmesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
zmesh.position.set(x, y, z);
zmesh.scale.set(scale, scale, scale);
meshes.push(zmesh);
scene.add(zmesh);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
webglRenderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
for (var i = 0; i < meshes.length; i++) {
meshes[i].rotation.y += .01;
}
requestAnimationFrame(animate);
render();
}
function render() {
camera.lookAt(scene.position);
webglRenderer.render(scene, camera);
}
$(document).ready(function () {
init();
animate();
});
now i want to change the 1st texture picture to some other texture and rest of the texture remains same on runtime! how to do it?
if you'd like to change the texture at runtime. All you need to do is look at the zmesh objects material. Find the appropriate index of the blue dress material and swap it out. Your model is a little tricky in that you have an array of materials but no matter. For a single material object you simply change the mesh.material.map and update it, in your case we need mesh.material.materials[index].map. So try adding this to the bottom of your createScene function. It will replace the dress with the eyeball texture:
zmesh.material.materials[1].map = THREE.ImageUtils.loadTexture( 'c006_10.jpg' );
Of course, replace 'c006_10.jpg' with the appropriate path to your eyeball texture. One added Note, if you hook up the texture swap to an onclick for example you'll want to have an active render loop or call renderer's render function to get it to display.

How can I print text along an arc using Three.js?

I'm trying to print text along an arc using Three.js. With help from this post, I was able to get the math for the rotation. But, as you'll see, the text is all jumbled on top of itself. How can I get it to correctly space itself out? Codepen is here.
var container, camera, scene, renderer;
function init() {
container = document.getElementById( 'canvas' );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 100000);
camera.position.z = 500;
scene.add(camera);
var loader = new THREE.FontLoader();
loader.load( 'https://raw.githubusercontent.com/mrdoob/three.js/master/examples/fonts/helvetiker_bold.typeface.json', function ( font ) {
var theText = "This is some text."
var numRadsPerChar = 2*Math.PI/theText.length;
for (var i = 0; i < theText.length; i++){
var char = theText[i]
var geometry = new THREE.TextBufferGeometry( char, {
font: font,
size: 60,
height: 60,
curveSegments: 20
});
var materials = [
new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
];
var mesh = new THREE.Mesh( geometry, materials );
mesh.rotation.z = (i * numRadsPerChar);
//mesh.position.x = i * 20;
group = new THREE.Group();
group.add( mesh );
scene.add( group );
};
} );
renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
animate();
} init();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Had some help figuring this out, but here's the portion that needed to be edited to work:
mesh.rotation.z = (i * numRadsPerChar);
Needed to be:
mesh.position.x = 100 * Math.sin(i * numRadsPerChar);
mesh.position.y = 100 * Math.cos(i * numRadsPerChar);
mesh.rotation.z = Math.PI/2 -(i * numRadsPerChar);
Basically, I needed to add a constant (Math.PI/2) for the rotation. For the x and y positions, I had to take the sin and cosine, respectively, to get the letters to be placed properly around the arc. Here's a working codepen.
Another way to do this would be to draw your text on a canvas and use the canvas in a texture with texture.wrapS and .wrapT set to THREE.RepeatWrapping.. then put that texture on a material.. then make a path with the extruded path geometry and set it's material. The you can move the text by setting the texture.offset.x or y each frame in your render loop.

Categories

Resources