작성
·
53
·
수정됨
0
강의 코드를 그대로 따라하면 mesh 색이 어두운 회색으로 표현되고 그림자가 생기지 않는 문제가 있습니다.
그래서 SpotLight의 위치와 강도를 조정했더니 그림자는 나타나는데 강의영상처럼 모든 집에대한 그림자가 동일하게 나오는 것이 아니라 맨 처음 집에 대한 그림자만 선명히 나타납니다!
빛을 한방향에서만 쏘기 때문에 저 처럼 표현되는게 맞는 것 같은데, 강의영상처럼 모두 동일한 그림자를 표현하려면 어떻게 해야할까요..?
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/Addons.js';
import { House } from './House';
import gsap from 'gsap';
// ----- 주제: 스크롤에 따라 움직이는 3D 페이지
// Renderer
const canvas = document.querySelector('#three-canvas');
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);
renderer.shadowMap.enabled = true; // 그림자 설정, mesh도 함께 설정해야함
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 그림자 부드럽게
// Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color('white'); // 백그라운드 하얀색
// Camera
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(-5, 2, 25);
scene.add(camera);
// Light
const ambientLight = new THREE.AmbientLight('white', 2);
scene.add(ambientLight);
const spotLight = new THREE.SpotLight('white', 500);
spotLight.position.set(-5, 10, 30);
// 그림자 설정
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024; // 그림자 퀄리티 조정(성능에 크게 영향을 미치지 않는 정도)
spotLight.shadow.mapSize.height = 1024; // 그림자 퀄리티 조정(성능에 크게 영향을 미치지 않는 정도)
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 1000;
scene.add(spotLight);
const spotLightHelper = new THREE.SpotLightHelper(spotLight, 'red');
scene.add(spotLightHelper);
// --- (2) HemisphereLight 추가 ---
// const hemiLight = new THREE.HemisphereLight('white', 'white', 2);
// scene.add(hemiLight);
const gltfLoader = new GLTFLoader();
// Mesh
const floorMesh = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100),
new THREE.MeshStandardMaterial({
color: 'white',
roughness: 0.4, // 필요에 따라 조절
metalness: 0.2, // 필요에 따라 조절
toneMapped: false,
}) // 강의에는 MeshStandartMaterial 사용했는데, 이거 사용시 floorMesh가 하얀색이 아닌 회색으로 보여서 변경
);
floorMesh.rotation.x = -Math.PI / 2; // 180//2 = 90도
floorMesh.receiveShadow = true; // floorMesh에 그림자가 그려지기 때문에 recieveShadow 사용
scene.add(floorMesh);
// 하우스를 통해 그림자가 만들어져야 하므로 -> castShadow
const houses = [];
houses.push(
new House({
gltfLoader,
scene,
modelSrc: '/models/house.glb',
x: -5,
z: 20,
height: 2,
})
);
houses.push(
new House({
gltfLoader,
scene,
modelSrc: '/models/house.glb',
x: 7,
z: 10,
height: 2,
})
);
houses.push(
new House({
gltfLoader,
scene,
modelSrc: '/models/house.glb',
x: -10,
z: 0,
height: 2,
})
);
houses.push(
new House({
gltfLoader,
scene,
modelSrc: '/models/house.glb',
x: 10,
z: -10,
height: 2,
})
);
houses.push(
new House({
gltfLoader,
scene,
modelSrc: '/models/house.glb',
x: -5,
z: -20,
height: 2,
})
);
// 그리기
const clock = new THREE.Clock();
function draw() {
const delta = clock.getDelta();
renderer.render(scene, camera);
renderer.setAnimationLoop(draw);
spotLightHelper.update();
}
let currentSection = 0;
function setSection() {
// console.log('setSection 실행!'); // setSection 스크롤할때마다 실행됨
const newSection = Math.round(window.scrollY / window.innerHeight); // 0,1,2,3,4
if (currentSection !== newSection) {
console.log('animation!'); // section값이 바뀔때만 애니메이션이 동작하도록
gsap.to(camera.position, {
duration: 1,
x: houses[newSection].x,
z: houses[newSection].z + 5,
});
currentSection = newSection;
}
}
function setSize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
// 이벤트
window.addEventListener('scroll', setSection);
window.addEventListener('resize', setSize);
draw();
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 김혜빈님께서 질문하신 내용에 대해 답변드리겠습니다.
Three.js에서 여러 개의 물체에 대해 그림자를 자연스럽게 표현하려면 몇 가지 사항을 점검해볼 필요가 있습니다.
조명 설정: SpotLight와 같은 특정 조명은 setup에 따라 그림자를 다르게 표현할 수 있습니다. 강의와 다르게 표현되는 이유는 조명 위치 및 각도 설정이 다를 수 있기 때문입니다. 그림자가 강의와 같이 모두 동일하게 나오도록 하려면, 각도나 위치를 조정하여 조명 광원을 더 넓게 설정하거나, 추가적인 조명을 사용할 수 있습니다.
그림자 속성 확인: 각 Mesh가 castShadow
와 receiveShadow
속성을 올바르게 설정했는지 확인하세요. 그림자는 일반적으로 빛과 대상 객체 모두에 castShadow
속성이 필요하고, 지표면과 같은 받는 면에는 receiveShadow
속성이 필요합니다.
장면 내 요소들의 구성: 현재 장면의 구성 요소가 어떤 방식으로 배치되어 있는지 확인해보세요. 적절한 그림자를 위해, 조명이 충분히 모든 물체에 닿을 수 있도록 배치해야 합니다.
빛의 강도: 빛의 강도를 더 높이거나, 총 사용 가능한 그림자 맵의 해상도를 올려 물체에 그림자가 고르게 드리워지는지 확인하세요.
아래 링크를 참조하여 추가적인 도움 받으실 수 있습니다:
해당 페이지에서 비슷한 질문 및 답변을 잘 정리해두었다고 하니 참고해보시면 좋겠습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.