ShaderMaterial not work with MeshFaceMaterial - three.js

I use ShaderMaterial to create real material for my cube. But it not works well. As can see, only first face work well. Even when i use different texture for different faces, it not works. I don't know what is problem with my code.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Test_material</title>
<style type="text/css" media="all">
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<div id='container'></div>
<script type="text/javascript" src="js/threejs/Three.js">
</script>
<script type="text/javascript" src="js/lib/util.js">
</script>
<script type="text/javascript" src="js/threejs/TrackballControls.js"></script>
<script>
var WIDTH= 400;
var HEIGHT = 400;
var container = document.getElementById('container');
var camera =new THREE.PerspectiveCamera(25, WIDTH/HEIGHT, 1, 10000);
camera.position.set(0,300,100);
var animate;
var scene = new THREE.Scene();
scene.add(camera);
camera.lookAt(scene.position);
var controls = new THREE.TrackballControls(camera);
//custom shape
materialArr = [];
var data = new utils.Storage.ResourceStorage();
data.load({
'textures': {
'track_normal_0' : 'images/pattern/track_normal_0.jpg',
'track_diffuse_0' : 'images/pattern/track_diffuse_0.jpg',
'track_specular_0' : 'images/pattern/track_specular_0.jpg',
'track_normal_0' : 'images/pattern/track_normal_0.jpg',
'track_diffuse_0' : 'images/pattern/track_diffuse_0.jpg',
'track_specular_0' : 'images/pattern/track_specular_0.jpg',
'track_normal_1' : 'images/pattern/track_normal_1.jpg',
'track_diffuse_1' : 'images/pattern/track_diffuse_1.jpg',
'track_specular_1' : 'images/pattern/track_specular_1.jpg',
'track_normal_2' : 'images/pattern/track_normal_2.jpg',
'track_diffuse_2' : 'images/pattern/track_diffuse_2.jpg',
'track_specular_2' : 'images/pattern/track_specular_2.jpg',
'track_normal_3' : 'images/pattern/track_normal_3.jpg',
'track_diffuse_3' : 'images/pattern/track_diffuse_3.jpg',
'track_specular_3' : 'images/pattern/track_specular_3.jpg',
'track_normal_4' : 'images/pattern/track_normal_4.jpg',
'track_diffuse_4' : 'images/pattern/track_diffuse_4.jpg',
'track_specular_4' : 'images/pattern/track_specular_4.jpg',
'track_normal_5' : 'images/pattern/track_normal_5.jpg',
'track_diffuse_5' : 'images/pattern/track_diffuse_5.jpg',
'track_specular_5' : 'images/pattern/track_specular_5.jpg',
},
'onReady': init
});
function init(){
var materialArr = [];
for (var i=0; i< 6; i++){
var shader = THREE.ShaderLib['normalmap'];
var normalTexture = data.getTexture('track_normal_' + i).clone();
normalTexture.needsUpdate = true;
var diffuseTexture = data.getTexture('track_diffuse_' + i);
diffuseTexture.needsUpdate = true;
var specularTexture = data.getTexture('track_specular_' + i);
specularTexture.needsUpdate = true;
var uniforms = THREE.UniformsUtils.clone(shader.uniforms);
uniforms['tNormal'].value = normalTexture;
uniforms['tDiffuse'].value = diffuseTexture;
uniforms['tSpecular'].value = specularTexture;
uniforms['enableDiffuse'].value = true;
uniforms['enableSpecular'].value = true;
uniforms['uSpecularColor'].value.setHex(0x00cc00);
uniforms['uDiffuseColor'].value.setHex(0x0000ff);
<!--uniforms['uShininess'].value = 100;-->
var material = new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader + " ",
uniforms: uniforms,
lights: true
});
material.perPixel = true;
material.needsUpdate = true;
materialArr.push(material);
}
var geometry = new THREE.CubeGeometry(40, 40, 40);
geometry.computeTangents();
var material = new THREE.MeshFaceMaterial(materialArr);
for (var i=0; i< material.materials.length; i++){
material.materials[i].needsUpdate = true;
}
mesh =new THREE.Mesh(geometry, material);
scene.add(mesh);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(WIDTH, HEIGHT);
container.appendChild(renderer.domElement);
var dirLight = new THREE.DirectionalLight(0xffffff);
scene.add(dirLight);
var ambientLight = new THREE.AmbientLight(0xcddacc);
scene.add(ambientLight);
renderer.render(scene, camera);
animate = function (){
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
}
</script>
</body>
</html>
My result

