当前位置: 首页 > news >正文

ThreeJS-3D教学五-材质

我们在ThreeJS-3D教学二:基础形状展示中有简单介绍过一些常用的材质,这次我们举例来具体看下效果:
在这里插入图片描述
代码是这样的:

<!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() {/*** 凹凸贴图可以使纹理也有厚度,看起来更立体。凹凸贴图一般使用一张灰度图,设置成材料的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中将这两个图片的信息合在一起,就形成了一个细节丰富的立体纹理* 设置材质的 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, //高光部分的亮度,默认30map: textureNormal, // 普通纹理贴图specularMap: textureSpec, // 高光贴图specular: '#fff' // 高光部分的颜色});/**SphereGeometry(radius:浮点,widthSegments:整数,heightSegments:整数)radius——球体半径。默认值为1。widthSegments—水平线段的数量。最小值为3,默认值为32。heightSegments—垂直线段的数量。最小值为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() {// 创建一个平面 PlaneGeometry(width, height, widthSegments, heightSegments)const planeGeometry = new THREE.PlaneGeometry(widthImg, heightImg, 1, 1);// 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。const planeMaterial = new THREE.MeshPhongMaterial({color: 0xb2d3e6,side: THREE.DoubleSide});const plane = new THREE.Mesh(planeGeometry, planeMaterial);// 以自身中心为旋转轴,绕 x 轴顺时针旋转 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;// 色调映射的曝光级别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 );// 设置最大最小视距controls.minDistance = 20;controls.maxDistance = 1000;window.addEventListener( 'resize', onWindowResize );stats = new Stats();stats.setMode(1); // 0: fps, 1: msdocument.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.lryc.cn/news/184119.html

相关文章:

  • 递归
  • Vercel部署个人静态之DNS污染劫持问题
  • Microsoft Defender Vulnerability部署方案
  • 云服务器CVM_云主机_云计算服务器_弹性云服务器-腾讯云
  • PLC之间无线通信-不用编程实现多品牌PLC无线通讯的解决方案
  • 第二证券:A股反弹已至?9月最牛金股涨超41%
  • 机器人革命:你一定没见过这些全新的机器人技术!
  • vue前端项目中添加独立的静态资源
  • 外汇天眼:业务员离职,也不给出金!Sky Alliance Markets摆烂不玩了?
  • chrome浏览器如何多开
  • 学习笔记|串口通信的基础知识|同步/异步|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础
  • Golang接口实现OCP原则
  • 【论文笔记】SVDM: Single-View Diffusion Model for Pseudo-Stereo 3D Object Detection
  • C++之sqlite数据库读写
  • 大模型应用疯狂加速,洗牌却在静悄悄进行了
  • oracle后台进程详解#进程结构
  • 解决DDP的参数未参与梯度计算
  • cpp primer笔记100-拷贝控制
  • 【数据库——MySQL】(16)游标和触发器习题及讲解
  • javascript二维数组(9)toString的用法
  • OpenAI重大更新!为ChatGPT推出语音和图像交互功能
  • 【开发篇】十六、SpringBoot整合JavaMail实现发邮件
  • 如何在Ubuntu系统部署RabbitMQ服务器并公网访问【内网穿透】
  • Flutter笔记:用于ORM的Floor框架简记
  • Zabbix自定义脚本监控MySQL数据库
  • 【Spatial-Temporal Action Localization(五)】论文阅读2020年
  • Linux基本指令(中)——“Linux”
  • OWASP Top 10漏洞解析(3)- A3:Injection 注入攻击
  • Java自定义类加载器的详解与步骤
  • 完美清晰,炫酷畅享——Perfectly Clear Video为你带来卓越的AI视频增强体验