I have the following Three.js code:
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script>
//Basic Three components
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 );
//Let´s add a cube
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
//Let´s add a text
var material2 = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
var textGeom = new THREE.TextGeometry( 'Sitescope', {
font: 'optimer',
weight: 'normal'
});
var textMesh = new THREE.Mesh( textGeom, material2 );
scene.add( textMesh );
//Render scene
function render() {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
render();
</script>
</body>
When i run my code, My cube renders well but my text does not appear anywhere.
The only output that i get in the javascript console is:
THREE.WebGLRenderer 69.
Could anyone tell me why my text does not appear? (I am a beginner in Three.js) Thanks!
When using a THREE.MeshPhongMaterial() you need a light in the scene. Otherwise the model will come out black. If your scene background is also black you will never know if the model was drawn or not. Take a look at this fiddle. I am using THREE.MeshNormalMaterial(). Replace it with PhongMaterial to see what I am talking about. You can see the text is being drawn with black color just because it is over the green cube.
Related
I'm starting on three.js and I'm already stuck on a trivial case : display an image on a sprite. I can only get a black plane following the lines written in the documentation:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>TEST Sprite</title>
<style>
body { margin: 0; background-color:#000; }
canvas { width: 100%; height: 100%; }
#glRender {
position:absolute;
top: 50px;
left: 200px;
min-width: 200px;
width: 50%;
min-height: 200px;
z-index: 1;
height: 50%;
border: 10px solid #38272C;
}
</style>
</head>
<body>
<div id="glRender"></div>
<script src="http://threejs.org/build/three.js"></script>
<script>
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 / 2, window.innerHeight / 2 );
container = document.getElementById( 'glRender' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
// A simple cube
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
// completely black...
var photoTexLoad = new THREE.TextureLoader().load( 'http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg' );
var matPhoto = new THREE.SpriteMaterial( { map: photoTexLoad, color: 0xffffff } );
var sprite = new THREE.Sprite( matPhoto );
sprite.scale.set( 2, 2, 2 );
sprite.position.set( 1, 0, 0.5 );
scene.add( sprite );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
cube.rotation.x += 0.01;
cube.rotation.y += 0.1;
renderer.render( scene, camera );
}
render();
</script>
</body>
</html>
I get the spinning green cube intersecting with a black plane.
What did I miss to have the image displayed on the plane?
.TextureLoader().load() is asynchronous. Trying to apply it immediately after invoking it leads to a black plane in your code most likely because the texture has not finished loading.
You can solve this by:
Passing a callback to .load as a 2nd parameter. (It is called once the texture has finished loading):
var matPhoto,
sprite,
texloader = new THREE.TextureLoader();
texloader.load('http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg',
function(tex) {
matPhoto = new THREE.SpriteMaterial( { map: tex, color: 0xffffff } );
sprite = new THREE.Sprite( matPhoto );
//...etc...
}
);
OR
set an event listener:
var texloader = new THREE.TextureLoader();
texloader.load('http://s2.favim.com/610/150817/plage-summer-Favim.com-3137863.jpg');
textureLoader.addEventListener('load', function(event){
// event.content holds the texture---------------v
matPhoto = new THREE.SpriteMaterial( { map: event.content, color: 0xffffff } ); = event.content;
});
I just found out I got the "CORS" issue highlighted in question three.js: texture goes all black
The code is working fine but I cannot try to load an image from external website or directly on my computer, only files on my localhost.
For testing, I now use a specific instance of google chrome using a desktop shortcut launching the browser as : "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --args --user-data-dir="C:/Chrome dev session" --disable-web-security
I'm very new to Three.JS and 3D web dev in general what I'm trying to do is mimic this action: https://www.youtube.com/watch?v=HWSTxPc8npk&feature=youtu.be&t=7s Essentially this is a set of 3D planes and upon click the whole stack reacts and gives space around the one that's clicked.
For now, my base case is 3 planes and figuring first out if I can click the the middle one, how do I get the others to jump back smoothly as if they were pushed rather than instant appear and disappear as they do now on the click of a button.
The long term goal is to have a separate button for every plane so that on click, the selected plane will have padding around it and the rest of the planes in stack move accordingly.
I've looked into Tween.js, and CSS3D but pretty overwhelmed as a newbie. Any tutorials or tips would be greatly appreciated!
// Our Javascript will go here.
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
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.PlaneGeometry( 3, 3, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var plane = new THREE.Mesh( geometry, material );
plane.rotation.y = -.7;
var material2 = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var material3 = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var plane2 = new THREE.Mesh(geometry, material2 );
plane2.rotation.y = -.7;
plane2.position.x = 1;
var plane3 = new THREE.Mesh(geometry, material3);
plane3.rotation.y = -.7;
plane3.position.x = -1;
scene.add( plane, plane2, plane3 );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
// cube.rotation.x += 0.1;
// cube.rotation.y += 0.1;
renderer.render( scene, camera );
}
render();
function clickFirst() {
TWEEN.removeAll();
var tween = new TWEEN.Tween(plane3.position).to({x: -2}, 1000).start();
tween.easing(TWEEN.Easing.Elastic.InOut);
render();
}
</script>
<button onclick="clickFirst();" style="background-color: white; z-index: 9999;">Click me</button>
First, you need to locate the 2 planes.
Second, you need to make the planes clickable:
https://threejs.org/examples/#webgl_interactive_cubes
https://github.com/josdirksen/learning-threejs/blob/master/chapter-09/02-selecting-objects.html
Third, you should use Tween.js for the transition.
after picking the right plane, make a tween for the other planes with a tween, all to move on the same Axis:
example:
createjs.Tween.get(plane3.position.z).to(
plane3.position.z + 100
, 1000, createjs.Ease.cubicOut)
If you will add some code here after starting to implement i would be able to help more.
I made a trial with basic scene of threejs but I can't understand why the canvas background is completely black.
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100%;background-color: white; }
</style>
</head>
<body>
<script src="Stereos/threejs/three.js"></script>
<script>
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 );
</script>
</body>
</html>
EDIT:
Code at felpone.netsons.org
The color of the background of the canvas is not determined by the CSS value but using renderer.setClearColor (0xff0000, 1);
You can control the background color using css, but you must first set the "alpha" of your WebGLRenderer to "true".
In you example, I added the alpha option and set to true in the renderer, and I also added the background-color property in the body style.
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; background-color: white; }
canvas { width: 100%; height: 100%; background-color: white; }
</style>
</head>
<body>
<script src="Stereos/threejs/three.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer( {alpha: true} );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
</script>
</body>
</html>
Better add the background to the scene directly which can be a texture or a THREE.Color!
From r78 versions onwards, you can use the code below to set your scene's background colour:
var scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
Docs:
Scene.background
You made a scene, created a camera and created a renderer, but you're missing two important things: adding something to render, and actually rendering it.
After your last line, add
var cube = new THREE.Mesh(
new THREE.CubeGeometry( 1,1,1 ),
new THREE.MeshNormalMaterial()
);
scene.add( cube );
camera.position.set( 2,2,2 );
camera.lookAt( cube.position );
renderer.render( scene, camera );
That will create a cube on the origin ( 0,0,0 ), with size 1 unit; place the camera a bit away from it and pointed at the cube; and then call the renderer to render the cube.
Updating this for the latest version of ThreeJS (2019) -
After you instantiate your scene using:
scene = new THREE.Scene();
You can then access the "background" property of this object and set the hex color like this:
scene.background = new THREE.Color(0xf5f5f5);
#Jaume Sanchez is the correct answer. Although the others answers are factual, I don't think that they answer what you where asking as a person new to threeJS. the var rendereris just a reference to your render target. your code does not draw anthing. You also do not have a camera in your scene to look at anything. Creating a scene a tutorial for getting started
If for some reason:
renderer.setClearColor(0xff0000, 1);
does not work, try this:
const renderer = new THREE.WebGLRenderer();
renderer.domElement.className = "domElement";
and in css add a selector:
.domElement {
background-color: red; /* any color */
}
i have an instance of dat.GUI. I added a "comboBox" to that instance to make a selection of possible values. When i run my app, the dat.GUI appears with the comboBox but there is a problem: I cannot change it's default value (my gui is frozen), here is my code:
<html>
<head>
<title>Stack Overflow</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/threex.dynamictexture.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
//Basic Three components
var scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000 );
//position camera
camera.position.z = 700;
//Set camera controls
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
//Set the renderer
var renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Set the lights
var light;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 1 );
scene.add( light );
//GUI
initGUI();
//Let's add a cube
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
var material = new THREE.MeshBasicMaterial( { color: 0x5484d3 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set(0,20,50)
scene.add( cube );
function initGUI(){ //HERE IS THE MEAT, I THINK
var LevelView = function() {
this.level = 'Operacion';
// Define render logic ...
};
var gui = new dat.GUI();
var text = new LevelView();
gui.add(text, 'level', [ 'Operacion', 'Procesos', 'Participantes', 'Fuentes de Datos', 'Logica de software', 'Telecomunicaciones', 'Infraestructura'] ).onChange(function(value){
this.level = value;
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
//Render scene
function render() {
controls.update();
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
¿What i am doing wrong? I need to be able to change values with my GUI.
Solution: If you use a mouse-controlled camera with three.js, you have to comment the following line in the MouseListener of the mouseDown action:
event.preventDefault();
Place div containing dat.gui element bellow Three.js div
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
and then dat.gui
<div id="gui"></div>
I am new in three.js and using the following code I want to know how to change the background by clicking a button. So I think there is something different than using "switch" and "break". Here is something with .loadTexture am I right?
<html lang="en">
<head>
<title>gyroscopic</title>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1">
<style>
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="three.min.js"></script>
<script src="DeviceOrientationControls.js"></script>
<script>
(function() {
"use strict"
window.addEventListener('load', function() {
var container, camera, scene, renderer, controls, geometry, mesh;
var animate = function(){
window.requestAnimationFrame( animate );
controls.update();
renderer.render(scene, camera);
};
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 1100);
controls = new THREE.DeviceOrientationControls( camera );
scene = new THREE.Scene();
var geometry = new THREE.SphereGeometry( 500, 316, 18 );
geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
var material = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture( 'pic.jpg' )
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var geometry = new THREE.BoxGeometry( 100, 100, 100, 4, 4, 4 );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;
container.appendChild(renderer.domElement);
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false);
animate();
}, false);
})();
</script>
</body>
</html>
You should be able to change the texture using .loadTexture on a button click listener.
So you would probably add something like this to your HTML:
<button id="change-background">Change Background</button>
Then in Javascript:
var backgroundButton = document.getElementById('change-background');
backgroundButton.addEventListener('click', function(){
material.map = THREE.ImageUtils.loadTexture('//new image path//');
});
You'll obviously need to replace the //new image path// with whatever URL you have for the new image.
The only question would be whether this updates the material on the mesh as well. I'm sure it does, but have no way of testing it at present.