I would suggest using a single material and tweaking the UVs of the geometry instead. Take a look at the minecraft example to see how to do that.

Related

Why aren't any texture on .obj-s? (Three.js)

I am working on an anatomy application based on three.js. Recently I am trying to visualize a skeleton and an ecorche model. Both of us are .obj-s with an .mtl file and there are jpeg files as textures. My problem is that my app visualize the two models but on the ecorche the are no textures and the skeleton is black. The problem is somewhere in the obj and mtl loader. I guess there is also an easier way to load the models.
The files of a model is in a separate folder.
My other question is how I can manage to make a button that change the actual model to the other one.
Thank you for your help!
Here is the code:
if (!Detector.webgl) {
Detector.addGetWebGLMessage();
}
var container;
var camera, controls, scene, renderer;
var lighting, ambient, keyLight, fillLight, backLight;
var windowDivideX = window.innerWidth / 3.4;
var files=['WorkAlpha.obj','untitled.mtl'];
init();
animate();
function init() {
container = document.createElement('viewer');
document.body.appendChild(container);
/*Creating Camera*/
camera = new THREE.PerspectiveCamera(45, windowDivideX /
window.innerHeight, 1, 100);
camera.position.y = 0;
camera.position.z = 40;
camera.position.x = 0;
/* Scene and Lights */
scene = new THREE.Scene();
lighting = false;
ambient = new THREE.AmbientLight(0xEAE1EA, 0.3);
scene.add(ambient);
keyLight = new THREE.DirectionalLight(0xEAE1EA, 0.6);
//(new THREE.Color('hsl(30, 80%, 0%)'), 1.0);
keyLight.position.set(-100, 0, 100);
fillLight = new THREE.DirectionalLight(0xEAE1EA, 0.6);
//(new THREE.Color('hsl(30, 80%, 0%)'), 0.6);
fillLight.position.set(100, 0, 100);
backLight = new THREE.DirectionalLight(0xffffff, 0.6);
backLight.position.set(100, 0, -100).normalize();
//ambient.intensity = 0.1;
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
/////////////////////////////////////////////////////////////////////////
/* Model */
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl('assets/');
mtlLoader.setPath('assets/');
mtlLoader.load(files [0], function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('WorkAlpha.obj', function (object) {
object.position.y = 3;object.position.x = 0;
object.position.z = 0;
object.name = "muscles";
scene.add(object);
});
});
mtlLoader.setBaseUrl('skeleton/');
mtlLoader.setPath('skeleton/');
mtlLoader.load(files[1], function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('skeleton/');
objLoader.load('untitled.obj', function (object) {
object.position.y = -15;object.position.x = 0;
object.position.z = 0;
object.name = "skeleton";
scene.add(object);
});
});
/* Renderer */
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(windowDivideX, window.innerHeight);
renderer.setClearColor(0xC9D2D3);
container.appendChild(renderer.domElement);
/* Controls */
controls = new THREE.OrbitControls(camera,
renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
controls.maxPolarAngle = Math.PI/2;
/* Events */
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('keydown', onKeyboardEvent, false);
}
function onWindowResize() {
camera.aspect = windowDivideX / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(windowDivideX, window.innerHeight);
}
function onKeyboardEvent(e) {
if (e.code === 'KeyL') {
lighting = !lighting;
if (lighting) {
ambient.intensity = 0.25;
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
} else {
ambient.intensity = 1.0;
scene.remove(keyLight);
scene.remove(fillLight);
scene.remove(backLight);
}
}
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
Here you can see the HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="three.js"></script>
<script src="Detector.js"></script>
<script src="OrbitControls.js"></script>
<script src="OBJLoader.js"></script>
<script src="MTLLoader.js"></script>
<script src="TrackballControls.js"></script>
<script
src="https://threejs.org/examples/js/renderers/Projector.js">
</script>
<script
src="https://threejs.org/examples/js/renderers/CanvasRenderer.js">
</script>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="design.css">
</head>
<body>
<script src="3d.js"></script>
</body>
</html>

Three.js Updating DataTextures with a renderTarget's image data

I am working on a motion detection program in Three.js which uses the difference between the current and previous frame. For now, before the subtraction, the current and the previous frame are both blurred using a Three.EffectComposer each.
The main problem is: Instead of having to blur the previous frame again, I want to use the previously blurred "current" frame as the texture in the subtraction process.
The closest I have managed to do is by using the function below to update the image.data of the Three.DataTexture. It was used in the render()-function after the Blurring composer is rendered, but before the subtraction is rendered.
Both of them were rendered to the screen with Three.CopyShader.
function getData(image) {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return new Uint8Array(context.getImageData(0, 0, image.width, image.height).data);
}
Where the “image” is the renderer.domElement. This method feels quite inefficient and I needed to render the Blur-pass to the screen, which caused the result to flicker.
Edit 1 The current code is shown below, it blurs the current and previous images and then calculates the difference. The animate()-function is the point of interest.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Three.js Webcam Test</title>
<meta charset="utf-8">
<!-- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="lib/three.min.js"></script>
<!-- Effect composer scripts -->
<script src = "postprocessing/EffectComposer.js"></script>
<script src = "postprocessing/MaskPass.js"></script>
<script src = "postprocessing/RenderPass.js"></script>
<script src = "postprocessing/TexturePass.js"></script>
<script src = "postprocessing/ShaderPass.js"></script>
<script src = "postprocessing/SavePass.js"></script>
<script src = "shaders/CopyShader.js"></script>
<script src = "shaders/ColorifyShader.js"></script>
<script src = "shaders/DilationShader.js"></script>
<script src = "shaders/ErosionShader.js"></script>
<script src = "shaders/HorizontalBlurShader.js"></script>
<script src = "shaders/VerticalBlurShader.js"></script>
<script src = "shaders/BlendShader.js"></script>
<script src = "shaders/passThroughShader.js"></script>
<script src = "shaders/framediffShader.js"></script>
<script src = "shaders/PawaskarPostShader.js"></script>
<!-- ----------------------- -->
<script src="lib/Projector.js"></script>
<script src="lib/CanvasRenderer.js"></script>
<script src="lib/webcam.js"></script>
<script src="lib/perspective.js"></script>
<script src="lib/stats.min.js"></script>
<script src="lib/rStats.js"></script>
<script src="lib/rStats.extras.js"></script>
<script type="text/javascript" src="lib/dat.gui.min.js"></script>
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="http://bootswatch.com/lumen/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Motion Detection (in progress)</h1>
<p>Press P to print the current frame</p>
<div id="WebGL-output">
</div>
<div id="camera" class="camera">
<div class="label"></div>
<video id="theVideo" autoplay width="640" height="480" class="webcam"></video>
<canvas id="theCanvas" width="640" height="480" class="hidden"></canvas>
</div>
<script>
var SCREEN_HEIGHT = 480;
var SCREEN_WIDTH = 640;
var values = {
detectmotion: true,
softness: 0.17,
threshold: 0.11,
color: "#ffae23",
usecolor: false,
postprocess: false,
postprocessmethod: 0,
preprocess: true,
detectedges: false,
framedifference: false,
binarydifference: false,
bufferlength: 1
};
var stats, container, video, renderer, currTexture, uniforms, camera, scene, prevTexture, prevTexture2, prevTexture3, prevTextureBuffer = [], bufferLenght,
videoContext,
prevTime;
var rS, glS, tS;
var postProcessFilters = [];
var prepScene, prepRenderTarget, prepComposer, prepPrevComposer, hBlur, vBlur, temporalShader, prevTemporalShader, prevBlur;
var modelScene, modelRenderTarget, modelComposer, passShader;
var subtractScene, subtractRenderTarget,subtractComposer, subtractShader;
//GUI variables
var gui, cPostProcessMethod, doPostProcess = false;
var frameNumber;
/** TEST **/
var BlurSave;
function init(){
frameNumber = 0;
/* INIT */
scene = new THREE.Scene();
camera = new THREE.Camera();
scene.add(camera);
webcam.updateSources(function(s){
webcam.start('theVideo',s[0]);
});
var size = SCREEN_WIDTH * SCREEN_HEIGHT;
video = document.getElementById( 'theVideo' );
videoContext = document.getElementById('theCanvas').getContext('2d');
//The textures
currTexture = new THREE.DataTexture([],SCREEN_WIDTH,SCREEN_HEIGHT);
prevTexture = new THREE.DataTexture([],SCREEN_WIDTH,SCREEN_HEIGHT);
prevBlur = new THREE.DataTexture([], SCREEN_WIDTH, SCREEN_HEIGHT);
currTexture.minFilter = prevTexture.minFilter = prevBlur.minFilter= THREE.LinearFilter;
prevTime = -1;
renderer = new THREE.WebGLRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.domElement.width = SCREEN_WIDTH;
renderer.domElement.height = SCREEN_HEIGHT;
renderer.autoClear = false;
document.body.insertBefore(renderer.domElement, document.body.childNodes[0]);
uniforms = {
currentTexture: { type: "t", value: currTexture },
mirrorImage: { type: "i", value: 0}
}
var geometry = new THREE.PlaneBufferGeometry(1, 1);
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: THREE.passThroughShader.vertexShader,
fragmentShader: THREE.passThroughShader.fragmentShader
} );
// A plane with the current video context as texture
var mesh = new THREE.Mesh(geometry,material);
mesh.material.depthTest = false;
mesh.material.depthWrite = false;
scene.add(mesh);
// COPY SHADER, used to render the current context to the screen
var effectCopy = new THREE.ShaderPass(THREE.CopyShader);
effectCopy.renderToScreen = true;
/** Preprocess stage **/
prepScene = new THREE.Scene();
prepScene.add( new THREE.AmbientLight( 0xffffff ) );
prepScene.add(mesh) // add the current quad
var renderTargetParameters = {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false};
//blur shaders
hBlur = new THREE.ShaderPass(THREE.HorizontalBlurShader);
hBlur.uniforms["h"].value = 1 / SCREEN_WIDTH;
hBlur.enabled = values['preprocess'];
vBlur = new THREE.ShaderPass(THREE.VerticalBlurShader);
vBlur.uniforms["v"].value = 1 / SCREEN_HEIGHT;
vBlur.enabled = values['preprocess'];
BlurSave = new THREE.SavePass(new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters));
//preprocess scene render pass
var renderModelPrep = new THREE.RenderPass(prepScene, camera);
var prevPassShader1 = new THREE.ShaderPass(THREE.passThroughShader);
prevPassShader1.uniforms["mirrorImage"].value = 1;
//Preprocess of the current image
//It is this prepComposer's rendertarget value I want to use in the next loop
prepComposer = new THREE.EffectComposer(renderer, new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters));
prepComposer.addPass(renderModelPrep);
prepComposer.addPass(prevPassShader1);
prepComposer.addPass(hBlur);
prepComposer.addPass(vBlur);
prepComposer.addPass(BlurSave);
//
// subtractComposer.addPass(effectCopy);
//Preprocess of the previous image
//Want to skip this stage
var prevPassShader = new THREE.ShaderPass(THREE.passThroughShader, prevTexture);
prevPassShader.uniforms["currentTexture"].value = prevTexture;
prevPassShader.uniforms["mirrorImage"].value = 1;
var prevBlurSave = new THREE.SavePass(new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters));
prepPrevComposer = new THREE.EffectComposer(renderer, new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters));
prepPrevComposer.addPass(renderModelPrep);
prepPrevComposer.addPass(prevPassShader);
prepPrevComposer.addPass(hBlur);
prepPrevComposer.addPass(vBlur);
prepPrevComposer.addPass(prevBlurSave);
/**------------------**/
/**---------------------------**/
/** Background Subtraction stage **/
subtractScene = new THREE.Scene();
subtractScene.add( new THREE.AmbientLight( 0xffffff ) );
var renderTargetParameters3 = {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: false};
//Background Subtraction shaders
subtractShader = new THREE.ShaderPass(THREE.framediffShader);
subtractShader.uniforms['currentTexture'].value = BlurSave.renderTarget; // from the preprocess
subtractShader.uniforms['previousTexture'].value = prevBlurSave.renderTarget; //modelled background
//Background subtraction scene render pass
var renderSubtract = new THREE.RenderPass(subtractScene, camera);
//Background subtraction Composer
subtractComposer = new THREE.EffectComposer(renderer, new THREE.WebGLRenderTarget(SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters3));
subtractComposer.addPass(renderSubtract);
subtractComposer.addPass(subtractShader);
//subtractComposer.addPass(effectCopy2);
/**------------------------------**/
/** Postprocessing stage **/
//Dilation
var dilationFilter = new THREE.ShaderPass(THREE.DilationShader);
dilationFilter.enabled = values['postprocess'];
postProcessFilters.push(dilationFilter);
//Erosion
var erosionFilter = new THREE.ShaderPass(THREE.ErosionShader);
erosionFilter.enabled = values['postprocess'];
postProcessFilters.push(erosionFilter);
//Pawaskar's postprocess filter
var pawaskarFilter = new THREE.ShaderPass(THREE.PawaskarPostShader);
pawaskarFilter.uniforms['threshold'].value = values['threshold'];
pawaskarFilter.enabled = values['postprocess'];
postProcessFilters.push(pawaskarFilter);
subtractComposer.addPass(pawaskarFilter);
//Opening
subtractComposer.addPass(erosionFilter);
subtractComposer.addPass(dilationFilter);
//Closing
subtractComposer.addPass(dilationFilter);
subtractComposer.addPass(erosionFilter);
//The final result rendered to the screen
subtractComposer.addPass(effectCopy);
/**----------------------**/
animate();
}
function animate()
{
if(video.readyState === video.HAVE_ENOUGH_DATA ){
var time = video.currentTime;
if(time !== prevTime){
//Because a firefox bug when drawImage is used, need to catch NS_ERROR_NOT_AVAILABLE
try {
videoContext.drawImage(video, 0, 0,SCREEN_WIDTH,SCREEN_HEIGHT); //update the video
if(currTexture.image.data.length){
//var imgData = getData(renderer.domElement);
//var imgData = renderer.domElement.toDataURL();
// var gl = renderer.getContext();
//gl.readPixels( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, gl.RGBA, gl.UNSIGNED_BYTE, prevBlur.image.data );
//prevBlur.image.data = imgData;
// prevBlur.needsUpdate = true;
/** I want to update the prevBlur texture with the BlurSave.renderTarget! **/
prevTexture.image.data = currTexture.image.data;
prevTexture.needsUpdate = true; //updates the previous texture in the shader
}
currTexture.image.data = new Uint8Array(videoContext.getImageData(0,0,SCREEN_WIDTH, SCREEN_HEIGHT).data);
currTexture.needsUpdate = true; //updates the current texture in the shader
prevTime = time;
}catch (e) {
if (e.name == "NS_ERROR_NOT_AVAILABLE") {
console.error(e);
} else {
throw e;
}
}
}
}
prepComposer.render(0.05);
prepPrevComposer.render(0.05);
subtractComposer.render(0.05);
frameNumber++;
requestAnimationFrame(animate);
}
function getData(image) {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return new Uint8Array(context.getImageData(0, 0, image.width, image.height).data);
}
function copyCanvas(e) {
var imgData, imgNode;
if (e.which !== 80) {
return;
} else {
imgData = renderer.domElement.toDataURL();
}
// create a new image and add to the document
imgNode = document.createElement("img");
imgNode.src = imgData;
document.body.appendChild(imgNode);
}
window.onload = init;
window.addEventListener("keyup", copyCanvas);
</script>
</body>
</html>
How can I update the prevBlur.image.data with the current image data of the BlurSave.rendertarget?
Are there any other way to update a shader's Sampler2D uniform with the value from a WebGLRenderTarget’s image data from a previous time-step?
If you want to post-process your scene with a subtraction shader that uses the difference between the current and previous frames, you can do something like the following:
First create two render targets rt1 and rt2. Set currentRT = rt1 and prevRT = rt2.
Then in your render loop, (1) render to currentRT, then (2) pass currentRT and prevRT as uniforms to your subtraction shader and render to the screen, then (3) swap the render targets.
three.js r.70

