I am trying to create an online 3D manipulation tool. I have got my THREE.js view set up with a rotating cube and a grid. When I run the code it works 100% fine, but if I resize the view it does not adjust the THREE.js screen with it. (It shrinks the length or width of the scene depending on how the browser view changes.) causing to view to look distorted.
$(function(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, .1, 500);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xdddddd);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMapSoft = true;
var axis = new THREE.AxisHelper(10);
scene.add(axis);
var color = new THREE.Color("rgb(255,0,0)");
var color2 = new THREE.Color(0xd3d3d3);
var grid = new THREE.GridHelper(50, 15, color, color2);
scene.add(grid);
var cubeGeometry = new THREE.BoxGeometry(5, 5, 5);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff3300});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
/*var planeGeometry = new THREE.PlaneGeometry(30, 30, 30);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -.5*Math.PI;
plane.position.y = -.1
plane.recieveShadow = true;
scene.add(plane);*/
cube.position.x = 2.5;
cube.position.y = 4;
cube.position.z = 2.5;
cube.castShadow = true;
scene.add(cube);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.castShadow = true;
spotLight.position.set(15, 30, 50);
scene.add(spotLight);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
var guiControls = new function(){
this.rotationX = 0.01;
this.rotationY = 0.01;
this.rotationZ = 0.01;
}
var datGUI = new dat.GUI();
datGUI.add(guiControls, 'rotationX', 0, 1);
datGUI.add(guiControls, 'rotationY', 0, 1);
datGUI.add(guiControls, 'rotationZ', 0, 1);
render();
function render() {
//Me trying to reset the camera view every render
camera.fov = 45
camera.aspect = window.innerWidth / window.innerHeight
camera.near = .1
camera.far = 500
scene.add(camera);
cube.rotation.x += .1;
renderer.setSize(window.innerWidth, window.innerHeight);
requestAnimationFrame(render);
renderer.render(scene, camera);
}
$("#world").append(renderer.domElement);
renderer.render(scene, camera);
});
Add an event listener in your code to handle the resize:
window.addEventListener( 'resize', onWindowResize, false );
And then:
function onWindowResize() {
w = window.innerWidth;
h = window.innerHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize( w, h );
}
Or, since you are using jQuery, you can add this instead:
$( window ).resize(function() {
w = window.innerWidth;
h = window.innerHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize( w, h );
});
Click here to see a working codePen.
Related
I am rendering a cityscape using Three.js. When attempting to view the scene I can't seem to get the camera near/far settings correct to render the whole scene. When I increase the camera's far plane - I am able to see the model, but it appears blue (image below) until I zoom into it. Is there a way to see the entire model without having to zoom super close to the scene?
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)
When an object is being clipped out of the camera's focal length, you can use Object3D.scale. AFter adjusting this scaler value the entire building is visible in the camera on load and does not get clipped. You adjust the objects scale during the loading callback.
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
// adjust the scale of the object in the scene.
// default scale is (1,1,1)
obj.scale.set( .1, .1, .1 );
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)
I'm creating an HTML file integrating ThreeJs, basically I have created 4 Spheres, 1 of them projects the light, other 3 spheres turn in a wall. When the Spheres is behind the wall they should not reflect the light, what I supposed to do to solve this?
I've already try changing the materials of the Spheres which turns around the wall to Lambert and Phong, setting up castShadow to true, and recieveShadow to False
(function onLoad() {
var camera, scene, renderer, orbitControls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 30, -100);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
orbitControls = new THREE.OrbitControls(camera);
escena = scene;
esferaLuz = new THREE.SphereBufferGeometry(0.5, 16, 16);
luzUno = new THREE.SpotLight(0xFFFFFF, 1);
luzUno.angle = Math.PI / 12;
luzUno.penumbra = 0.05;
luzUno.decay = 2;
luzUno.position.set(-30, 40, -5);
mtLuzUno = new THREE.MeshBasicMaterial({color: 0xFFFFFF});
mallaLuzUno = new THREE.Mesh(esferaLuz, mtLuzUno);
luzUno.add(mallaLuzUno);
escena.add(luzUno);
luzUno.castShadow = true;
luzUno.shadow.mapSize.width = 1024;
luzUno.shadow.mapSize.height = 1024;
luzUno.shadow.camera.near = 10;
luzUno.shadow.camera.far = 200;
luzMap = new THREE.SpotLightHelper(luzUno);
escena.add(luzMap);
sombraMap = new THREE.CameraHelper(luzUno.shadow.camera);
escena.add(sombraMap);
var luzAmbiente = new THREE.AmbientLight( 0xffffff, 0.1 );
escena.add(luzAmbiente);
geometriaPlana = new THREE.CubeGeometry(100, 100, 2, 2);
mtPlano = new THREE.MeshLambertMaterial({color: 0x000000});
mtPlano.transparent = false;
mtPlano.depthWrite = true;
mallaPlano = new THREE.Mesh(geometriaPlana, mtPlano);
mallaPlano.rotation.x = -0.5*Math.PI;
mallaPlano.position.x = 15;
mallaPlano.position.y = 0;
mallaPlano.position.z = 0;
mallaPlano.receiveShadow = true;
escena.add(mallaPlano);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xFFFFFF, specular:0xFFFFFF, shininess: 1024});
mallaObjEsfera3 = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera3.position.set(20, 0, 0);
mallaObjEsfera3.castShadow = true;
mallaObjEsfera3.receiveShadow = false;
escena.add(mallaObjEsfera3);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xF90E0E, specular:0xF90E0E, shininess: 512});
mallaObjEsfera2 = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera2.position.set(5, 0, 0);
mallaObjEsfera2.castShadow = true;
mallaObjEsfera2.receiveShadow = false;
escena.add(mallaObjEsfera2);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshLambertMaterial({color: 0xF2E406});
mallaObjEsfera = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera.position.set(-10, 0, 0);
mallaObjEsfera.castShadow = true;
mallaObjEsfera.receiveShadow = false;
escena.add(mallaObjEsfera);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio);
renderer.setClearColor(0xEEEEEE);
renderer.shadowMap.enabled = true;
renderer.shadowMap.renderReverseSided = false;
renderer.sortObjects = false
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.gammaInput = true;
renderer.gammaOutput = true;
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
I expect that when the spheres is behind the wall, don't show any type of reflects of light but when is on the front reflect the light .
One way to achieve your intended result is to work with shadows. So you have to set Object3D.castShadow and Object3D.receiveShadow to true for your spheres and your ground like in the following live example:
https://jsfiddle.net/85q3sfeg/
Also keep in mind that three.js does not support selective lighting so far. This issue was already discussed at github right here: https://github.com/mrdoob/three.js/issues/5180
Assuming all objects of your scene have a lit material applied, you can't define what light sources should affect what objects.
three.js R103
I've created two 3JS objects and scenes for learning purposes. Both housed in separate PHP files (not in the jsfiddle). However, I can't figure out why by adding a second object the first object stops animating and doesn't run anymore? How can I go about figuring out why my objects are canceling one another out and how to create two different or more multiple threejs items that animate at the same time?
//GRID OBJ is the first object, and the second is //BALL
When I remove the second script calling for 3js ball the grid will animate, when the ball is added the grid stops animating and only the ball animates.
http://jsfiddle.net/tdqh4jno/
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor( 0x000000, 0 );
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(background, 1);
container.appendChild(renderer.domElement);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
function renderGrid() {
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
requestAnimationFrame(renderGrid);
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
renderer.render(scene2, camera2);
}
updatePlane();
renderGrid();
//BALL ITEM
var camera2 = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera2.position.z = 90;
function myrender(){
renderer.setClearColor( 0x000000, 0 );
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.render(sceneTop, camera2);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>
You create 2 THREE.WebGLRenderer objects, but both assigned to the variable renderer. This breaks down the animation of the first (grid) object in the function renderGrid.
In your code are created 2 different scenes referenced by 2 different variables (sceneTop, scene2). Create 2 different render objects, referenced by 2 different variables (renderer, renderer2), too:
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );
// [...]
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);
function renderGrid() {
// [...]
renderer2.render(scene2, camera2);
}
In the following you have to respect, that renderer corresponds to camera respectively sceneTop, but renderer2 corresponds to scene2 and camera2:
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
[...]
camera.position.z = 90;
function myrender(){
// [...]
renderer.render(sceneTop, camera);
requestAnimationFrame(myrender);
}
See the example, where I applied the suggested changes to your original code:
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
function renderGrid() {
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
requestAnimationFrame(renderGrid);
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
renderer2.render(scene2, camera2);
}
updatePlane();
renderGrid();
//BALL ITEM
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera.position.z = 90;
function myrender(){
renderer.setClearColor( 0x000000, 0 );
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.render(sceneTop, camera);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
renderer2.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
camera2.aspect = window.innerWidth / window.innerHeight;
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>
Alternatively both scenes can be rendered to different parts of the viewport.
Create 1 THREE.WebGLRenderer, with the .autoClear property set to false:
var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
Render both scenes 2 different parts of the viewport. The viewport rectangle can be changed by .setViewport:
function myrender(){
// [...]
renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
renderer.clear();
renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
renderer.render(sceneTop, camera, 0, false);
renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
renderer.render(scene2, camera2, 0, false);
requestAnimationFrame(myrender);
}
Ensure that the .background property is only set for the THREE.Scene which is rendered first.
See the example:
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
var camera2 = new THREE.PerspectiveCamera( 110, window.innerWidth/2/window.innerHeight, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
updatePlane();
//BALL ITEM
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/2/window.innerHeight, 0.1, 1000);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera.position.z = 90;
function myrender(){
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
renderer.clear();
renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
renderer.render(sceneTop, camera, 0, false);
renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
renderer.render(scene2, camera2, 0, false);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / 2 / window.innerHeight;
camera.updateProjectionMatrix();
camera2.aspect = window.innerWidth / 2 / window.innerHeight;
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
I am trying to set up image background for my scene with globe in three.js, but unfortunately, when I did it the main object of my scene also became black (the same colour with background.
I used method:
renderer = new THREE.WebGLRenderer({ antialias: false, alpha:true });
Which makes default background transparent. And then I added image-background in CSS part.
My whole script for the scene looks like this:
var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
//closer
camera.position.z = 500;
scene = new THREE.Scene();
group = new THREE.Group();
scene.add( group );
// earth
var loader = new THREE.TextureLoader();
loader.load( 'textures/mapnew1.jpg', function ( texture ) {
var geometry = new THREE.SphereGeometry( 180, 32, 32 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
} );
// shadow
var canvas = document.createElement( 'canvas' );
canvas.width = 128;
canvas.height = 128;
var context = canvas.getContext( '2d' );
var gradient = context.createRadialGradient(
canvas.width / 2,
canvas.height / 2,
0,
canvas.width / 2,
canvas.height / 2,
canvas.width / 2
);
gradient.addColorStop( 0.1, '#000000' );
gradient.addColorStop( 1, '#000000' );
context.fillStyle = gradient;
context.fillRect( 0, 0, canvas.width, canvas.height );
var texture = new THREE.CanvasTexture( canvas );
var geometry = new THREE.PlaneBufferGeometry( 300, 300, 3, 3 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.y = - 200;
mesh.rotation.x = - Math.PI / 2;
group.add( mesh );
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer = new THREE.WebGLRenderer({ antialias: false, alpha:true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0x000000, 0);
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.08;
camera.position.y += ( - mouseY - camera.position.y ) * 0.08;
camera.lookAt( scene.position );
group.rotation.y -= 0.003;
renderer.render( scene, camera );
}
</script>
This is my CSS:
body {
color: #ffffff;
font-family:'Futura';
font-size:20px;
text-align: center;
background-image: url(textures/starfield.png);
background-color: black;
margin: 0px;
overflow: hidden;
}
Do you have any ideas how to fix it and make globe visible?
Thank you very much!
Regarding the background image, you are setting the alpha value for WebGLRenderer, which is correct. You didn't post your CSS, but ensure you're setting the background image on your container, not on the canvas.
Also, comment out this line:
renderer.setClearColor(0x000000, 0);
You don't need to set a clear color, since you are clearing to transparency, not a color. That should resolve the background image issue.
Regarding the all-black model, you need a light in your scene. Try adding this to your init method:
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
This will add a light source at the location of your camera (and will follow the camera as it moves).
Edit to add snippet:
var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
//closer
camera.position.z = 500;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
scene = new THREE.Scene();
group = new THREE.Group();
scene.add(group);
// earth
var loader = new THREE.TextureLoader();
loader.crossOrigin = '';
loader.load('https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/640px-Equirectangular_projection_SW.jpg', function(texture) {
var geometry = new THREE.SphereGeometry(180, 32, 32);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: 0.5
});
var mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
});
// shadow
var canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 128;
var context = canvas.getContext('2d');
var gradient = context.createRadialGradient(
canvas.width / 2,
canvas.height / 2,
0,
canvas.width / 2,
canvas.height / 2,
canvas.width / 2
);
gradient.addColorStop(0.1, '#000000');
gradient.addColorStop(1, '#000000');
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
var texture = new THREE.CanvasTexture(canvas);
var geometry = new THREE.PlaneBufferGeometry(300, 300, 3, 3);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: 0.5
});
var mesh = new THREE.Mesh(geometry, material);
mesh.position.y = -200;
mesh.rotation.x = -Math.PI / 2;
group.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: false,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
//renderer.setClearColor(0x000000, 0);
container.appendChild(renderer.domElement);
stats = new Stats();
container.appendChild(stats.dom);
document.addEventListener('mousemove', onDocumentMouseMove, false);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
//
function animate() {
requestAnimationFrame(animate);
render();
stats.update();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.08;
camera.position.y += (-mouseY - camera.position.y) * 0.08;
camera.lookAt(scene.position);
group.rotation.y -= 0.003;
renderer.render(scene, camera);
}
body {
color: #ffffff;
font-family: 'Futura';
font-size: 20px;
text-align: center;
background-image: url(https://upload.wikimedia.org/wikipedia/commons/6/62/Starsinthesky.jpg);
background-color: black;
margin: 0px;
overflow: hidden;
}
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="container"></div>
three.js r86
Since a while, there is:
var texture = new THREE.TextureLoader().load( "textures/bg.jpg" );
scene.background = texture;
I'm using three.js v 0.87
There are two ways to do it
1) Load a image using TextureLoader and set it as background. This will result into static background which may not look very realistic.
var texture = new THREE.TextureLoader().load(
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
);
scene.background = texture;
2) Use skybox to load images for top, left, right bottom, front back sides. Then set them inside a cube or sphere geometry
var urls = [
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
"https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg"
];
var materialArray = [];
for (var i = 0; i < 6; i++)
materialArray.push(
new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(urls[i]),
side: THREE.BackSide
})
);
var skyGeometry = new THREE.SphereGeometry(400, 32, 32);
var skyMaterial = new THREE.MeshFaceMaterial(materialArray);
var skybox = new THREE.Mesh(skyGeometry, skyMaterial);
scene.add(skybox);
This will give a sphere with images as texture on backside. Just replace THREE.SphereGeometry with THREE.CubeGeometry and you can emulate envMap.
The previous solutions didn't work for me,
they miss the using of callback so at least from v.0.124 of the library,
this is how you can set the background image for the scene:
var texture_bg = new THREE.TextureLoader().load("img/bg.jpg", () => {
scene.background = texture_bg;
});
I'm kinda new to Three.js, I'm enjoying it a whole bunch, though I'm having an issue with shadow maps, I've read and looked everywhere but I just can't get it to work, can somebody point me in the direction of what I'm doing wrong?
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry(1,1,1);
var cube = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial( {color: 0x808080 } ));
cube.castShadow = true;
scene.add( cube );
camera.position.y = 2;
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( 0, 10, 0 );
directionalLight.castShadow = true;
scene.add( directionalLight );
var geo2 = new THREE.BoxGeometry(5,0.1,5);
var floor = new THREE.Mesh(geo2, new THREE.MeshLambertMaterial( {color: 0x808080 } ));
floor.position.y = -1;
floor.receiveShadow = true;
scene.add(floor);
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
var ambient = new THREE.AmbientLight( 0x111111 );
directionalLight.shadowCameraVisible = true;
scene.add( ambient );
renderer.shadowCameraNear = 3;
renderer.shadowCameraFar = camera.far;
renderer.shadowCameraFov = 50;
function animate() {
camera.lookAt({x:0,y:0,z:0});
var timer = Date.now() * 0.0002;
camera.position.x = Math.cos(timer) * 5;
camera.position.z = Math.sin(timer) * 5;
requestAnimationFrame(animate);
render();
}
function render() {
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
}
animate();
These three lines:
renderer.shadowCameraNear = 3;
renderer.shadowCameraFar = camera.far;
renderer.shadowCameraFov = 50;
should be on your light not the renderer; so
directionalLight.shadowCameraNear = 3;
directionalLight.shadowCameraFar = camera.far;
directionalLight.shadowCameraFov = 50;
and since your light is directional you will need:
directionalLight.shadowCameraLeft = -500;
directionalLight.shadowCameraRight = 500;
directionalLight.shadowCameraTop = 500;
directionalLight.shadowCameraBottom = -500;
and you might need to play around with these values.