How to avoid transparency overlap using threejs - javascript

I am using threejs to build a map application, and I need to make all building models translucent, but in this case, the transparent buildings will overlap, resulting in a confusing display effect, as shown in the following figure
Overlapping renderings
The effect I hope to achieve is similar to the example on mapboxgl, the nearby buildings can directly block the buildings behind, which is much more refreshing
Expected renderings
How can this be done?
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xcccccc );
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
scene.background = new THREE.Color( 0x4186D1 );
// scene.fog = new THREE.FogExp2( 0x4186D1, 0.002 );
scene.fog = new THREE.Fog( 0x4186D1, 800, 1800 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 400, 200, 0 );
// controls
controls = new MapControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 100;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;
// world
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
geometry.translate( 0, 0.5, 0 );
const material = new THREE.MeshPhongMaterial( { color: 0xffffff, transparent: true, opacity: 0.7, flatShading: true } );
for ( let i = 0; i < 500; i ++ ) {
const mesh = new THREE.Mesh( geometry, material );
mesh.position.x = Math.random() * 1600 - 800;
mesh.position.y = 0;
mesh.position.z = Math.random() * 1600 - 800;
mesh.scale.x = 20;
mesh.scale.y = Math.random() * 80 + 10;
mesh.scale.z = 20;
mesh.updateMatrix();
mesh.matrixAutoUpdate = false;
scene.add( mesh );
}
// lights
const dirLight1 = new THREE.DirectionalLight( 0xffffff );
dirLight1.position.set( 1, 1, 1 );
scene.add( dirLight1 );
const dirLight2 = new THREE.DirectionalLight( 0x002288 );
dirLight2.position.set( - 1, - 1, - 1 );
scene.add( dirLight2 );
const ambientLight = new THREE.AmbientLight( 0x222222 );
scene.add( ambientLight );
//
window.addEventListener( 'resize', onWindowResize );
const gui = new GUI();
gui.add( controls, 'screenSpacePanning' );

Related

Three.js duplicates objects shape but uses new color with ColladaLoader and STLLoader

I need to load collada and STL models stored in files to the same scene. I do this with three.js framework with a standard ColladaLoader() and STLLoader() like in the linked examples.
The first object appears correctly, but the second repeats its shape in the color of the second object.
I don't understand why. Where can be the problem?
UPD
var sloader = new STLLoader();
sloader.load( 'models/m1.stl', function ( geometry ) {
var meshMaterial = new THREE.MeshPhongMaterial( { color: 0xAAAAAA, specular: 0x111111, shininess: 200 } );
if ( geometry.hasColors ) {
meshMaterial = new THREE.MeshPhongMaterial( { opacity: geometry.alpha, vertexColors: THREE.VertexColors } );
}
var mesh = new THREE.Mesh( geometry, meshMaterial );
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
});
var tmploader = new ColladaLoader();
tmploader.load('models/m2.dae',
function (geometry) {
var robot = geometry.scene;
var meshMaterial = new THREE.MeshPhongMaterial();
robot.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.material = meshMaterial;
}
});
//robot = new THREE.Mesh( geometry, meshMaterial );
scene.add(robot);
});
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera.position.set( -10, 10, -10);
camera.lookAt( 0, 3, 0 );
scene = new THREE.Scene();
// lights
var light = new THREE.AmbientLight( 0x404040, 1.0 ); // soft white light
scene.add( light );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.0 );
directionalLight.position.set( 1, 1, -1 ).normalize();
scene.add( directionalLight );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

Threejs: WebGL 3D text to three.js ocean scene