Pan is the only working thing for OrbitControls

I am trying to program a solar system that you can orbit around and pan so I added an OrbitControls to my project and pan is working fine but for some reason rotate and zoom aren't working. I have tried copying other people's examples and I cannot figure out what is wrong with mine. I don't know if it could just be my computer, but I have no reason to believe that it would be.
<!DOCTYPE html>
<html>
<head>
<title>Example 01.02 - First Scene</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<script type="text/javascript" src="../libs/OrbitControls.js"></script>
<script type="text/javascript" src="../libs/chroma.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body{
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// once everything is loaded, we run our Three.js stuff.
$(function () {
var stats = initStats();
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var clock = new THREE.Clock();
// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 5000);
// position and point the camera to the center of the scene
camera.position.x = -150;
camera.position.y = 200;
camera.position.z = 150;
camera.lookAt(scene.position);
// create a render and set the size
renderer = new THREE.WebGLRenderer( {antialias:true} );
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
ccontrols = new THREE.OrbitControls( camera, renderer.domElement );
ccontrols.damping = 0.2;
ccontrols.addEventListener( 'change', render );
var ambiLight = new THREE.AmbientLight(0x747474)
scene.add(ambiLight);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 0, 0);
pointLight.distance = 100;
scene.add(pointLight);
//create the light box
var lightboxgeom = new THREE.SphereGeometry(3000,50,50);
var lightboxmat = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture("./TexturesAndModels/lightbox.png"), side: THREE.BackSide});
var lightbox = new THREE.Mesh(lightboxgeom, lightboxmat);
//sun and glow
var sun = createMesh(new THREE.SphereGeometry(20, 20, 20), "texture_sun.jpg", "texture_sun_DISP.jpg", "texture_sun_SPEC.jpg");
sun.shading = THREE.NoShading;
var spriteMaterial = new THREE.SpriteMaterial(
{
map: new THREE.ImageUtils.loadTexture( "TexturesAndModels/GLOW.png" ),
useScreenCoordinates: false, alignment: THREE.SpriteAlignment.center,
color: 0xffcc00, transparent: false, blending: THREE.AdditiveBlending
});
var sprite = new THREE.Sprite( spriteMaterial );
sprite.scale.set(100, 100, 1.0);
sun.add(sprite);
//mercury
var mercury = createMesh(new THREE.SphereGeometry(1.50, 20, 20), "texture_mercury.jpg", "texture_mercury_DISP.jpg", "texture_mercury_SPEC.jpg", "texture_mercury_NRM.jpg");
//venus
var venus = createMesh(new THREE.SphereGeometry(3.80, 20, 20), "texture_venus_surface.jpg", "texture_venus_surface_DISP.jpg", "texture_venus_surface_SPEC.jpg", "texture_venus_surface_NRM.jpg");
//earth and clouds
var earth = createMesh(new THREE.SphereGeometry(4.00, 20, 20), "ColorMap.jpg", "Bump2.jpg", "SpecMask2.png", "ColorMap_NRM.jpg");
//mars
var mars = createMesh(new THREE.SphereGeometry(2.10, 20, 20), "texture_mars.jpg", "texture_mars_DISP.jpg", "texture_mars_SPEC.jpg", "texture_mars_NRM.jpg");
//Jupiter
var jupiter = createMesh(new THREE.SphereGeometry(18.7, 20, 20), "texture_jupiter.jpg", "texture_jupiter_DISP.jpg", "texture_jupiter_SPEC.jpg", "texture_jupiter_NRM.jpg");
//saturn
var saturn = createMesh(new THREE.SphereGeometry(18, 20, 20), "texture_saturn.jpg", "texture_saturn_DISP.jpg", "texture_saturn_SPEC.jpg", "texture_saturn_NRM.jpg");
//uranus
var uranus = createMesh(new THREE.SphereGeometry(15, 20, 20), "texture_uranus.jpg", "texture_uranus_DISP.jpg", "texture_uranus_SPEC.jpg", "texture_uranus_NRM.jpg");
//neptune
var neptune = createMesh(new THREE.SphereGeometry(14, 20, 20), "texture_neptune.jpg", "texture_neptune_DISP.jpg", "texture_neptune_SPEC.jpg", "texture_neptune_NRM.jpg");
// position the planets
sun.position.x=0;
sun.position.y=0;
sun.position.z=0;
earth.position.y=0;
mars.position.y=0;
venus.position.y=0;
mercury.position.y=0;
saturn.position.y=0;
jupiter.position.y=0;
uranus.position.y=0;
neptune.position.y=0;
// add the planets to the scene
scene.add(lightbox);
scene.add(earth);
scene.add(sun);
scene.add(mercury);
scene.add(venus);
scene.add(mars);
scene.add(jupiter);
scene.add(saturn);
scene.add(uranus);
scene.add(saturn);
// add the output of the renderer to the html element
$("#WebGL-output").append(renderer.domElement);
var r = 0;
var step = 0;
var controls = new function() {
this.timeScale = 1;
}
var gui = new dat.GUI();
gui.add(controls, 'timeScale', 0, 10);
// render the scene
render();
function createMesh(geom, imageFile, bump, spec, normal) {
var texture = THREE.ImageUtils.loadTexture("./TexturesAndModels/" + imageFile)
var mat = new THREE.MeshPhongMaterial();
mat.map = texture;
if (bump) {
var bump = THREE.ImageUtils.loadTexture("./TexturesAndModels/" + bump)
mat.bumpMap = bump;
mat.bumpScale = 0.2;
}
if(spec) {
var spec = THREE.ImageUtils.loadTexture("./TexturesandModels/" + spec)
mat.specularMap = spec;
}
if(normal) {
var norm = THREE.ImageUtils.loadTexture("./TexturesAndModels/" + normal)
mat.normalMap = norm;
}
var mesh = new THREE.Mesh(geom, mat);
return mesh;
}
function render() {
stats.update();
earth.position.x = Math.sin(r*0.1)*150;
earth.position.z = Math.cos(r*0.1)*150;
earth.rotation.y = step += controls.timeScale * 0.02;
mercury.position.x = Math.sin(r*0.4)*58;
mercury.position.z = Math.cos(r*0.4)*58;
mercury.rotation.y = step/58.7;
venus.position.x = Math.sin(r*0.1625)*108;
venus.position.z = Math.cos(r*0.1625)*108;
venus.rotation.y = step/243;
mars.position.x = Math.sin(r*0.05)*228;
mars.position.z = Math.cos(r*0.05)*228;
mars.rotation.y = step*1.026;
jupiter.position.x = Math.sin(r*.008)*483;
jupiter.position.z = Math.cos(r*.008)*483;
jupiter.rotation.y = step*2.44;
saturn.position.x = Math.sin(r*.003)*886;
saturn.position.z = Math.cos(r*.003)*886;
saturn.rotation.y = step*2.35;
uranus.position.x = Math.sin(r*.001)*1784;
uranus.position.z = Math.cos(r*.001)*1784;
uranus.rotation.y = step*1.34;
neptune.position.x = Math.sin(r*.0006)*2794;
neptune.position.z = Math.cos(r*.0006)*2794;
neptune.rotation.y = step*1.26;
r+=controls.timeScale * (Math.PI/180*2);
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
$("#Stats-output").append(stats.domElement);
return stats;
}
});
</script>
</body>
</html>

