반응형
1. poly haven
https://polyhaven.com/a/shanghai_bund
위 사이트에서 HDRIs 파일을 자유롭게 가져올 수 있다.
// RGBE Loader
var loader = new RGBELoader()
loader.setDataType(THREE.UnsignedByteType)
loader.load('../static/ex-14/shanghai_bund_1k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture //배경
scene.environment = texture //텍스처
})
2. glb 파일 연결
1) GLTFLoader를 import 한다.
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js'
참고 : https://threejs.org/docs/#examples/en/loaders/GLTFLoader
2) 예제 코드를 입력 후 Optional 코드를 지워준다.
//GLTFLoader 예제 코드
// Instantiate a loader
const GLTFloader = new GLTFLoader();
// Load a glTF resource
GLTFloader.load(
// resource URL
'../static/ex-14/skull.glb',
// called when the resource is loaded
function ( gltf ) {
scene.add( gltf.scene );
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Group
gltf.scenes; // Array<THREE.Group>
gltf.cameras; // Array<THREE.Camera>
gltf.asset; // Object
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
해골 광원의 경우 RGBELoader에 의한 것이다. 아래가 코드이다.
// RGBE Loader
var RGBEloader = new RGBELoader()
RGBEloader.setDataType(THREE.UnsignedByteType)
RGBEloader.load('../static/ex-14/shanghai_bund_1k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture //배경
scene.environment = texture //광원 -> 여기
})
3. glb 오브젝트 설정
1) GLTF 오브젝트 변수 설정
function ( gltf ) {
scene.add( gltf.scene );
const GLTFObj = gltf.scene //여기
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Group
gltf.scenes; // Array<THREE.Group>
gltf.cameras; // Array<THREE.Camera>
gltf.asset; // Object
},
GLTF오브젝트 변수를 설정한다. scene에 추가한 gltf 요소를 할당해주면 된다.
2) 크기 조절
GLTFObj.scale.set(0.5, 0.5, 0.5)
3) position 조절
GLTFObj.position.y = 1
4. 그림자 및 머터리얼 추가
1) 그림자 추가
GLTFObj.traverse(function(obj){
if(obj.isMesh){
obj.castShadow = true
}
})
2) 오브젝트에 그림자 받기
GLTFObj.traverse(function(obj){
if(obj.isMesh){
obj.castShadow = true
obj.receiveShadow = true //여기
}
})
정수리 부분에 그림자를 받는 것을 볼 수 있다.
3) 머터리얼 적용 (색깔)
const GLTFMaterial = new THREE.MeshPhysicalMaterial({
color: 0x004fff,
})
다른 Material 적용하듯 GLTF도 똑같이 선언한다.
GLTFObj.traverse(function(obj){
if(obj.isMesh){
obj.material = GLTFMaterial //여기
obj.castShadow = true
obj.receiveShadow = true
}
})
GLTFObj의 traverse 안에 material 요소로 GLTFMaterial을 적용해주면 된다.
4) 머터리얼 적용 (메탈 효과)
const GLTFMaterial = new THREE.MeshPhysicalMaterial({
color: 0x004fff,
metalness:0.9
})
5) 머터리얼 적용 (거칠기)
const GLTFMaterial = new THREE.MeshPhysicalMaterial({
color: 0x004fff,
metalness:0.9,
roughness: 0.5,
})
5. 그룹 추가
1) Object3D
let GLTFObjGroup = new THREE.Object3D()
2) 그룹 관리
const GLTFloader = new GLTFLoader();
let GLTFObjGroup = new THREE.Object3D()
// Load a glTF resource
GLTFloader.load(
// resource URL
'../static/ex-14/skull.glb',
// called when the resource is loaded
function ( gltf ) {
const GLTFObj = gltf.scene
GLTFObj.traverse(function(obj){
if(obj.isMesh){
obj.material = GLTFMaterial
obj.castShadow = true
obj.receiveShadow = true
}
})
GLTFObj.scale.set(0.5, 0.5, 0.5)
GLTFObj.position.y = 0.5
GLTFObjGroup.add(GLTFObj);
scene.add( GLTFObjGroup );
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Group
gltf.scenes; // Array<THREE.Group>
gltf.cameras; // Array<THREE.Camera>
gltf.asset; // Object
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
GLTFObjGroup에 오브젝트를 넣고, scene에 GLTFObjGroup가 로드되도록 구성한다.
3) 애니메이션 추가
function animate() {
requestAnimationFrame(animate) //인자로 받은 함수 animate를 반복 실행
GLTFObjGroup.rotation.y += 0.01 //여기
renderer.render(scene, camera)
}
animate()
6. 자동차 도입
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { WEBGL } from './webgl'
if (WEBGL.isWebGLAvailable()) {
// 장면 추가
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x111111)
scene.fog = new THREE.Fog(0x111111, 4, 12)
// scene.add(new THREE.AxesHelper(5)) // 중심점 표현
// 카메라 추가
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
camera.position.z = 3
camera.lookAt(0, 0, 0)
// 렌더러 추가
const renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
})
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
renderer.shadowMap.enabled = true
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.toneMappingExposure = 1
// 컨트롤
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.maxPolarAngle = Math.PI / 2 - 0.1 // 각도 제한
controls.minDistance = 2
controls.maxDistance = 10
controls.target.set(0, 0, -0.2)
controls.update()
// 텍스처 추가
const textureLoader = new THREE.TextureLoader()
const textureBaseColor = textureLoader.load(
'../static/img/stone_basecolor.jpg'
)
const textureNormalMap = textureLoader.load(
'../static/img/stone_normal.jpg'
)
const textureHeightMap = textureLoader.load(
'../static/img/stone_height.png'
)
const textureRoughnessMap = textureLoader.load(
'../static/img/stone_roughness.jpg'
)
// RGBE Loader
var RGBEloader = new RGBELoader()
RGBEloader.setDataType(THREE.UnsignedByteType)
RGBEloader.load('../static/ex-14/royal_esplanade_2k.hdr', function (texture) {
texture.mapping = THREE.EquirectangularReflectionMapping
// scene.background = texture //배경
scene.environment = texture //광원
})
const GLTFMaterial = new THREE.MeshPhysicalMaterial({
color: 0x004fff,
map: textureBaseColor,
// normalMap: textureNormalMap,
roughnessMap: textureRoughnessMap,
metalness: 0.9,
roughness: 0.5,
// wireframe: true,
})
// Instantiate a loader
const GLTFloader = new GLTFLoader()
let GLTFObjGroup = new THREE.Object3D()
GLTFloader.load(
// resource URL
'../static/ex-14/car.glb',
// called when the resource is loaded
function (gltf) {
const GLTFObj = gltf.scene
GLTFObj.traverse(function (obj) {
if (obj.isMesh) {
obj.material = GLTFMaterial
obj.castShadow = true
obj.receiveShadow = true
}
})
GLTFObj.scale.set(0.3, 0.3, 0.3)
GLTFObj.position.y = -0.4
GLTFObjGroup.add(GLTFObj)
scene.add(GLTFObjGroup)
},
// called while loading is progressing
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
},
// called when loading has errors
function (error) {
console.log('An error happened')
}
)
//바닥 추가
const planeGeometry = new THREE.PlaneGeometry(30, 30, 1, 1)
const planeMaterial = new THREE.MeshPhysicalMaterial({
color: 0x111111,
map: textureBaseColor,
normalMap: textureNormalMap,
displacementMap: textureHeightMap,
displacementScale: 0.001,
roughnessMap: textureRoughnessMap,
metalness: 0.5,
roughness: 0.5,
clearcoat: 0.1,
})
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.rotation.x = -0.5 * Math.PI
plane.position.y = -0.5
scene.add(plane)
plane.receiveShadow = true
// 빛
const ambientLight = new THREE.AmbientLight(0x004fff, 0.8)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
directionalLight.position.set(-1, 3, 0.5)
scene.add(directionalLight)
directionalLight.castShadow = true
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight2.position.set(0.5, 2.5, 1)
scene.add(directionalLight2)
directionalLight2.castShadow = true
function animate() {
requestAnimationFrame(animate) //인자로 받은 함수 animate를 반복 실행
// GLTFObjGroup.rotation.y += 0.01
renderer.render(scene, camera)
}
animate()
// 반응형 처리
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
window.addEventListener('resize', onWindowResize)
} else {
var warning = WEBGL.getWebGLErrorMessage()
document.body.appendChild(warning)
}
반응형
'FE > Three.js' 카테고리의 다른 글
링고타운 이야기 - R3F 물리엔진 뼈대 제거 (0) | 2023.11.01 |
---|---|
Three.js 11일차 (Skybox / Side / AxesHelper) (0) | 2023.10.18 |
Three.js 10일차 (안개 효과) (0) | 2023.10.18 |
Three.js 9일차 (OrbitControls) (0) | 2023.10.18 |
Three.js 8일차 (그림자) (0) | 2023.10.18 |