I'm working with the three.js ocean scene and 3D canvas text. The 3D text is suppose to replace the location of the ball, but the text doesn't appear.
When I inspect elements, I only notice the canvas for the background rendering. How can both canvases- the background and 3D text- appear? How can I overlay a canvas on another?
What is another way to have 3D text over the water without using canvas or canvasrenderer.js for the 3D text?
Original code for Canvas 3D Text: https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_text.html
JavaScript to combine both elements:
var container, stats;
var camera, scene, renderer;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;
var group;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var loader = new THREE.FontLoader();
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
} );
init();
animate();
function init( font ) {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 150, 500 );
scene = new THREE.Scene();
// Get text from hash
var theText = "three.js";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
theText = hash;
}
var geometry0 = new THREE.TextGeometry( theText, {
font: font,
size: 80,
height: 20,
curveSegments: 2
});
geometry.computeBoundingBox();
var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
var material0 = new THREE.MultiMaterial( [
new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
] );
var mesh = new THREE.Mesh( geometry0, material0 );
mesh.position.x = centerOffset;
mesh.position.y = 100;
mesh.position.z = 50;
group = new THREE.Group();
group.add( mesh );
scene.add( group );
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 750, 2000 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enablePan = false;
controls.minDistance = 1000.0;
controls.maxDistance = 5000.0;
controls.maxPolarAngle = Math.PI * 0.495;
controls.target.set( 0, 500, 0 );
scene.add( new THREE.AmbientLight( 0x444444 ) );
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);
mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
// load skybox
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;
var loader = new THREE.ImageLoader();
loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {
var getSide = function ( x, y ) {
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
};
cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;
} );
var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
var geometry = new THREE.IcosahedronGeometry( 400, 4 );
for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
var material = new THREE.MeshPhongMaterial( {
vertexColors: THREE.FaceColors,
shininess: 100,
envMap: cubeMap
} );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
water.material.uniforms.time.value += 1.0 / 60.0;
controls.update();
water.render();
renderer.render( scene, camera );
}
The first thing i notice is that you are calling the init(); animate(); functions before the loader has a chance to load the font ( and because of that you are not passing the font into the init function like the canvas_geometry_text example ).
I've pasted the code from the ocean example below ( with comments for how I modified it to work with the code from the canvas_geometry_text example ). I've tested this and it works
var container, stats;
var camera, scene, renderer;
var sphere;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;
// 1.
// copy+paste this code from the canvas_geometry_text file
var loader = new THREE.FontLoader();
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
init( font );
animate();
} );
// 2.
// comment out these calls to init() and animate()
// these will be called in the loader's callback above instead
// init();
// animate();
// add 'font' parameter to init
function init( font ) {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 750, 2000 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enablePan = false;
controls.minDistance = 1000.0;
controls.maxDistance = 5000.0;
controls.maxPolarAngle = Math.PI * 0.495;
controls.target.set( 0, 500, 0 );
scene.add( new THREE.AmbientLight( 0x444444 ) );
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
waterNormals = new THREE.TextureLoader().load( 'textures/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);
mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
// load skybox
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;
var loader = new THREE.ImageLoader();
loader.load( 'textures/skyboxsun25degtest.png', function ( image ) {
var getSide = function ( x, y ) {
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
};
cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;
} );
var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
// 3.
// comment out all the sphere mesh code
// var geometry = new THREE.IcosahedronGeometry( 400, 4 );
// for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
// geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
// }
// var material = new THREE.MeshPhongMaterial( {
// vertexColors: THREE.FaceColors,
// shininess: 100,
// envMap: cubeMap
// } );
// sphere = new THREE.Mesh( geometry, material );
// scene.add( sphere );
// 4.
// copy+paste the text mesh code from canvas_geometry_text
var theText = "Hello three.js! :)";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
theText = hash;
}
var geometry = new THREE.TextGeometry( theText, {
font: font,
size: 80,
height: 20,
curveSegments: 2
});
geometry.computeBoundingBox();
var centerOffset = -0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
var material = new THREE.MultiMaterial( [
new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } ),
new THREE.MeshBasicMaterial( { color: 0x000000, overdraw: 0.5 } )
] );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = centerOffset;
mesh.position.y = 100;
mesh.position.z = 0;
mesh.rotation.x = 0;
mesh.rotation.y = Math.PI * 2;
group = new THREE.Group();
group.add( mesh );
scene.add( group );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var time = performance.now() * 0.001;
// 6.
// comment out the sphere animation code
// sphere.position.y = Math.sin( time ) * 500 + 250;
// sphere.rotation.x = time * 0.5;
// sphere.rotation.z = time * 0.51;
// 7.
// copy+paste the sphere animation code above
// but replace 'sphere' with 'group'
group.position.y = Math.sin( time ) * 500 + 250;
group.rotation.x = time * 0.5;
group.rotation.z = time * 0.51;
water.material.uniforms.time.value += 1.0 / 60.0;
controls.update();
water.render();
renderer.render( scene, camera );
}

How to show a cube map reflection on a object without showing the cubemap in the background?