addEventListener: undefined is not a function

On my chrome browser, I've got an error:
undefined is not a function
at the line: dom.addEventListener( 'mouseup', onMouseUp, false);
I'm learning webGL and here is my actual code:
<html>
<head>
<?php include "header.php"?>
<title>Learning WebGL</title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="/glmatrix/glMatrix.min.js"></script>
<script type="text/javascript" src="../three.min.js"></script>
<script type="text/javascript" src="../requestAnimationFrame.js"> </script>
<script>
var renderer = null,
scene = null,
camera = null,
cube = null,
animating = false;
function onload()
{
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(container.offsetWidth, container.offsetHeight);
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, container.offsetWidth/container.offsetHeight, 1, 4000);
camera.position.set(0,0,3);
var light = new THREE.DirectionalLight(0xffffff, 1.5);
light.position.set(0,0,1);
scene.add(light);
var mapUrl = "/test.jpg";
var map = THREE.ImageUtils.loadTexture(mapUrl);
var material = new THREE.MeshPhongMaterial({map: map});
var geometry = new THREE.CubeGeometry(1,1,1);
cube = new THREE.Mesh(geometry, material);
cube.rotation.x = Math.PI / 5;
cube.rotation.y = Math.PI / 5;
scene.add(cube);
addMouseHandler();
run();
}
function run()
{
renderer.render(scene,camera);
if(animating){
cube.rotation.y -= 0.01;
}
requestAnimationFrame(run);
}
function addMouseHandler()
{
var mydom = renderer.domElement;
mydom.addEventlistener('mouseup', onMouseUp, false);
}
function onMouseUp(event){
event.preventDefault();
animating = !animating;
}
</script>
</head>
<body onload="onload();">
<?php include "navigation.php"?>
<div id="container" style="width:95%; height:95%; position:absolute;">
</div>
<div id="prompt" style="width:95%; height:6%; bottom:0; position:absolute;">
Click to animate the cube
</div>
</body>
</html>
I've tried changing the variable name from "dom" to "mydom" but that doesn't help.
Many thanks!

