Putting three.js inside of div 2 - three.js

I apologize for one more basic question which basically is a copy of another old thread, but I'm new to three.js and learning more or less through trial and error over here...
I found the old thread 'Putting three.js animation inside of div' where they succeeded putting a three.js animation inside of a div with the following lines of code:
container = document.getElementById( 'canvas' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setSize( 200, 200 );
container.appendChild( renderer.domElement );
A JSFiddle of above script (http://jsfiddle.net/fek9ddg5/1/)
I'm trying to do the same and added the lines to my script, but ended up with a completely white screen instead. I managed to basically part the screen in two parts, one completely white and another with the script. However, it failed since the script reacted to the mouse even if it moved in the white part. I made a codepen, I placed the script I added inside of comment-signs.
See it here: http://codepen.io/anon/pen/qRdGWo

Usually to add three.js to a page I would use this:
renderer = new THREE.WebGLRenderer();
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;
As can be seen in this fiddle
But, to add it to a div that is already on the page with the ID 'canvas-container' I would use..
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
// get the div that will hold the renderer
var container = document.getElementById('canvas-container');
var w = container.offsetWidth;
var h = container.offsetHeight;
renderer.setSize(w, h);
// add the renderer to the div
container.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, w / h, 1, 1000);
camera.position.z = 400;
Which can be seen in this fiddle
Basically where the renderer is added is determined on what dom element you call appendChild(renderer.domElement) on.

Related

Three.js: is using a RenderTarget as a mesh the most direct way put a scene back into a WebGLRenderer after an EffectComposer?

I'm attempting to use the Magnify-3d package after using an EffectComposer to apply a bokeh effect to a scene. Magnify-3D takes in a renderer, so I cannot simply pass in the EffectComposer after applying passes.
The intended result would work like a microscope, with the ability to independently adjust the plane of focus by adjusting the BokehPass effect, and the magnification using Magnify-3d.
The only way I've gotten this to work so far has been like so:
Create a temporary scene containing actual scene I want to render.
Create an EffectComposer that applies BokehPass and renders the temporary scene to renderTarget.
Create a PlaneBufferGeometry and a mesh that maps renderTarget.texture (the output of the temporary scene) to the plane, and add this to a new scene.
Render the new scene that effectively is just a camera staring at a mesh of the original scene.
Pass the renderer into magnify3d, which creates a lens effect around the scene I want to render.
This seems to work OK (though there appears to be some fuzziness and distortion of the original scene I'm still working out), but I began to wonder -- is this really the best way to use something rendered to a RenderTarget? Is there a more direct way than effectively taking a picture of a picture that I can use to take the output of an EffectComposer, feed it back into a renderer so my final scene is rendered in a WebGLRenderer, and pass it into a library? Any other way I can think to do this, the EffectComposer would not be able to run (since Magnify3d takes in a renderer, not an EffectComposer and I need to run the EffectComposer before passing it into a renderer).
Here's a screenshot of the final result
Here's some code below:
// create initial scene
const renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
const rtScene = new THREE.Scene();
const rtCamera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
// add a sample cube to the new scene and move the camera back
const geometry = new THREE.BoxGeometry( 10, 10, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
rtScene.add(cube);
rtCamera.position.z = 500;
// initialize renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.body.appendChild( renderer.domElement );
// initialize EffectComposer and apply BokehEffect.
// Note that composer renders its output to RenderTarget.
const composer = new EffectComposer( renderer, renderTarget );
composer.renderToScreen = false;
const renderPass = new RenderPass( rtScene, rtCamera );
composer.addPass( renderPass );
const bokehValues = {
focus: 500,
aperture: .00025,
maxblur: 1,
width: window.innerWidth,
height: window.innerHeight
}
export const bokehPass = new BokehPass( rtScene, rtCamera, bokehValues);
composer.addPass( bokehPass );
// create final scene to render before passing to Magnify3D
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
const scene = new THREE.Scene();
camera.position.z = 100;
// make a plane geometry, a mesh that maps renderTarget.texture, and add it to the scene
const planeGeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
const planeMaterial = new THREE.MeshBasicMaterial( { map: renderTarget.texture } );
const plane = new THREE.Mesh( planeGeometry, planeMaterial );
scene.add( plane );
function animate() {
// first render temporary scene
renderer.setClearColor( 0xffffff, 1 );
composer.render(); // now composer has rendered to renderTarget
renderer.setClearColor( 0x141414, 1 ); // create a black background for outside of microscope
renderer.render( scene, camera ); // render final scene with meshed plane
// Finally use Magnify3D to render final scene with microscope
magnify3d.render({
renderer: renderer,
pos: {
x: window.innerWidth/2,
y: window.innerHeight/2
},
renderSceneCB: (target) => {
if (target) {
renderer.setRenderTarget(target);
} else {
renderer.setRenderTarget(null);
}
renderer.render(scene, camera);
},
radius: window.innerWidth/5,
exp: 150,
zoom: state.magnification,
});
requestAnimationFrame( animate );
}

Manually specifying camera matrices in ThreeJS

I'm working on a project where I will draw 3D graphics on a video that is filmed with a real camera. I get provided a static projection and view matrix and my task is to draw the actual graphics on top. I've got it working in pure WebGL and know I'm trying to do it in ThreeJS. The problem is that I can't find a way to manually set the projection and view matrix for the camera in ThreeJS.
I've tried to set camera.matrixAutoUpdate = false and calling camera.projectionMatrix.set(matrix) and camera.matrixWorldInverse.set(matrix), but it doesn't seam to work. It is like the actual variable isn't passed to the shader.
Does anyone know how this can be done?
This is what I've got so far:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.matrixAutoUpdate = false;
camera.projectionMatrix.set(...)
camera.matrixWorldInverse.set(...)
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();

Adding three.js compound object into A-Frame causing unexpected flickering of child objects

I am adding augmented reality experience to my web app which originally created using threejs
I have a compound object(which is an Object3D instance with multiple meshes). but placing it into A-Frame giving unexpected flickering s shown in below
Pic of the original web app with threejs is given below
I have the three.js code like below
scene = new THREE.Scene();
mainObj = new THREE.Object3D();
scene.add(mainObj);
renderer = new THREE.WebGLRenderer({alpha: true, antialias: true});
renderer.sortObjects = false
container = document.getElementById("canvas-container");
width = $(container).innerWidth();
height = $(container).innerHeight();
renderer.setSize(width, height);
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(75, width / height, 10, 2000);
camera.position.set(0, 67, 100);
controls = new THREE.OrbitControls( camera , container);
controls.dampingFactor = 0.2;
controls.enableDamping = true;
controls.target.set( 0, 10, -20 );
controls.maxPolarAngle = (Math.PI/2) - 0.05;
controls.maxDistance = 800;
controls.minDistance = 2;
controls.target.set(0, buildingConfig.h/2, buildingConfig.l/-2)
controls.enableKeys = false;
controls.update();
scene.add(camera);
light = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.7);
light.position.set(1, 10000, 1);
light.castShadow = true
scene.add( light );
renderer.render(scene, camera);
// logic to add child meshes to mainObj
Which I changed to include in A-Frame.
<script type="text/javascript">
initmodels();
AFRAME.registerComponent('e1', {
init:function(){
this.el.setObject3D('building', mainObj);
}
});
</script>
<a-scene e1>
</a-scene>
I guess this issue is related to the scene or renderer. Can anyone help me with a proper scene or renderer setup in A-Frame
This looks like z-fighting. Is the three.js version running on a different system than your aframe version?
Different platforms have different z-buffer precision. It may require you to make changes to the geometry to compensate for the limited resolution.
Also, I don't know about AR.s, but the THREE renderer has a "logarithmicDepthBuffer" option that can increase the resolution of your z-buffer at near scales, but may have some side effects.
I had exactly the same issue. After a few trial and errors, I was able to fix it
Added recent version of aframe
Add <a-scene embedded artoolkit='sourceType: webcam;' renderer='logarithmicDepthBuffer: true;'>
Add <a-marker-camera camera="far:100000; near:0.01" >
Main reason was the light, Remove all lights and add only the hemisphere light into the scene and improvise upon other lights later on.
Hope this would resolve your issue too.

Three.VRControls initial rotation

I've been doing through this Unable to change camera position when using VRControls and Three.js - VRControls integration - How to move in the scene? but it's not quite doing what I need.
I have a VR video app and I've just switched to VRControls with the WebVR polyfill from something old and custom. This is working well, however I'm really struggling to set the initial camera angle.
I.e. I want the camera to start pointing at a particular angle, and then rotate with the controls - however the controls always override this angle.
I've tried adding the camera to a Dolly Group or Persepective Camera, and it seems like I can move the camera but not set the initial viewing angle.
Here is how the camera is set up
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1024);
scene = new THREE.Scene();
target = new THREE.Vector3();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
var vrEffect = new THREE.VREffect(renderer);
vrEffect.setSize(window.innerWidth, window.innerHeight);
var params = {
hideButton: false, // Default: false.
isUndistorted: false // Default: false.
};
manager = new WebVRManager(renderer, vrEffect, params);
dolly = new THREE.PerspectiveCamera();
dolly.add( camera );
//scene.add( dolly );
controls = new THREE.VRControls(camera);// (I've tried using Dolly here)
controls.standing = true;
And I've tried various ways to rotate the camera, dolly or scene
camera.position.y = currentScene.pan * Math.PI/180;
//controls.resetPose();
//dolly.position.x = currentScene.tilt * Math.PI/180;
//camera.updateProjectionMatrix();
I can rotate the mesh, but then all the objects inside the mesh are in the wrong place.. I could try moving them but this seems like the wrong approach to point the camera to the place I want it..
The camera was getting re-added to the scene at a later time, overriding the dolly. It's working now.

Three.js Stereo Effect not lining up

I'm using Stero Effect in Three.js for a simple VR player, and the views don't line up - i.e. the right view is pointing a little more to the left than the left view and vice versa.
I've looked through all the examples and I'm not sure what I'm doing wrong. No one else seems to have this problem
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1024);
scene = new THREE.Scene();
target = new THREE.Vector3();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.autoClear = false;
effect = new THREE.StereoEffect(renderer);
effect.setSize(window.innerWidth, window.innerHeight);
//in the renderer
if(vrMode)
effect.render(scene, camera);
else
renderer.render(scene, camera);
Has anyone seen this before or know what else might cause it?
I think it's due to the eye separation parameter. Try to set it to 0 it worked for me.
The parameter is on the StereoEffect.js file: this.separation

Resources