更多有趣示例 尽在 知屋安砖社区
示例
CSS
body { margin: 0; padding: 0; overflow: hidden; }
canvas { width: 100%; height: 100% }
JS
var Leaf = function() {
THREE.Group.apply(this, arguments);
var leaf = new THREE.Mesh(
new THREE.TorusGeometry(.8,1.6,3,4),
new THREE.MeshStandardMaterial( {
color: 0x0b8450,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} )
);
//leaf.geometry.vertices[4].y -=1;
leaf.rotateX(Math.random()*Math.PI*2);
leaf.rotateZ(Math.random()*Math.PI*2);
leaf.rotateY(Math.random()*Math.PI*2);
leaf.receiveShadow = true;
leaf.castShadow = true;
this.add(leaf);
}
Leaf.prototype = Object.create(THREE.Group.prototype);
Leaf.prototype.constructor = Leaf;
var ChristmasTree = function() {
THREE.Group.apply(this, arguments);
// A material for the pot
var potMaterial = new THREE.MeshStandardMaterial( {
color: 0xf97514,
shading: THREE.FlatShading,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} );
// The pot
var pot = new THREE.Mesh(
addNoise(new THREE.CylinderGeometry(30, 25, 35, 64, 2), 2),
potMaterial
);
pot.position.y += 17.5;
pot.castShadow = true;
pot.receiveShadow = true;
this.add(pot);
var potRim = new THREE.Mesh(
addNoise(new THREE.CylinderGeometry(38, 35, 10, 8, 1), 2),
potMaterial
);
potRim.position.y += 35;
potRim.castShadow = true;
potRim.receiveShadow = true;
this.add(potRim);
// A tree trunk
var trunk = new THREE.Mesh(
addNoise(new THREE.CylinderGeometry(12, 18, 30, 8, 3),2),
new THREE.MeshStandardMaterial( {
color: 0x713918,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} )
);
trunk.position.y += 45;
trunk.castShadow = true;
trunk.receiveShadow = true;
this.add(trunk);
// A shape,
var logo = new THREE.Shape();
logo.moveTo(3.43, 96.86);
logo.bezierCurveTo(2.01, 96.86, 1.38, 95.87, 2.04, 94.63);
logo.lineTo (9.07, 83.43);
logo.bezierCurveTo(9.72, 82.2, 11.42, 81.2, 12.84, 81.2);
logo.lineTo (67.94, 81.2);
logo.bezierCurveTo(69.37, 81.2 , 70, 80.2, 69.34, 78.97);
logo.lineTo (41.58, 24.87);
logo.bezierCurveTo(40.92, 23.64, 40.92, 21.65, 41.58, 20.41);
logo.lineTo (49.44, 5.66);
logo.bezierCurveTo(49.44+0.65, 5.66-1.23, 49.44+1.72, 5.66-1.23, 51.82, 5.66);
logo.lineTo (99.22,94.63);
logo.bezierCurveTo(99.22+0.65, 94.63+1.23, 99.22+0.02, 94.63+2.23, 97.82, 96.86);
var extrudeSettings = {
steps: 1,
amount: 16,
curveSegments: 1,
bevelEnabled: true,
bevelThickness: 5,
bevelSize: 5,
bevelSegments: 1
};
var treeGroup = new THREE.Group();
var logoGeometry = new THREE.ExtrudeGeometry( logo, extrudeSettings );
addNoise(logoGeometry, 2,2,0.5)
var mesh = new THREE.Mesh( logoGeometry, new THREE.MeshStandardMaterial( {
color: 0x15a46b,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} ) ) ;
mesh.castShadow = true;
mesh.receiveShadow = true;
treeGroup.add( mesh );
for(var x = 0; x < logoGeometry.vertices.length; x++) {
var leaf = new Leaf();
leaf.position.copy(logoGeometry.vertices[x]);
treeGroup.add(leaf);
}
treeGroup.position.y += 180;
treeGroup.position.x -= 60;
treeGroup.position.z += 10;
treeGroup.rotateZ(Math.PI);
treeGroup.rotateY(Math.PI);
treeGroup.scale.set(1.2,1.2,1.2);
this.add(treeGroup);
var decorationPositions = [
[-35, 55, 17, -0.1, 0],
[35, 59, 17, -0.1, 0],
[-5, 74, 17, -0.2, 0.2],
[18, 123, 18, -0.2, 0.3],
[43, 100, 15, -0.2, 0.3],
[-12, 133, 1, 0, 0],
[-35, 65, -17, 0.1, -0],
[25, 67, -17, 0.1, -0],
[-5, 74, -17, 0.2, -0.2],
[10, 143, -18, 0.2, 0.3],
[50, 85, -15, 0.2, 0.3],
];
this.decorations = [];
for (var d = 0; d < decorationPositions.length; d++) {
var decoration = new Decoration();
decoration.position.set(decorationPositions[d][0], decorationPositions[d][1], decorationPositions[d][2]);
decoration.rotateX(decorationPositions[d][3]);
decoration.rotateZ(decorationPositions[d][4]);
this.add(decoration);
this.decorations.push(decoration);
}
}
ChristmasTree.prototype = Object.create(THREE.Group.prototype);
ChristmasTree.prototype.constructor = ChristmasTree;
ChristmasTree.prototype.updatePosition = function() {
for(var d = 0; d < this.decorations.length; d++) {
this.decorations[d].updatePosition();
}
};
var Star = function() {
THREE.Group.apply(this, arguments);
var starShape = new THREE.Shape([
new THREE.Vector2(0, 50),
new THREE.Vector2(10, 10),
new THREE.Vector2(40, 10),
new THREE.Vector2(20, -10),
new THREE.Vector2(30, -50),
new THREE.Vector2(0, -20),
new THREE.Vector2(-30, -50),
new THREE.Vector2(-20, -10),
new THREE.Vector2(-40, 10),
new THREE.Vector2(-10, 10)
]);
var geometry = new THREE.ExtrudeGeometry(starShape, {
steps: 1,
amount: 4,
curveSegments: 1,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 10,
bevelSegments: 1
});
addNoise(geometry, 0, 0, 2);
var star = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({
color: 0xffd423,
shading: THREE.FlatShading,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25,
emissive: 0xffd423,
emissiveIntensity: 0.4
}));
star.scale.set(.3, .3, .3);
this.add(star);
var pointLight = new THREE.DirectionalLight( 0xffd423,.4);
pointLight.position.set( 0, 10, 0);
this.add( pointLight );
}
Star.prototype = Object.create(THREE.Group.prototype);
Star.prototype.constructor = Star;
Star.prototype.updatePosition = function() {
this.rotateY(0.005);
};
var Decoration = function() {
// Run the Group constructor with the given arguments
THREE.Group.apply(this, arguments);
this.rotationSpeed = Math.random() * 0.01 + 0.003;
this.rotationPosition = Math.random();
// A random color assignment
var colors = ['#ff0051', '#f56762','#a53c6c','#f19fa0','#72bdbf','#47689b'];
var bauble = new THREE.Mesh(
addNoise(new THREE.OctahedronGeometry(12,1), 2),
new THREE.MeshStandardMaterial( {
color: colors[Math.floor(Math.random()*colors.length)],
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
})
);
bauble.castShadow = true;
bauble.receiveShadow = true;
bauble.rotateZ(Math.random()*Math.PI*2);
bauble.rotateY(Math.random()*Math.PI*2);
this.add(bauble);
var shapeOne = new THREE.Mesh(
addNoise(new THREE.CylinderGeometry(4, 6, 10, 6, 1), 0.5),
new THREE.MeshStandardMaterial( {
color: 0xf8db08,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} )
);
shapeOne.position.y += 8;
shapeOne.castShadow = true;
shapeOne.receiveShadow = true;
this.add(shapeOne);
var shapeTwo = new THREE.Mesh(
addNoise(new THREE.TorusGeometry( 2,1, 6, 4, Math.PI), 0.2),
new THREE.MeshStandardMaterial( {
color: 0xf8db08,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} )
);
shapeTwo.position.y += 12.5;
shapeTwo.castShadow = true;
shapeTwo.receiveShadow = true;
this.add(shapeTwo);
var scale = Math.random() * 0.2 + 0.4;
this.scale.set(scale,scale,scale);
};
Decoration.prototype = Object.create(THREE.Group.prototype);
Decoration.prototype.constructor = Decoration;
Decoration.prototype.updatePosition = function() {
this.rotationPosition += this.rotationSpeed;
this.rotation.y = (Math.sin(this.rotationPosition));
};
var Leaf = function() {
THREE.Group.apply(this, arguments);
var leaf = new THREE.Mesh(
new THREE.TorusGeometry(.8,1.6,3,4),
new THREE.MeshStandardMaterial( {
color: 0x0b8450,
shading: THREE.FlatShading ,
metalness: 0,
roughness: 0.8,
refractionRatio: 0.25
} )
);
//leaf.geometry.vertices[4].y -=1;
leaf.rotateX(Math.random()*Math.PI*2);
leaf.rotateZ(Math.random()*Math.PI*2);
leaf.rotateY(Math.random()*Math.PI*2);
leaf.receiveShadow = true;
leaf.castShadow = true;
this.add(leaf);
}
Leaf.prototype = Object.create(THREE.Group.prototype);
Leaf.prototype.constructor = Leaf;
var Present = function() {
THREE.Group.apply(this, arguments);
// A random color assignment
var colors = ['#ff0051', '#a53c6c','#f19fa0','#72bdbf','#47689b'],
boxColor = colors.splice( Math.floor(Math.random()*colors.length), 1 )[0];
colors.push('#393839'),
ribbonColor = colors.splice( Math.floor(Math.random()*colors.length), 1 )[0],
boxMaterial = new THREE.MeshStandardMaterial( {
color: boxColor,
shading: THREE.FlatShading,
metalness: 0,
roughness: 1
}),
ribbonMaterial = new THREE.MeshStandardMaterial( {
color: ribbonColor,
shading: THREE.FlatShading,
metalness: 0,
roughness: 1
});
var box = new THREE.Mesh(
addNoise(new THREE.BoxGeometry( 20, 12, 15), 2,1, 2),
boxMaterial
);
box.position.y += 6;
box.castShadow = true;
box.receiveShadow = true;
this.add(box);
box = new THREE.Mesh(
addNoise(new THREE.BoxGeometry( 22, 14, 2),.5),
ribbonMaterial
);
box.position.y += 6;
box.castShadow = true;
box.receiveShadow = true;
this.add(box);
box = new THREE.Mesh(
addNoise(new THREE.BoxGeometry( 2, 14, 17),.5),
ribbonMaterial
);
box.position.y += 6;
box.castShadow = true;
box.receiveShadow = true;
this.add(box);
var bow = new THREE.Mesh(
addNoise(new THREE.TorusGeometry(2, 1, 4, 4), 0.5),
ribbonMaterial
);
bow.position.x -= 2;
bow.position.y += 14;
bow.rotateZ(-1*Math.PI/1.5);
bow.castShadow = true;
bow.receiveShadow = true;
this.add(bow);
bow = new THREE.Mesh(
addNoise(new THREE.TorusGeometry(2, 1, 4, 4), 0.5),
ribbonMaterial
);
bow.position.x += 2;
bow.rotateZ(Math.PI/1.5);
bow.position.y += 14;
bow.castShadow = true;
bow.receiveShadow = true;
this.add(bow);
this.scale.set(2,2,2);
}
Present.prototype = Object.create(THREE.Group.prototype);
Present.prototype.constructor = Present;
// Create a scene which will hold all our meshes to be rendered
var scene = new THREE.Scene();
// Create and position a camera
var camera = new THREE.PerspectiveCamera(
70, // Field of view
window.innerWidth/window.innerHeight, // Aspect ratio
0.1, // Near clipping pane
1000 // Far clipping pane
);
// Reposition the camera
camera.position.set(-60,80,210);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0,80,0))
// Create a renderer
var renderer = new THREE.WebGLRenderer({ antialias: true });
// Size should be the same as the window
renderer.setSize( window.innerWidth, window.innerHeight );
// Set a near white clear color (default is black)
renderer.setClearColor( 0xfff6e6 );
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
document.body.appendChild( renderer.domElement );
// Add an ambient lights
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.3 );
scene.add( ambientLight );
// Add a point light that will cast shadows
var pointLight = new THREE.PointLight( 0xffffff,.8 );
pointLight.position.set( 80, 160, 120 );
pointLight.castShadow = true;
pointLight.shadow.mapSize.width = 1024;
pointLight.shadow.mapSize.height = 1024;
scene.add( pointLight );
// A basic material that shows the geometry wireframe.
var shadowMaterial = new THREE.ShadowMaterial( { color: 0xffffff } );
shadowMaterial.opacity = 0.5;
var groundMesh = new THREE.Mesh(
new THREE.BoxGeometry( 1000, .1, 1000 ),
shadowMaterial
);
groundMesh.receiveShadow = true;
scene.add( groundMesh );
// Add the tree
var tree = new ChristmasTree();
scene.add(tree);
// A star on top
var star = new Star();
star.position.y += 200;
scene.add(star);
// Loop around the tree, adding presents every 20 to 40 degrees.
for(var angle = 0; angle < 360; angle += Math.random()*20+20) {
var p = new Present();
var radius = Math.random() * 40 + 50;
p.position.x = Math.cos(angle * Math.PI / 180) * radius;
p.position.z = Math.sin(angle * Math.PI / 180) * radius;
p.scale.set(Math.random() + 1, Math.random() + 1,Math.random() + 1);
scene.add(p);
}
// Add an orbit control which allows us to move around the scene. See the three.js example for more details
// https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.target = new THREE.Vector3(0,80,0);
controls.maxPolarAngle = Math.PI / 2;
controls.minDistance = 100;
controls.maxDistance = 220;
requestAnimationFrame(render);
function render() {
controls.update();
// Update animated elements
tree.updatePosition();
star.updatePosition();
// Render the scene/camera combnation
renderer.render(scene, camera);
// Repeat...
requestAnimationFrame(render);
}
/**
* Helper function to add random noise to geometry vertixes
*
* @param geometry The geometry to alter
* @param noiseX Amount of noise on the X axis
* @param noiseY Amount of noise on the Y axis
* @param noiseZ Amount of noise on the Z axis
* @returns the geometry object
*/
function addNoise(geometry, noiseX, noiseY, noiseZ) {
var noiseX = noiseX || 2;
var noiseY = noiseY || noiseX;
var noiseZ = noiseZ || noiseY;
for(var i = 0; i < geometry.vertices.length; i++){
var v = geometry.vertices[i];
v.x += -noiseX / 2 + Math.random() * noiseX;
v.y += -noiseY / 2 + Math.random() * noiseY;
v.z += -noiseZ / 2 + Math.random() * noiseZ;
}
return geometry;
}
function addShapeNoise(shapes, noiseX, noiseY) {
var noiseX = noiseX || 2;
var noiseY = noiseY || noiseX;
for(var i = 0; i < shapes.length; i++){
var v = shapes[i];
v.x += -noiseX / 2 + Math.random() * noiseX;
v.y += -noiseY / 2 + Math.random() * noiseY;
shapes[i] = v;
}
return shapes;
}