<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - car</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
<style>
body {
color: #bbbbbb;
background: #333333;
}
a {
color: #08f;
}
.colorPicker {
display: inline-block;
margin: 0 10px
}
</style>
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> car materials<br/>
Ferrari 458 Italia model by <a href="https://sketchfab.com/models/57bf6cc56931426e87494f554df1dab6" target="_blank" rel="noopener">vicent091036</a>
<br><br>
<span class="colorPicker"><input id="body-color" type="color" value="#ff0000"></input><br/>Body</span>
<span class="colorPicker"><input id="details-color" type="color" value="#ffffff"></input><br/>Details</span>
<span class="colorPicker"><input id="glass-color" type="color" value="#ffffff"></input><br/>Glass</span>
</div>
<div id="container"></div>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
//stats查看threejs渲染帧率
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
let camera, scene, renderer;
let stats;
let grid;
let controls;
const wheels = [];
function init() {
const container = document.getElementById( 'container' );
// 创建渲染器对象
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
//定义输出画布的尺寸
renderer.setSize( window.innerWidth, window.innerHeight );
//动画
renderer.setAnimationLoop( render );
//塑造出更加真实的效果
renderer.toneMapping = THREE.ACESFilmicToneMapping;
//色调映射的曝光级别
renderer.toneMappingExposure = 0.85;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize );
//创建stats对象
stats = new Stats();
container.appendChild( stats.dom );
//创建相机(透视相机)模拟人眼所看到的的画面
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 100 );
//设置相机的位置
camera.position.set( 4.25, 1.4, - 4.5 );
//设置相机控件轨道控制器
controls = new OrbitControls( camera, container );
// 能够将相机向外移动多少(仅适用于PerspectiveCamera)
controls.maxDistance = 9;
//够垂直旋转的角度的上限
controls.maxPolarAngle = THREE.MathUtils.degToRad( 90 );
controls.target.set( 0, 0.5, 0 );
controls.update();
//创建场景
scene = new THREE.Scene();
//设置背景颜色
scene.background = new THREE.Color( 0x333333 );
//设置环境贴图
scene.environment = new RGBELoader().load( 'textures/equirectangular/venice_sunset_1k.hdr' );
scene.environment.mapping = THREE.EquirectangularReflectionMapping;
//雾
scene.fog = new THREE.Fog( 0x333333, 10, 15 );
//创建坐标格辅助对象
grid = new THREE.GridHelper( 20, 40, 0xffffff, 0xffffff );
//设置透明度
grid.material.opacity = 0.2;
//渲染此材质是否对深度缓冲区有任何影响
grid.material.depthWrite = false;
//开启透明度
grid.material.transparent = true;
//添加到场景
scene.add( grid );
// materials
//设置车身的材质 颜色(红色) 金属度 粗糙度
//物体表面清漆层(可以用来模拟物体表面一层透明图层,就好比你在物体表面刷了一层透明清漆,喷了点水)
//清漆层的粗糙度
const bodyMaterial = new THREE.MeshPhysicalMaterial( {
color: 0xff0000, metalness: 1.0, roughness: 0.5, clearcoat: 1.0, clearcoatRoughness: 0.03
} );
//设置车轮与车座细节的材质属性
const detailsMaterial = new THREE.MeshStandardMaterial( {
color: 0xffffff, metalness: 1.0, roughness: 0.5
} );
//设置挡风玻璃的材质属性 颜色 金属度 粗糙度 透光率(透射率)
const glassMaterial = new THREE.MeshPhysicalMaterial( {
color: 0xffffff, metalness: 0.25, roughness: 0, transmission: 1.0
} );
//将更改的颜色体现出来
const bodyColorInput = document.getElementById( 'body-color' );
bodyColorInput.addEventListener( 'input', function () {
bodyMaterial.color.set( this.value );
} );
const detailsColorInput = document.getElementById( 'details-color' );
detailsColorInput.addEventListener( 'input', function () {
detailsMaterial.color.set( this.value );
} );
const glassColorInput = document.getElementById( 'glass-color' );
glassColorInput.addEventListener( 'input', function () {
glassMaterial.color.set( this.value );
} );
// Car
const shadow = new THREE.TextureLoader().load( 'models/gltf/ferrari_ao.png' );
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( 'jsm/libs/draco/gltf/' );
const loader = new GLTFLoader();
loader.setDRACOLoader( dracoLoader );
loader.load( 'models/gltf/ferrari.glb', function ( gltf ) {
const carModel = gltf.scene.children[ 0 ];
carModel.getObjectByName( 'body' ).material = bodyMaterial;
carModel.getObjectByName( 'rim_fl' ).material = detailsMaterial;
carModel.getObjectByName( 'rim_fr' ).material = detailsMaterial;
carModel.getObjectByName( 'rim_rr' ).material = detailsMaterial;
carModel.getObjectByName( 'rim_rl' ).material = detailsMaterial;
carModel.getObjectByName( 'trim' ).material = detailsMaterial;
carModel.getObjectByName( 'glass' ).material = glassMaterial;
wheels.push(
carModel.getObjectByName( 'wheel_fl' ),
carModel.getObjectByName( 'wheel_fr' ),
carModel.getObjectByName( 'wheel_rl' ),
carModel.getObjectByName( 'wheel_rr' )
);
// shadow
//渲染出车子的底部阴影
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry( 0.655 * 4, 1.3 * 4 ),
new THREE.MeshBasicMaterial( {
map: shadow, blending: THREE.MultiplyBlending, toneMapped: false, transparent: true
} )
);
//将该阴影旋转90度 与地面平齐
mesh.rotation.x = - Math.PI / 2;
//这个值将使得scene graph(场景图)中默认的的渲染顺序被覆盖, 即使不透明对象和透明对象保持独立顺序。 渲染顺序是由低到高来排序的,默认值为0。
mesh.renderOrder = 2;
//将阴影添加到模型中
carModel.add( mesh );
//将模型添加到场景中
scene.add( carModel );
} );
}
//设置渲染的画布随着窗口尺寸的大小变化
function onWindowResize() {
//全屏情况下:设置观察范围长宽比aspect为窗口宽高比
camera.aspect = window.innerWidth / window.innerHeight;
// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
camera.updateProjectionMatrix();
// 重置渲染器输出画布canvas尺寸
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
controls.update();
const time = - performance.now() / 1000;
for ( let i = 0; i < wheels.length; i ++ ) {
wheels[ i ].rotation.x = time * Math.PI * 2;
}
//坐标格辅助对象随着时间逐渐向后移动 造成车子往前走的景象
grid.position.z = - ( time ) % 1;
//执行渲染操作
renderer.render( scene, camera );
stats.update();
}
init();
</script>
</body>
</html>
ThreeJS官方案例学习 webgl - materials - car
最新推荐文章于 2024-06-01 00:15:00 发布