I'm new to three.js and I'd like to learn how to cycle through materials onclick. This example shows what I'd like to achieve except it's cycling through textures rather than materials.
I'd like to have the materials in an array, then be able to click the canvas to cycle and loop through the materials.
Here's the code for the above example:
var scene = new THREE.Scene();
scene.background = new THREE.Color( 0xcccccc );
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
camera.position.y = 5;
camera.position.x = 5;
camera.lookAt(new THREE.Vector3(0,0,0)); // Make the camera look at the point of origin
var renderer = new THREE.WebGLRenderer({antialias:true});
var devicePixelRatio = window.devicePixelRatio || 1; // To handle high pixel density displays
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(devicePixelRatio);
document.body.appendChild( renderer.domElement );
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
};
// instantiate a texture loader
var loader = new THREE.TextureLoader();
//allow cross origin loading
loader.crossOrigin = '';
// The textures to use
var arr = [
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/259155/THREE_gates.jpg',
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/259155/THREE_crate1.jpg',
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/259155/THREE_crate2.jpg'
];
var textureToShow = 0;
// Load the first texture
// var texture = loadTexture('https://s3-us-west-2.amazonaws.com/s.cdpn.io/259155/MarbleSurface.jpg');
// Instantiate the material we will be using
var material = new THREE.MeshBasicMaterial();
// Instantiate a geometry to use
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
// Instatiate the mesh with the geometry and material
var cube = new THREE.Mesh( geometry, material );
cube.position.y = 0.5;
// Then load the texture
loader.load(arr[textureToShow], function(tex) {
// Once the texture has loaded
// Asign it to the material
material.map = tex;
// Update the next texture to show
textureToShow++;
// Add the mesh into the scene
scene.add( cube );
});
// Click interaction
var canvas = document.getElementsByTagName("canvas")[0];
canvas.addEventListener("click", function() {
loader.load(arr[textureToShow], function(tex) {
// Once the texture has loaded
// Asign it to the material
material.map = tex;
// Update the next texture to show
textureToShow++;
// Have we got to the end of the textures array
if(textureToShow > arr.length-1) {
textureToShow = 0;
}
});
});
// Start rendering the scene
render();
Here's the code I can't get working:
var container, stats;
var camera, scene, renderer;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var globalObject;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 500;
//scene
scene = new THREE.Scene();
ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambientLight);
pointLight = new THREE.PointLight(0xff0000, 0.5);
pointLight.position.z = 2500;
scene.add(pointLight);
var pointLight2 = new THREE.PointLight(0xff6666, 1);
camera.add(pointLight2);
var pointLight3 = new THREE.PointLight(0x0000ff, 0.5);
pointLight3.position.x = -1000;
pointLight3.position.z = 1000;
scene.add(pointLight3);
//manager
var manager = new THREE.LoadingManager();
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
//materials
var path = "textures/cube/skybox/";
var format = '.jpg';
var urls = [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
];
var reflectionCube = new THREE.CubeTextureLoader().load(urls);
var material = new THREE.MeshStandardMaterial({
envMap: reflectionCube,
roughness: 0.1,
metalness: 1,
color: 0xfee6af,
});
var materialTwo = new THREE.MeshStandardMaterial({
envMap: reflectionCube,
roughness: 0.1,
metalness: 0,
color: 0xffff00,
});
//model
var loader = new THREE.OBJLoader(manager);
loader.load('logo97.obj', function(object) {
//store global reference to .obj
globalObject = object;
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.material = material;
child.material.needsUpdate = true;
}
});
object.position.y = 0;
scene.add(object);
});
//render
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
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) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
// Click interaction
var canvas = document.getElementsByTagName("canvas")[0];
canvas.addEventListener("click", function() {
var materials = [
new THREE.MeshBasicMaterial( {color:'#b02030'} ),
new THREE.MeshLambertMaterial( {color:'#b02030'} ),
new THREE.MeshPhongMaterial( {color:'#b02030', shininess: 100 } ),
new THREE.MeshNormalMaterial(),
// ...
];
var materialToShow = 0;
materialToShow ++;
if ( materialToShow >= materials.length ) materialToShow = 0;
child.material = materials[materialToShow];
});
//animate
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * .05;
camera.position.y += (-mouseY - camera.position.y) * .05;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}