我們在ThreeJS-3D教學(xué)二:基礎(chǔ)形狀展示中有簡單介紹過一些常用的材質(zhì),這次我們舉例來具體看下效果:
代碼是這樣的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.label {
font-size: 20px;
color: #000;
font-weight: 700;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="importmap">
{
"imports": {
"three": "../three-155/build/three.module.js",
"three/addons/": "../three-155/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
let stats, labelRenderer, gpuPanel, spotLight;
let camera, scene, renderer, controls, earth;
const group = new THREE.Group();
let widthImg = 200;
let heightImg = 200;
let time = 0;
init();
initHelp();
initLight();
axesHelperWord();
animate();
// 添加平面
addPlane();
addBox();
function addBox() {
/**
* 凹凸貼圖可以使紋理也有厚度,看起來更立體。凹凸貼圖一般使用一張灰度圖,設(shè)置成材料的bumpMap屬性
* */
const loader = new THREE.TextureLoader();
loader.load("../materials/line_images/stone.jpg", texture => {
loader.load("../materials/line_images/stone-bump.jpg",bumpTexture => {
const boxGeo = new THREE.BoxGeometry(60, 60, 2);
const material = new THREE.MeshStandardMaterial({
map: texture,
bumpMap: bumpTexture,
bumpScale: 1
});
const box = new THREE.Mesh(boxGeo,material);
box.position.set(-45, 10, 0);
box.castShadow = true;
scene.add(box);
});
});
/**
* 法向貼圖使用一張法向圖來表示紋理圖片某個點的法向量。即用一張圖片保存另一張圖片的法向量信息,
* 然后再在threejs中將這兩個圖片的信息合在一起,就形成了一個細節(jié)豐富的立體紋理
* 設(shè)置材質(zhì)的 normalMap 屬性
* */
loader.load("../materials/line_images/normal2.jpg", texture => {
loader.load("../materials/line_images/normal1.jpg", bumpTexture => {
const boxGeo = new THREE.BoxGeometry(60, 60, 2);
const material = new THREE.MeshStandardMaterial({
map: texture,
normalMap: bumpTexture
});
// material.normalScale.set(1, 1)
const box = new THREE.Mesh(boxGeo,material);
box.position.set(45, 10, 0);
box.castShadow = true;
scene.add(box);
});
});
// 高光貼圖
loader.load("../materials/line_images/earth.jpg",textureNormal => {
loader.load("../materials/line_images/earthSpec.png", textureSpec => {
const meterial = new THREE.MeshPhongMaterial({
shininess: 5, //高光部分的亮度,默認30
map: textureNormal, // 普通紋理貼圖
specularMap: textureSpec, // 高光貼圖
specular: '#fff' // 高光部分的顏色
});
/**
SphereGeometry(radius:浮點,widthSegments:整數(shù),heightSegments:整數(shù))
radius——球體半徑。默認值為1。
widthSegments—水平線段的數(shù)量。最小值為3,默認值為32。
heightSegments—垂直線段的數(shù)量。最小值為2,默認值為16。
*/
const earthGeo = new THREE.SphereGeometry(15, 50, 50);
earth = new THREE.Mesh(earthGeo, meterial);
earth.position.set(0, 15, 70);
earth.castShadow = true;
scene.add(earth);
});
});
}
function addPlane() {
// 創(chuàng)建一個平面 PlaneGeometry(width, height, widthSegments, heightSegments)
const planeGeometry = new THREE.PlaneGeometry(widthImg, heightImg, 1, 1);
// 創(chuàng)建 Lambert 材質(zhì):會對場景中的光源作出反應(yīng),但表現(xiàn)為暗淡,而不光亮。
const planeMaterial = new THREE.MeshPhongMaterial({
color: 0xb2d3e6,
side: THREE.DoubleSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
// 以自身中心為旋轉(zhuǎn)軸,繞 x 軸順時針旋轉(zhuǎn) 45 度
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(0, -4, 0);
plane.castShadow = true;
plane.receiveShadow = true;
scene.add(plane);
}
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 1000 );
camera.up.set(0, 1, 0);
camera.position.set(60, 40, 60);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
scene.background = new THREE.Color( '#ccc' );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
// 色調(diào)映射的曝光級別
renderer.toneMappingExposure = 1;
document.body.appendChild( renderer.domElement );
labelRenderer = new CSS2DRenderer();
labelRenderer.setSize( window.innerWidth, window.innerHeight );
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.pointerEvents = 'none';
document.getElementById( 'container' ).appendChild( labelRenderer.domElement );
controls = new OrbitControls( camera, renderer.domElement );
// 設(shè)置最大最小視距
controls.minDistance = 20;
controls.maxDistance = 1000;
window.addEventListener( 'resize', onWindowResize );
stats = new Stats();
stats.setMode(1); // 0: fps, 1: ms
document.body.appendChild( stats.dom );
gpuPanel = new GPUStatsPanel( renderer.getContext() );
stats.addPanel( gpuPanel );
stats.showPanel( 0 );
scene.add( group );
}
function initLight() {
const targetObject = new THREE.Object3D();
targetObject.position.set(0, 0, 0);
scene.add(targetObject);
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 80, 150);
spotLight.target = targetObject;
spotLight.angle = Math.PI / 4;
spotLight.intensity = 500;
spotLight.penumbra = 1;
spotLight.decay = 1;
spotLight.distance = 300;
// spotLight.map = textures['uv_grid_opengl.jpg'];
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 200;
spotLight.shadow.focus = 1;
scene.add(spotLight);
const lightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(lightHelper);
const AmbientLight = new THREE.AmbientLight(new THREE.Color('rgb(255, 255, 255)'));
scene.add( AmbientLight );
}
function initHelp() {
// const size = 100;
// const divisions = 5;
// const gridHelper = new THREE.GridHelper( size, divisions );
// scene.add( gridHelper );
// The X axis is red. The Y axis is green. The Z axis is blue.
const axesHelper = new THREE.AxesHelper( 100 );
scene.add( axesHelper );
}
function axesHelperWord() {
let xP = addWord('X軸');
let yP = addWord('Y軸');
let zP = addWord('Z軸');
xP.position.set(50, 0, 0);
yP.position.set(0, 50, 0);
zP.position.set(0, 0, 50);
}
function addWord(word) {
let name = `<span>${word}</span>`;
let moonDiv = document.createElement( 'div' );
moonDiv.className = 'label';
// moonDiv.textContent = 'Moon';
// moonDiv.style.marginTop = '-1em';
moonDiv.innerHTML = name;
const label = new CSS2DObject( moonDiv );
group.add( label );
return label;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
if (earth) {
time += 0.00005;
earth.rotateY(time);
}
stats.update();
controls.update();
labelRenderer.render( scene, camera );
renderer.render( scene, camera );
}
</script>
</body>
</html>
圖片我依次放進來,方便大家本地看效果
stone.jpg
stone-bump.jpg
normal2.jpg
normal1.jpg
earth.jpg
earthSpec.png文章來源:http://www.zghlxwxcb.cn/news/detail-733753.html
具體的注釋也都放代碼里了!感覺不錯的點個贊,光白嫖可還行!文章來源地址http://www.zghlxwxcb.cn/news/detail-733753.html
到了這里,關(guān)于ThreeJS-3D教學(xué)五-材質(zhì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!