Can't get first person controls works

I'm starting with Three.js, and I'm trying to set up a simple first person controls in my scene, which is containing a single sphere. I just see a black screen. There are no errors.
Without FirstPersonControls, I can see the sphere.
What am I doing wrong ?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
#container {
width: 400px;
height: 300px;
}
</style>
<script type="text/javascript" src="js/Three.js"></script>
<script type="text/javascript">
var controls;
window.onload = function() {
var RENDER_WIDTH = 400, RENDER_HEIGHT = 300;
// Creating scene
var scene = new THREE.Scene();
// Camera
var camera = new THREE.PerspectiveCamera(45, RENDER_WIDTH / RENDER_HEIGHT, 0.1, 10000);
camera.position.z = 300;
scene.add(camera);
controls = new THREE.FirstPersonControls(camera);
controls.movementSpeed = 1000;
controls.lookSpeed = 0.125;
controls.lookVertical = true;
// Sphere
var sphereMaterial = new THREE.MeshLambertMaterial({
color: 0x00ff00
});
var radius = 50, segments = 16, rings = 16;
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
sphereMaterial
);
scene.add(sphere);
// Light
scene.add(new THREE.AmbientLight(0x333333));
var light = new THREE.PointLight(0xffffff, 0.9);
light.position.set(50, 200, 50);
scene.add(light);
// Render
var container = document.getElementById('container');
var renderer = new THREE.WebGLRenderer();
renderer.setSize(RENDER_WIDTH, RENDER_HEIGHT);
renderer.setClearColorHex(0x000000, 1);
container.appendChild(renderer.domElement);
var clock = new THREE.Clock();
setInterval(function() {
var delta = clock.getDelta();
controls.update(delta);
renderer.render(scene, camera);
}, 100);
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
FirstPersonControls is designed to work with full-width canvases, so you need to set
var RENDER_WIDTH = window.innerWidth, RENDER_HEIGHT = window.innerHeight;
Also remove you style settings.
Finally, to make it easier to "find" your sphere, set controls.lookVertical = false -- just for now.
From that point, you'll just have to experiment.

Resources