How to show a cube map reflection on a object without showing the cubemap in the background?
I like to receive a reflection on a lever mechanism without showing a cubemap in the background. The background should be with a gradient from blue to white.
So basicially, the cubemap should be only visible on the object.
Thank you very much in advance!
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var loader;
var camera, cameraTarget, controls, scene, renderer;
init();
animate();
function init() {
var previewDiv = document.getElementById("preview");
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 );
camera.position.set( 3, 0.15, 3 );
cameraTarget = new THREE.Vector3( 0, -0.25, 0 );
controls = new THREE.OrbitControls( camera );
controls.maxPolarAngle = Math.PI / 2.2;
controls.minDistance = 3;
controls.maxDistance = 8;
// controls.noPan = true;
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xdae1e6, 2, 15 );
// Ground
var plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 40, 40 ),
new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
);
plane.rotation.x = -Math.PI/2;
plane.position.y = -0.5;
scene.add( plane );
plane.receiveShadow = true;
// feinleinen
var feinleinen = THREE.ImageUtils.loadTexture( 'textures/feinleinen.jpg' );
feinleinen.anisotropy = 1;
feinleinen.wrapS = feinleinen.wrapT = THREE.RepeatWrapping;
feinleinen.repeat.set( 5, 5 );
// create a cube
var basisGeometry = new THREE.BoxGeometry(3,0.02,3);
var basisMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, map: feinleinen } );
var basis = new THREE.Mesh(basisGeometry, basisMaterial);
basis.castShadow = false;
basis.receiveShadow = true;
// position the cube
basis.position.set( 0, -0.47, 0 );
// add the cube to the scene
scene.add(basis);
var loader = new THREE.JSONLoader();
loader.load('/models/hebelmechanik.js', function(geo, mat){
var chrome = new THREE.MeshLambertMaterial( { ambient: 0x444444, color: 0x111111, shininess: 800, specular: 0x111111, shading: THREE.SmoothShading, reflectivity: 1.1 } );
var mesh = new THREE.Mesh(geo, chrome);
mesh.position.set( 0, - 0.497, 0 );
mesh.rotation.set( 0, - Math.PI / 2, 0 );
mesh.scale.set( 0.008, 0.008, 0.008 );
mesh.castShadow = true;
mesh.receiveShadow = true;
loadJson(mesh );
});
function loadJson(mesh){
scene.add( mesh );
}
// Lights
scene.add( new THREE.AmbientLight( 0x777777 ) );
addShadowedLight( 1, 1, 1, 0xffffff, 1.35 );
addShadowedLight( 0.5, 1, -1, 0xffffff, 1 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapCullFace = THREE.CullFaceBack;
previewDiv.appendChild (renderer.domElement);
// resize
window.addEventListener( 'resize', onWindowResize, false );
}
function addShadowedLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
directionalLight.castShadow = true;
// directionalLight.shadowCameraVisible = true;
var d = 1;
directionalLight.shadowCameraLeft = -d;
directionalLight.shadowCameraRight = d;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 1;
directionalLight.shadowCameraFar = 4;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.lookAt( cameraTarget );
controls.update();
renderer.render( scene, camera );
}
</script>
You can add a cubemap reflection to your model by specifying the envMap property of the model's material.
Use a pattern like this one:
var path = "textures/cube/foo/";
var format = '.png';
var urls = [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
];
var envMap = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping, callback ); // callback function is optional
var material = new THREE.MeshPhongMaterial( {
color : 0x999999,
specular : 0x050505,
shininess : 50,
envMap : envMap,
combine : THREE.MixOperation, // or THREE.AddOperation, THREE.MultiplyOperation
reflectivity : 0.5
} );
three.js r.71

Three.js reflective plane with cubeCamera & texture

I'm trying to create a simple plane which will combine a texture and a cubeCamera reflection and I'm failing and I'm not sure what to do next?
If I swap the envMap on the plane material to a simple jpg/png texturecube then it will work fine, but this is not what I want.
My goal is to create a glossy reflective plane with a texture that will be replicated to create a room and reflect any 3d meshes inside the room.
Here is what I have so far.
var scene, camera, cameraCube, renderer;
var light1, light2;
var wallMesh;
var init = function(){
// scene
scene = new THREE.Scene();
// cameras
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.set(0,50000,50000);
cameraCube = new THREE.CubeCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
cameraCube.renderTarget.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cameraCube)
// textureCube just for test
// var path = "http://three.dev/cortana/textures/";
// var format = '.png';
// var urls = [
// path + 'px' + format, path + 'nx' + format,
// path + 'py' + format, path + 'ny' + format,
// path + 'pz' + format, path + 'nz' + format
// ];
// var textureCube = THREE.ImageUtils.loadTextureCube( urls );
var texture = THREE.ImageUtils.loadTexture( 'http://three.dev/various/textures/white.png' );
// room
var plane = new THREE.PlaneBufferGeometry( 50000, 50000 );
var wallMaterial = new THREE.MeshLambertMaterial( {
color: 0x333333,
ambient: 0xdddddd,
map: texture,
envMap: cameraCube.renderTarget,
combine: THREE.MixOperation,
reflectivity: 0.5
} );
var wallMaterial = new THREE.MeshBasicMaterial({
envMap: cameraCube.renderTarget,
})
wallMesh = new THREE.Mesh( plane, wallMaterial );
wallMesh.rotateX(toRadians(-90));
wallMesh.position.set(0,-250,0);
scene.add( wallMesh );
// sphere
var sphereGeometry = new THREE.SphereGeometry( 100, 64, 64 );
var sphereMaterial = new THREE.MeshPhongMaterial( { ambient: 0x111111, color: 0x111111, specular: 0x333333, shininess: 50, shading: THREE.SmoothShading });
var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
sphere.scale.x = sphere.scale.y = sphere.scale.z = 20;
sphere.position.set( 0, 2000, 0 );
scene.add(sphere);
// lights
var ambient = new THREE.AmbientLight(0xffffff);
scene.add( ambient );
var directionalLight1 = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight1.position.set( 0, 50000, 0 ).normalize();
scene.add( directionalLight1 );
var color = new THREE.Color("rgb(0,255,0)");
light2 = new THREE.PointLight(color, 1, 50000);
light2.position.set(2000,500,2000);
scene.add( light2 );
// renderer
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setClearColor( 0xffffff, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.autoClear = false;
document.getElementsByTagName('body')[0].appendChild( renderer.domElement );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.rotateSpeed = 0.5;
controls.minDistance = 1000;
controls.maxDistance = 50000;
controls.minPolarAngle = 0;
controls.maxPolarAngle = toRadians(90)
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
cameraCube.aspect = window.innerWidth / window.innerHeight;
cameraCube.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
controls.update();
//camera.lookAt( scene.position );
//cameraCube.rotation.copy( camera.rotation );
//renderer.render( scene, cameraCube );
wallMesh.visible = false;
cameraCube.updateCubeMap(renderer, scene);
wallMesh.visible = true;
renderer.render( scene, camera );
}
window.onload = function(){
init();
animate();
}

