castShadow 和 recieveShadow 未在场景中渲染
castShadow and recieveShadow is not rendering in the scene
我正在通过做一些游戏来学习 threejs。我能够渲染场景中的所有模型并添加一些灯光,现在很完美,
但是当我尝试在飞机上投射和接收阴影时。场景中物体的阴影没有渲染。
我不明白我哪里做错了。
下面是代码
请看一下,帮我解决问题。
import { OrbitControls } from '../assets/js/OrbitControls.js';
import { GLTFLoader } from '../assets/js/GLTFLoader.js';
import { OBJLoader } from '../assets/js/OBJLoader.js';
import { MTLLoader } from '../assets/js/MTLLoader.js';
const extrudeSettings = { depth: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 };
const logo = {
position : {
top: 750,
back: -2000,
},
title: " Exhibition !!!",
color: 0x006699
};
var camera, scene, renderer, man_walk, mixer, action, keyboard, controls, door, mixerG, mixerB;
var mixerW = new THREE.AnimationMixer();
var man_walk = new THREE.Scene();
var clock = new THREE.Clock();
var gltfLoader = new GLTFLoader();
var objLoader = new OBJLoader();
init();
animate();
function init(){
// RENDERER
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.gammaOutput = true
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.BasicShadowMap;
document.body.appendChild(renderer.domElement);
// SCENE
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xC3D8D6 );
// scene.fog = new THREE.Fog( 0xffffff, 0, 750 );
// CAMERA
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.y = 250;
camera.position.z = 2090;
// LIGHTS
const light = new THREE.AmbientLight(0xffffff);
light.position.set = (0,100,100);
light.castShadow = true;
scene.add(light);
var dlight = new THREE.DirectionalLight( 0xaabbff, 0.3 );
dlight.position.x = 0;
dlight.position.y = 250;
dlight.position.z = 2500;
dlight.castShadow = true;
scene.add( dlight );
// KEY EVENTS
keyboard = new THREEx.KeyboardState();
// console.log(keyboard);
// // ORBIT CONTROLS
// controls = new OrbitControls(camera, renderer.domElement);
// controls.enableDampling = true;
// controls.campingFactor = 0.25;
// controls.enableZoom = true;
ExhibitionLogo()
getAlternateTiles();
getFloorMaterialByImage();
loadDoor();
loadTent();
loadSchoolGirl();
loadCollegeBoy()
loadMan();
// loadIntroModel();
loadFrame();
}
function loadDoor(){
// objLoader.load('/assets/3d_models/Doorway/Doorway.obj', object => {
// object.traverse(function (child) {
// if (child.type == "Mesh") {
// child.material = new THREE.MeshNormalMaterial();
// }
// });
// door=object;
// scene.add(object);
// object.rotation.z = -Math.PI / 2;
// object.rotation.x = -Math.PI / 2;
// object.scale.multiplyScalar(50);
// object.position.z = 1000
// });
gltfLoader.load('/assets/3d_models/torii_gate/scene.gltf', gltf => {
var door = gltf.scene;
door.position.set(0, 250, 1050);
door.scale.set(500,400,500);
door.rotateY(210.5);
scene.add(door);
});
}
function loadMan(){
gltfLoader.load('/assets/3d_models/boy_animated/scene.gltf', gltf => {
man_walk = gltf.scene;
man_walk.position.set(0, 0, 2050);
man_walk.rotateY(210.5);
gltf.scene.castShadow = true;
scene.add(man_walk);
mixer = new THREE.AnimationMixer(man_walk);
mixer.clipAction(gltf.animations[0]).play();
});
}
function loadWoman(){
gltfLoader.load('/assets/3d_models/woman/scene.gltf', gltf => {
var woman = gltf.scene;
woman.position.set(-300, 0, -500);
scene.add(woman);
gltf.scene.castShadow = true;
mixerW = new THREE.AnimationMixer(woman);
mixerW.clipAction(gltf.animations[0]).play();
var box = new THREE.Box3().setFromObject(woman);
console.log(box)
var text1 = makeTextSprite("Hello, Welcome to Gallery. This will take you to SOMs world");
scene.add(text1);
text1.position.set(-300, box.max.y + 20, -500);
text1.scale.set(150,100,1);
});
}
function loadTent(){
gltfLoader.load('/assets/3d_models/single_edition_tent/scene.gltf', gltf => {
var tent = gltf.scene;
tent.rotateY(10);
tent.scale.set(130,120,100);
tent.position.set(-300, 0, -900);
gltf.scene.castShadow = true;
scene.add(tent);
// generateCircleStage(extrudeSettings);
generateHexagonStage(extrudeSettings, -300, -900);
});
loadWoman();
}
function loadSchoolGirl() {
gltfLoader.load('/assets/3d_models/girl_idle/scene.gltf', gltf => {
gltf.scene.position.set(-1300, 100, 0);
gltf.scene.rotateY(10);
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(60);
gltf.scene.castShadow = true;
mixerG = new THREE.AnimationMixer(gltf.scene);
mixerG.clipAction(gltf.animations[0]).play();
});
}
function loadCollegeBoy() {
gltfLoader.load('/assets/3d_models/levi_boy_stylish/scene.gltf', gltf => {
gltf.scene.position.set(60, 0, 60)
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(50);
gltf.scene.castShadow = true;
mixerB = new THREE.AnimationMixer(gltf.scene);
mixerB.clipAction(gltf.animations[0]).play();
});
}
function loadIntroModel() {
gltfLoader.load('/assets/3d_models/cute_boy/scene.gltf', gltf => {
var box = new THREE.Box3().setFromObject(gltf.scene);
gltf.scene.position.z = (box.max.z - box.min.z) / 2;
gltf.scene.position.x = -(box.max.x - box.min.x) / 2;
gltf.scene.position.y = 50;
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(30);
});
}
function loadFrame() {
gltfLoader.load('/assets/3d_models/photo/scene.gltf', gltf => {
gltf.scene.position.set(1950, 150, -600)
gltf.scene.scale.multiplyScalar(200);
gltf.scene.traverse( function ( child ) {
if (child.type == "Mesh") {
var newTexture = new THREE.TextureLoader().load( '/assets/img/man.jpg' );
newTexture.encoding = THREE.sRGBEncoding;
newTexture.flipY = false;
child.material.map = newTexture;
child.material.needsUpdate = true;
child.material.map.needsUpdate = true;
}
});
gltf.scene.rotateY(100);
gltf.scene.castShadow = true;
scene.add(gltf.scene);
});
}
// Animate
function animate() {
requestAnimationFrame(animate);
var delta = clock.getDelta(); // seconds.
var rotateAngle = Math.PI / 2 * delta;
mixerW.update(delta);
mixerG.update(delta*5);
mixerB.update(delta*5);
render();
updateMan();
}
function updateMan(){
var delta = clock.getDelta(); // seconds.
var rotateAngle = Math.PI / 2 * delta;
mixerW.update(delta);
var moveDistance = 550 * delta; // 100 pixels per second
var rotateAngle = Math.PI / 2 * delta; // pi/2 radians (90 degrees) per second
if ( keyboard.pressed("a") ){
man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), rotateAngle);
}
if ( keyboard.pressed("d") ){
man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), -rotateAngle);
}
if ( keyboard.pressed("w") ){
man_walk.translateZ(moveDistance);
mixer.update(delta*5);
}
if ( keyboard.pressed("s") ){
man_walk.translateZ(-moveDistance);
mixer.update(delta*5);
}
var relativeCameraOffset = new THREE.Vector3(0,220,-600);
var cameraOffset = relativeCameraOffset.applyMatrix4( man_walk.matrixWorld );
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(man_walk.position);
}
function render()
{
// controls.update();
renderer.render( scene, camera );
}
/********************************** START : FLOOR *************************************/
function getAlternateTiles() {
var segments = 50;
var geometry = new THREE.PlaneGeometry(5000, 5000, segments, segments);
geometry.rotateX( - Math.PI / 2 );
var materialEven = new THREE.MeshBasicMaterial({color: 0x85A95D});
var materialOdd = new THREE.MeshBasicMaterial({color: 0x93BC54});
// #485C64
var materials = [materialEven, materialOdd];
for(var x=0; x<segments; x++) {
for(var y=0; y<segments; y++) {
var i = x * segments + y;
var j = 2 * i;
geometry.faces[ j ].materialIndex = geometry.faces[ j + 1 ].materialIndex = (x + y) % 2;
}
}
var mesh = new THREE.Mesh(geometry, materials);
mesh.receiveShadow = true;
scene.add(mesh);
}
function getFloorMaterialByImage() {
var geometry = new THREE.PlaneGeometry( 500, 5000, 10, 10 );
geometry.rotateX( - Math.PI / 2 );
// lightwood.jpg, whitetiles.jpg, floorline.jpg, woodsheet.jpg, Carpet.jpeg, Wood_Bamboo.jpeg, corporate.jpg
var floorTexture = new THREE.TextureLoader().load( '/assets/img/corporate.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(500, 500);
var material = new THREE.MeshBasicMaterial({map: floorTexture});
// Vertical road
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0,0.2,0);
mesh.receiveShadow = true;
scene.add(mesh);
// Horizontal road
var mesh1 = mesh.clone();
mesh1.rotateY(Math.PI / 2);
mesh1.receiveShadow = true;
scene.add(mesh1);
//cube
var geometry1 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material1 = new THREE.MeshPhongMaterial( {color: 0x8B0000} );
var cube = new THREE.Mesh( geometry1, material1 );
cube.scale.set(150,10,100);
cube.position.set(0,1,-2000);
var geometry2 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material2 = new THREE.MeshPhongMaterial( {color: 0x191970} );
var cube2 = new THREE.Mesh( geometry2, material2 );
cube2.scale.set(100,10,150);
cube2.position.set(2000,0,0);
var geometry3 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material3 = new THREE.MeshPhongMaterial( {color: 0x006400} );
var cube3 = new THREE.Mesh( geometry3, material3 );
cube3.scale.set(100,10,150);
cube3.position.set(-2000,0,0);
cube.receiveShadow = true;
cube2.receiveShadow = true;
cube3.receiveShadow = true;
scene.add(cube2);
scene.add(cube3);
scene.add( cube );
}
/********************************** END : FLOOR *************************************/
/********************************** START : GALLERY LOGO *************************************/
function ExhibitionLogo() {
var loader = new THREE.FontLoader();
loader.load( '/assets/font/gentilis_bold.typeface.json', function ( font ) {
var xMid, text;
var matDark = new THREE.LineBasicMaterial( {
color: logo.color,
side: THREE.DoubleSide
} );
var matLite = new THREE.MeshBasicMaterial( {
color: logo.color,
transparent: true,
opacity: 0.4,
side: THREE.DoubleSide
} );
var shapes = font.generateShapes( logo.title, 1000 );
var geometry = new THREE.ShapeBufferGeometry( shapes );
geometry.computeBoundingBox();
xMid = - 0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
geometry.translate( xMid, 0, 0 );
text = new THREE.Mesh( geometry, matLite );
text.position.z = logo.position.back;
text.position.y = logo.position.top;
scene.add( text );
var lineText = new THREE.Object3D();
for ( var i = 0; i < shapes.length; i ++ ) {
var shape = shapes[ i ];
var points = shape.getPoints();
var geometry = new THREE.BufferGeometry().setFromPoints( points );
geometry.translate( xMid, logo.position.top, 0 );
var lineMesh = new THREE.Line( geometry, matDark );
lineText.add( lineMesh );
lineText.position.z = logo.position.back + 50;
}
scene.add( lineText );
});
}
/********************************** END : GALLERY LOGO *************************************/
/********************************** START : TEXT TO SHOW WHEN USER APPROACHES PERSONS *************************************/
function makeTextSprite(message, parameters) {
// Canvas for text
const textCanvas = prepareTextCanvas(message, parameters);
// Canvas Texture
const texture = new THREE.CanvasTexture(textCanvas);
texture.minFilter = THREE.LinearFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
// Sprite Material
const textMaterial = new THREE.SpriteMaterial({
map: texture,
transparent: true,
});
// Sprite
const textSprite = new THREE.Sprite(textMaterial);
return textSprite;
}
function prepareTextCanvas(message, parameters) {
if ( parameters === undefined ) parameters = {};
var fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "Calibri";
var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 16;
var borderThickness = parameters.hasOwnProperty("borderThickness") ? parameters["borderThickness"] : 4;
var borderColor = parameters.hasOwnProperty("borderColor") ?parameters["borderColor"] : "white";
var backgroundColor = parameters.hasOwnProperty("backgroundColor") ?parameters["backgroundColor"] : "blue";
var textColor = parameters.hasOwnProperty("textColor") ?parameters["textColor"] : "white";
var maxWidth = 280;
var lineHeight = 20;
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var x = (canvas.width - maxWidth) / 2; // default canvas width-300, height-150
var y = 35;
context.font = fontsize + "px " + fontface;
context.fillStyle = backgroundColor;
context.strokeStyle = borderColor;
context.lineWidth = borderThickness;
context.fillRect(0, 15, canvas.width, lineHeight + y);
context.fillStyle = textColor;
wrapText(context, message, x, y, maxWidth, lineHeight);
return context.canvas;
}
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
}
/************************************* END : TEXT TO SHOW WHEN USER APPROACHES PERSONS *************************************/
/************************************* START : HEXAGON STAGES *************************************/
function generateHexagonStage(extrudeSettings, x, z) {
generate3DHexagon(100, extrudeSettings, 0x00f000, x, 8, z)
generate3DHexagon(80, extrudeSettings, 0xff00ff, x, 16, z)
generate3DHexagon(60, extrudeSettings, 0x00f000, x, 24, z)
}
function generate3DHexagon(size, extrudeSettings, color, x, y, z) {
var hexShape = getHexagonShape(size);
var hexagon = getHexagonMesh(hexShape, extrudeSettings, color, x, y, z)
scene.add(hexagon);
}
function getHexagonMesh(shape, extrudeSettings, color, x, y, z) {
var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color } ) );
mesh.position.set( x, y, z - 75 );
mesh.rotation.x = Math.PI/2;
return mesh;
}
function getHexagonShape(cellSize) {
// create base shape used for building geometry
var i, verts = [];
// create the skeleton of the hex
for (i = 0; i < 6; i++) {
verts.push(createVertex(i, cellSize));
}
// copy the verts into a shape for the geometry to use
var cellShape = new THREE.Shape();
cellShape.moveTo(verts[0].x, verts[0].y);
for (i = 1; i < 6; i++) {
cellShape.lineTo(verts[i].x, verts[i].y);
}
cellShape.lineTo(verts[0].x, verts[0].y);
cellShape.autoClose = true;
return cellShape
}
function createVertex(i, cellSize) {
var angle = (Math.PI * 2 / 6) * i;
return new THREE.Vector3((cellSize * Math.cos(angle)), (cellSize * Math.sin(angle)), 0);
}
/************************************* END : HEXAGON STAGES *************************************/
/************************************* START : CIRCLE STAGES *************************************/
function generateCircleStage(extrudeSettings) {
generate3DCircle(100, extrudeSettings, 0x00f000, 8)
generate3DCircle(80, extrudeSettings, 0xffffff, 16)
generate3DCircle(60, extrudeSettings, 0x00f000, 24)
}
function generate3DCircle(radius, extrudeSettings, color, y) {
var circleShape = getCircleShape(radius);
var circle = getCircleMesh( circleShape, extrudeSettings, color, 0, y, 0, 0, 0, 0, 1 );
circle.rotation.x = Math.PI/2;
scene.add(circle);
}
function getCircleMesh( shape, extrudeSettings, color, x, y, z, rx, ry, rz, s ) {
// extruded shape
var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color } ) );
mesh.position.set( x, y, z - 75 );
mesh.rotation.set( rx, ry, rz );
// mesh.scale.set( s, s, s );
return mesh
}
function getCircleShape(radius) {
var circleShape = new THREE.Shape()
.moveTo( 0, radius )
.quadraticCurveTo( radius, radius, radius, 0 )
.quadraticCurveTo( radius, - radius, 0, - radius )
.quadraticCurveTo( - radius, - radius, - radius, 0 )
.quadraticCurveTo( - radius, radius, 0, radius );
return circleShape
}
/************************************* END : CIRCLE STAGES *************************************/
请从这里找到完整代码:
我已经离线测试了您的代码,但存在多个问题和运行时错误:
AmbientLight
不投射阴影。设置 castShadow
将产生运行时错误。
- 您没有为您的
DirectionalLight
实例正确配置阴影平截头体。使用此代码试试:
var dlight = new THREE.DirectionalLight( 0xaabbff, 0.3 );
dlight.position.x = 0;
dlight.position.y = 750;
dlight.position.z = 0;
dlight.castShadow = true;
dlight.shadow.camera.top = 2500;
dlight.shadow.camera.bottom = - 2500;
dlight.shadow.camera.left = - 2500;
dlight.shadow.camera.right = 2500;
dlight.shadow.camera.near = 1;
dlight.shadow.camera.far = 1000;
dlight.shadow.mapSize.set( 2048, 2048 );
- 如果您只是将
gltf.scene.castShadow
设置为 true
,则加载的 glTF
资源不会投射阴影。您必须对所有网格递归执行此操作。
gltf.scene.traverse( function ( object ) {
if ( object.isMesh ) object.castShadow = true;
} );
- 您在 GitHub 存储库中的资产路径错误。例如。而不是
/assets/3d_models/torii_gate/scene.gltf
应该是 ../assets/3d_models/torii_gate/scene.gltf
.
- 浏览器控制台中记录了一些弃用警告。我建议您像这样配置渲染器(也可能不要更改默认阴影贴图类型):
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
- 由于
MeshBasicMaterial
是不发光的 material,它无法接收阴影。这意味着你应该使用例如MeshPhongMaterial
用于您的瓷砖和地板,否则您将看不到任何阴影。
我正在通过做一些游戏来学习 threejs。我能够渲染场景中的所有模型并添加一些灯光,现在很完美, 但是当我尝试在飞机上投射和接收阴影时。场景中物体的阴影没有渲染。
我不明白我哪里做错了。
下面是代码
请看一下,帮我解决问题。
import { OrbitControls } from '../assets/js/OrbitControls.js';
import { GLTFLoader } from '../assets/js/GLTFLoader.js';
import { OBJLoader } from '../assets/js/OBJLoader.js';
import { MTLLoader } from '../assets/js/MTLLoader.js';
const extrudeSettings = { depth: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 };
const logo = {
position : {
top: 750,
back: -2000,
},
title: " Exhibition !!!",
color: 0x006699
};
var camera, scene, renderer, man_walk, mixer, action, keyboard, controls, door, mixerG, mixerB;
var mixerW = new THREE.AnimationMixer();
var man_walk = new THREE.Scene();
var clock = new THREE.Clock();
var gltfLoader = new GLTFLoader();
var objLoader = new OBJLoader();
init();
animate();
function init(){
// RENDERER
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.gammaOutput = true
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.BasicShadowMap;
document.body.appendChild(renderer.domElement);
// SCENE
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xC3D8D6 );
// scene.fog = new THREE.Fog( 0xffffff, 0, 750 );
// CAMERA
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.y = 250;
camera.position.z = 2090;
// LIGHTS
const light = new THREE.AmbientLight(0xffffff);
light.position.set = (0,100,100);
light.castShadow = true;
scene.add(light);
var dlight = new THREE.DirectionalLight( 0xaabbff, 0.3 );
dlight.position.x = 0;
dlight.position.y = 250;
dlight.position.z = 2500;
dlight.castShadow = true;
scene.add( dlight );
// KEY EVENTS
keyboard = new THREEx.KeyboardState();
// console.log(keyboard);
// // ORBIT CONTROLS
// controls = new OrbitControls(camera, renderer.domElement);
// controls.enableDampling = true;
// controls.campingFactor = 0.25;
// controls.enableZoom = true;
ExhibitionLogo()
getAlternateTiles();
getFloorMaterialByImage();
loadDoor();
loadTent();
loadSchoolGirl();
loadCollegeBoy()
loadMan();
// loadIntroModel();
loadFrame();
}
function loadDoor(){
// objLoader.load('/assets/3d_models/Doorway/Doorway.obj', object => {
// object.traverse(function (child) {
// if (child.type == "Mesh") {
// child.material = new THREE.MeshNormalMaterial();
// }
// });
// door=object;
// scene.add(object);
// object.rotation.z = -Math.PI / 2;
// object.rotation.x = -Math.PI / 2;
// object.scale.multiplyScalar(50);
// object.position.z = 1000
// });
gltfLoader.load('/assets/3d_models/torii_gate/scene.gltf', gltf => {
var door = gltf.scene;
door.position.set(0, 250, 1050);
door.scale.set(500,400,500);
door.rotateY(210.5);
scene.add(door);
});
}
function loadMan(){
gltfLoader.load('/assets/3d_models/boy_animated/scene.gltf', gltf => {
man_walk = gltf.scene;
man_walk.position.set(0, 0, 2050);
man_walk.rotateY(210.5);
gltf.scene.castShadow = true;
scene.add(man_walk);
mixer = new THREE.AnimationMixer(man_walk);
mixer.clipAction(gltf.animations[0]).play();
});
}
function loadWoman(){
gltfLoader.load('/assets/3d_models/woman/scene.gltf', gltf => {
var woman = gltf.scene;
woman.position.set(-300, 0, -500);
scene.add(woman);
gltf.scene.castShadow = true;
mixerW = new THREE.AnimationMixer(woman);
mixerW.clipAction(gltf.animations[0]).play();
var box = new THREE.Box3().setFromObject(woman);
console.log(box)
var text1 = makeTextSprite("Hello, Welcome to Gallery. This will take you to SOMs world");
scene.add(text1);
text1.position.set(-300, box.max.y + 20, -500);
text1.scale.set(150,100,1);
});
}
function loadTent(){
gltfLoader.load('/assets/3d_models/single_edition_tent/scene.gltf', gltf => {
var tent = gltf.scene;
tent.rotateY(10);
tent.scale.set(130,120,100);
tent.position.set(-300, 0, -900);
gltf.scene.castShadow = true;
scene.add(tent);
// generateCircleStage(extrudeSettings);
generateHexagonStage(extrudeSettings, -300, -900);
});
loadWoman();
}
function loadSchoolGirl() {
gltfLoader.load('/assets/3d_models/girl_idle/scene.gltf', gltf => {
gltf.scene.position.set(-1300, 100, 0);
gltf.scene.rotateY(10);
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(60);
gltf.scene.castShadow = true;
mixerG = new THREE.AnimationMixer(gltf.scene);
mixerG.clipAction(gltf.animations[0]).play();
});
}
function loadCollegeBoy() {
gltfLoader.load('/assets/3d_models/levi_boy_stylish/scene.gltf', gltf => {
gltf.scene.position.set(60, 0, 60)
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(50);
gltf.scene.castShadow = true;
mixerB = new THREE.AnimationMixer(gltf.scene);
mixerB.clipAction(gltf.animations[0]).play();
});
}
function loadIntroModel() {
gltfLoader.load('/assets/3d_models/cute_boy/scene.gltf', gltf => {
var box = new THREE.Box3().setFromObject(gltf.scene);
gltf.scene.position.z = (box.max.z - box.min.z) / 2;
gltf.scene.position.x = -(box.max.x - box.min.x) / 2;
gltf.scene.position.y = 50;
scene.add(gltf.scene);
gltf.scene.scale.multiplyScalar(30);
});
}
function loadFrame() {
gltfLoader.load('/assets/3d_models/photo/scene.gltf', gltf => {
gltf.scene.position.set(1950, 150, -600)
gltf.scene.scale.multiplyScalar(200);
gltf.scene.traverse( function ( child ) {
if (child.type == "Mesh") {
var newTexture = new THREE.TextureLoader().load( '/assets/img/man.jpg' );
newTexture.encoding = THREE.sRGBEncoding;
newTexture.flipY = false;
child.material.map = newTexture;
child.material.needsUpdate = true;
child.material.map.needsUpdate = true;
}
});
gltf.scene.rotateY(100);
gltf.scene.castShadow = true;
scene.add(gltf.scene);
});
}
// Animate
function animate() {
requestAnimationFrame(animate);
var delta = clock.getDelta(); // seconds.
var rotateAngle = Math.PI / 2 * delta;
mixerW.update(delta);
mixerG.update(delta*5);
mixerB.update(delta*5);
render();
updateMan();
}
function updateMan(){
var delta = clock.getDelta(); // seconds.
var rotateAngle = Math.PI / 2 * delta;
mixerW.update(delta);
var moveDistance = 550 * delta; // 100 pixels per second
var rotateAngle = Math.PI / 2 * delta; // pi/2 radians (90 degrees) per second
if ( keyboard.pressed("a") ){
man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), rotateAngle);
}
if ( keyboard.pressed("d") ){
man_walk.rotateOnAxis(new THREE.Vector3(0,1,0), -rotateAngle);
}
if ( keyboard.pressed("w") ){
man_walk.translateZ(moveDistance);
mixer.update(delta*5);
}
if ( keyboard.pressed("s") ){
man_walk.translateZ(-moveDistance);
mixer.update(delta*5);
}
var relativeCameraOffset = new THREE.Vector3(0,220,-600);
var cameraOffset = relativeCameraOffset.applyMatrix4( man_walk.matrixWorld );
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(man_walk.position);
}
function render()
{
// controls.update();
renderer.render( scene, camera );
}
/********************************** START : FLOOR *************************************/
function getAlternateTiles() {
var segments = 50;
var geometry = new THREE.PlaneGeometry(5000, 5000, segments, segments);
geometry.rotateX( - Math.PI / 2 );
var materialEven = new THREE.MeshBasicMaterial({color: 0x85A95D});
var materialOdd = new THREE.MeshBasicMaterial({color: 0x93BC54});
// #485C64
var materials = [materialEven, materialOdd];
for(var x=0; x<segments; x++) {
for(var y=0; y<segments; y++) {
var i = x * segments + y;
var j = 2 * i;
geometry.faces[ j ].materialIndex = geometry.faces[ j + 1 ].materialIndex = (x + y) % 2;
}
}
var mesh = new THREE.Mesh(geometry, materials);
mesh.receiveShadow = true;
scene.add(mesh);
}
function getFloorMaterialByImage() {
var geometry = new THREE.PlaneGeometry( 500, 5000, 10, 10 );
geometry.rotateX( - Math.PI / 2 );
// lightwood.jpg, whitetiles.jpg, floorline.jpg, woodsheet.jpg, Carpet.jpeg, Wood_Bamboo.jpeg, corporate.jpg
var floorTexture = new THREE.TextureLoader().load( '/assets/img/corporate.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(500, 500);
var material = new THREE.MeshBasicMaterial({map: floorTexture});
// Vertical road
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0,0.2,0);
mesh.receiveShadow = true;
scene.add(mesh);
// Horizontal road
var mesh1 = mesh.clone();
mesh1.rotateY(Math.PI / 2);
mesh1.receiveShadow = true;
scene.add(mesh1);
//cube
var geometry1 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material1 = new THREE.MeshPhongMaterial( {color: 0x8B0000} );
var cube = new THREE.Mesh( geometry1, material1 );
cube.scale.set(150,10,100);
cube.position.set(0,1,-2000);
var geometry2 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material2 = new THREE.MeshPhongMaterial( {color: 0x191970} );
var cube2 = new THREE.Mesh( geometry2, material2 );
cube2.scale.set(100,10,150);
cube2.position.set(2000,0,0);
var geometry3 = new THREE.BoxBufferGeometry( 10, 3, 10 );//#8B0000
var material3 = new THREE.MeshPhongMaterial( {color: 0x006400} );
var cube3 = new THREE.Mesh( geometry3, material3 );
cube3.scale.set(100,10,150);
cube3.position.set(-2000,0,0);
cube.receiveShadow = true;
cube2.receiveShadow = true;
cube3.receiveShadow = true;
scene.add(cube2);
scene.add(cube3);
scene.add( cube );
}
/********************************** END : FLOOR *************************************/
/********************************** START : GALLERY LOGO *************************************/
function ExhibitionLogo() {
var loader = new THREE.FontLoader();
loader.load( '/assets/font/gentilis_bold.typeface.json', function ( font ) {
var xMid, text;
var matDark = new THREE.LineBasicMaterial( {
color: logo.color,
side: THREE.DoubleSide
} );
var matLite = new THREE.MeshBasicMaterial( {
color: logo.color,
transparent: true,
opacity: 0.4,
side: THREE.DoubleSide
} );
var shapes = font.generateShapes( logo.title, 1000 );
var geometry = new THREE.ShapeBufferGeometry( shapes );
geometry.computeBoundingBox();
xMid = - 0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
geometry.translate( xMid, 0, 0 );
text = new THREE.Mesh( geometry, matLite );
text.position.z = logo.position.back;
text.position.y = logo.position.top;
scene.add( text );
var lineText = new THREE.Object3D();
for ( var i = 0; i < shapes.length; i ++ ) {
var shape = shapes[ i ];
var points = shape.getPoints();
var geometry = new THREE.BufferGeometry().setFromPoints( points );
geometry.translate( xMid, logo.position.top, 0 );
var lineMesh = new THREE.Line( geometry, matDark );
lineText.add( lineMesh );
lineText.position.z = logo.position.back + 50;
}
scene.add( lineText );
});
}
/********************************** END : GALLERY LOGO *************************************/
/********************************** START : TEXT TO SHOW WHEN USER APPROACHES PERSONS *************************************/
function makeTextSprite(message, parameters) {
// Canvas for text
const textCanvas = prepareTextCanvas(message, parameters);
// Canvas Texture
const texture = new THREE.CanvasTexture(textCanvas);
texture.minFilter = THREE.LinearFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
// Sprite Material
const textMaterial = new THREE.SpriteMaterial({
map: texture,
transparent: true,
});
// Sprite
const textSprite = new THREE.Sprite(textMaterial);
return textSprite;
}
function prepareTextCanvas(message, parameters) {
if ( parameters === undefined ) parameters = {};
var fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "Calibri";
var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 16;
var borderThickness = parameters.hasOwnProperty("borderThickness") ? parameters["borderThickness"] : 4;
var borderColor = parameters.hasOwnProperty("borderColor") ?parameters["borderColor"] : "white";
var backgroundColor = parameters.hasOwnProperty("backgroundColor") ?parameters["backgroundColor"] : "blue";
var textColor = parameters.hasOwnProperty("textColor") ?parameters["textColor"] : "white";
var maxWidth = 280;
var lineHeight = 20;
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var x = (canvas.width - maxWidth) / 2; // default canvas width-300, height-150
var y = 35;
context.font = fontsize + "px " + fontface;
context.fillStyle = backgroundColor;
context.strokeStyle = borderColor;
context.lineWidth = borderThickness;
context.fillRect(0, 15, canvas.width, lineHeight + y);
context.fillStyle = textColor;
wrapText(context, message, x, y, maxWidth, lineHeight);
return context.canvas;
}
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
}
/************************************* END : TEXT TO SHOW WHEN USER APPROACHES PERSONS *************************************/
/************************************* START : HEXAGON STAGES *************************************/
function generateHexagonStage(extrudeSettings, x, z) {
generate3DHexagon(100, extrudeSettings, 0x00f000, x, 8, z)
generate3DHexagon(80, extrudeSettings, 0xff00ff, x, 16, z)
generate3DHexagon(60, extrudeSettings, 0x00f000, x, 24, z)
}
function generate3DHexagon(size, extrudeSettings, color, x, y, z) {
var hexShape = getHexagonShape(size);
var hexagon = getHexagonMesh(hexShape, extrudeSettings, color, x, y, z)
scene.add(hexagon);
}
function getHexagonMesh(shape, extrudeSettings, color, x, y, z) {
var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color } ) );
mesh.position.set( x, y, z - 75 );
mesh.rotation.x = Math.PI/2;
return mesh;
}
function getHexagonShape(cellSize) {
// create base shape used for building geometry
var i, verts = [];
// create the skeleton of the hex
for (i = 0; i < 6; i++) {
verts.push(createVertex(i, cellSize));
}
// copy the verts into a shape for the geometry to use
var cellShape = new THREE.Shape();
cellShape.moveTo(verts[0].x, verts[0].y);
for (i = 1; i < 6; i++) {
cellShape.lineTo(verts[i].x, verts[i].y);
}
cellShape.lineTo(verts[0].x, verts[0].y);
cellShape.autoClose = true;
return cellShape
}
function createVertex(i, cellSize) {
var angle = (Math.PI * 2 / 6) * i;
return new THREE.Vector3((cellSize * Math.cos(angle)), (cellSize * Math.sin(angle)), 0);
}
/************************************* END : HEXAGON STAGES *************************************/
/************************************* START : CIRCLE STAGES *************************************/
function generateCircleStage(extrudeSettings) {
generate3DCircle(100, extrudeSettings, 0x00f000, 8)
generate3DCircle(80, extrudeSettings, 0xffffff, 16)
generate3DCircle(60, extrudeSettings, 0x00f000, 24)
}
function generate3DCircle(radius, extrudeSettings, color, y) {
var circleShape = getCircleShape(radius);
var circle = getCircleMesh( circleShape, extrudeSettings, color, 0, y, 0, 0, 0, 0, 1 );
circle.rotation.x = Math.PI/2;
scene.add(circle);
}
function getCircleMesh( shape, extrudeSettings, color, x, y, z, rx, ry, rz, s ) {
// extruded shape
var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: color } ) );
mesh.position.set( x, y, z - 75 );
mesh.rotation.set( rx, ry, rz );
// mesh.scale.set( s, s, s );
return mesh
}
function getCircleShape(radius) {
var circleShape = new THREE.Shape()
.moveTo( 0, radius )
.quadraticCurveTo( radius, radius, radius, 0 )
.quadraticCurveTo( radius, - radius, 0, - radius )
.quadraticCurveTo( - radius, - radius, - radius, 0 )
.quadraticCurveTo( - radius, radius, 0, radius );
return circleShape
}
/************************************* END : CIRCLE STAGES *************************************/
请从这里找到完整代码:
我已经离线测试了您的代码,但存在多个问题和运行时错误:
AmbientLight
不投射阴影。设置castShadow
将产生运行时错误。- 您没有为您的
DirectionalLight
实例正确配置阴影平截头体。使用此代码试试:
var dlight = new THREE.DirectionalLight( 0xaabbff, 0.3 );
dlight.position.x = 0;
dlight.position.y = 750;
dlight.position.z = 0;
dlight.castShadow = true;
dlight.shadow.camera.top = 2500;
dlight.shadow.camera.bottom = - 2500;
dlight.shadow.camera.left = - 2500;
dlight.shadow.camera.right = 2500;
dlight.shadow.camera.near = 1;
dlight.shadow.camera.far = 1000;
dlight.shadow.mapSize.set( 2048, 2048 );
- 如果您只是将
gltf.scene.castShadow
设置为true
,则加载的glTF
资源不会投射阴影。您必须对所有网格递归执行此操作。
gltf.scene.traverse( function ( object ) {
if ( object.isMesh ) object.castShadow = true;
} );
- 您在 GitHub 存储库中的资产路径错误。例如。而不是
/assets/3d_models/torii_gate/scene.gltf
应该是../assets/3d_models/torii_gate/scene.gltf
. - 浏览器控制台中记录了一些弃用警告。我建议您像这样配置渲染器(也可能不要更改默认阴影贴图类型):
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
- 由于
MeshBasicMaterial
是不发光的 material,它无法接收阴影。这意味着你应该使用例如MeshPhongMaterial
用于您的瓷砖和地板,否则您将看不到任何阴影。