Three.js skybox seems broken after rotating camera

js and I'm trying to create a simple skybox based on this demo. Everything seems ok so far except 1 thing when I rotate my camera (I'm using orbitControls.js) and the z value is not the minimum possible then textures act weird and seem broken.
Source:
var camera, scene, renderer, controls, skybox;
var toRadians = function(deg) {
return deg * Math.PI / 180
}
var toDegrees = function(radians) {
return radians * (180 / Math.PI);
}
var init = function() {
// scene
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xffffff, 0.00010);
// camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.z = 5000;
scene.add( camera );
// skydome
var urlPrefix = "http://three.dev/skybox/textures/";
var urls = [urlPrefix + "px.png", urlPrefix + "nx.png",
urlPrefix + "py.png", urlPrefix + "ny.png",
urlPrefix + "pz.png", urlPrefix + "nz.png"];
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
var shader = THREE.ShaderLib[ "cube" ];
shader.uniforms[ "tCube" ].value = textureCube;
var material = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
} ),
skybox = new THREE.Mesh( new THREE.BoxGeometry( 10000, 10000, 10000 ), material );
scene.add( skybox );
//var texture = THREE.ImageUtils.loadTexture( 'http://three.dev/skybox/textures/wood.jpg')
//var paintMaterial = new THREE.MeshBasicMaterial({map: textureCube})
// var lightAmb = new THREE.AmbientLight(0x333333);
// lightAmb.position.set( 0,0,0 );
// scene.add(lightAmb);
// var directionalLightTop = new THREE.DirectionalLight( 0xffffff, 1 );
// directionalLightTop.position.set( 0, 0, 0 ).normalize();
// scene.add( directionalLightTop );
// var color = new THREE.Color("rgb(255,0,0)");
// var pointLightRed = new THREE.PointLight(color, 1, 8000);
// pointLightRed.position.set( 0, 0, 0);
// camera.add( pointLightRed );
// renderer
renderer = new THREE.WebGLRenderer( {alpha: true, antialias: true} );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
renderer.autoClear = false;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.rotateSpeed = 0.5;
controls.minDistance = 500;
controls.maxDistance = 6000;
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// start rendering
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
var update = function() {
}
var render = function() {
update();
controls.update();
requestAnimationFrame( render );
renderer.render(scene, camera);
}
window.onload = function(){
init();
}
You're adding a skybox in the 'main' scene. A better way to accomplish a skydome would be to create a new scene. this will be the 'background' to your 'main' scene. There's also a discussion about skydomes v.s. skyboxes, simply put, a box saves polys, a dome looks better. in this example i'll be using a dome/sphere.
var renderer = new THREE.WebGLRenderer( {alpha: true, antialias: true} );
var mainScene = new THREE.Scene();
var mainCamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
var skydome = {
scene: new THREE.Scene(),
camera: new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
};
skydome.material = new THREE.MeshBasicMaterial({color: 0x0F0F0F}) //the material for the skydome, for sake of lazyness i took a MeshBasicMaterial.
skydome.mesh = new THREE.Mesh(new THREE.SphereGeometry(100, 20, 20), skydome.material);
skydome.scene.add(skydome.mesh);
now, during the render function you adjust only the rotation of the skydome camera, not the position.
var render = function(){
requestAnimationFrame( render );
skydome.camera.quaternion = mainCamera.quaternion;
renderer.render(skydome.scene, skydome.camera); //first render the skydome
renderer.render(mainScene, mainCamera);//then render the rest over the skydome
};
renderer.autoclear = false; //otherwise only the main scene will be rendered.

Categories