学习threejs,THREE.MeshBasicMaterial网格材质、THREE.MeshLambertMaterial漫反射材质

server/2024/10/22 16:38:04/

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录


一、🍀前言

本文详细介绍如何基于threejs在三维场景中实现THREE.MeshBasicMaterial网格材质、THREE.MeshLambertMaterial漫反射材质效果,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.MeshBasicMaterial网格材质

THREE.MeshBasicMaterial 是 Three.js 中的一种基本材质类型,用于渲染网格对象(THREE.Mesh)。这种材质不考虑光源的影响,因此无论场景中有多少光源,材质的颜色和外观都不会改变。这使得 THREE.MeshBasicMaterial 非常适合用于不需要光照效果的场景,或者作为调试工具来检查模型的形状和纹理。
常用属性:
color:材质的颜色,默认为白色(0xffffff)。可以是一个整数,表示十六进制颜色值。
map:基础颜色贴图,可以用来替代材质的颜色。可以是一个 THREE.Texture 对象。
alphaMap:透明度贴图,可以用来定义材质的透明度。可以是一个 THREE.Texture 对象。
emissive:自发光颜色,默认为黑色(0x000000)。即使在没有光源的情况下,也会显示这个颜色。
emissiveMap:自发光贴图,可以用来定义自发光的颜色。可以是一个 THREE.Texture 对象。
specular:高光颜色,默认为白色(0x111111),但在 THREE.MeshBasicMaterial 中不会生效。
shininess:高光强度,默认为 30,但在 THREE.MeshBasicMaterial 中不会生效。
opacity:材质的全局透明度,默认为 1(不透明)。
transparent:是否开启透明模式,默认为 false。如果设置为 true,则需要设置 opacity 或者使用 alphaMap。
side:指定材质在哪一面渲染,可以是 THREE.FrontSide(正面)、THREE.BackSide(背面)或 THREE.DoubleSide(双面)。
wireframe:是否启用线框模式,默认为 false。
visible:是否渲染该材质,默认为 true。
depthTest:是否进行深度测试,默认为 true。
depthWrite:是否写入深度缓冲区,默认为 true。
blending:混合模式,默认为 THREE.NormalBlending。可以设置为 THREE.AdditiveBlending、THREE.SubtractiveBlending 等。
vertexColors:是否启用顶点颜色,默认为 THREE.NoColors。可以设置为 THREE.VertexBasicColors、THREE.VertexColors 或 THREE.FaceColors。
flatShading:是否使用平滑着色,默认为 false。如果设置为 true,则每个面片都将使用平均法线。

2.2 ☘️THREE.MeshLambertMaterial漫反射材质

THREE.MeshLambertMaterial 是 Three.js 中的一种材质类型,用于模拟物体表面的漫反射效果。这种材质遵循 Lambertian 反射模型,这意味着它会均匀地将接收到的光照散射到各个方向,从而产生较为自然的光照效果。THREE.MeshLambertMaterial 适用于需要模拟漫反射材质的场景,如墙面、木头、纸张等非金属材料。
常用属性:
THREE.MeshLambertMaterial 继承自 THREE.Material,并具有一些特定的属性,可以用来控制材质的外观:
color:材质的颜色,默认为白色(0xffffff)。可以是一个整数,表示十六进制颜色值。
map:基础颜色贴图,可以用来替代材质的颜色。可以是一个 THREE.Texture 对象。
alphaMap:透明度贴图,可以用来定义材质的透明度。可以是一个 THREE.Texture 对象。
emissive:自发光颜色,默认为黑色(0x000000)。即使在没有光源的情况下,也会显示这个颜色。
emissiveMap:自发光贴图,可以用来定义自发光的颜色。可以是一个 THREE.Texture 对象。
specular:高光颜色,默认为白色(0x111111),但在 THREE.MeshLambertMaterial 中不会生效。
shininess:高光强度,默认为 30,但在 THREE.MeshLambertMaterial 中不会生效。
opacity:材质的全局透明度,默认为 1(不透明)。
transparent:是否开启透明模式,默认为 false。如果设置为 true,则需要设置 opacity 或者使用 alphaMap。
side:指定材质在哪一面渲染,可以是 THREE.FrontSide(正面)、THREE.BackSide(背面)或 THREE.DoubleSide(双面)。
wireframe:是否启用线框模式,默认为 false。
visible:是否渲染该材质,默认为 true。
depthTest:是否进行深度测试,默认为 true。
depthWrite:是否写入深度缓冲区,默认为 true。
blending:混合模式,默认为 THREE.NormalBlending。可以设置为 THREE.AdditiveBlending、THREE.SubtractiveBlending 等。
vertexColors:是否启用顶点颜色,默认为 THREE.NoColors。可以设置为 THREE.VertexBasicColors、THREE.VertexColors 或 THREE.FaceColors。
flatShading:是否使用平滑着色,默认为 false。如果设置为 true,则每个面片都将使用平均法线。
envMap:环境贴图,可以用来模拟环境光照。可以是一个 THREE.Texture 对象。
reflectivity:环境光反射率,默认为 1。
refractionRatio:折射率,默认为 0.98。
combine:环境贴图的组合方式,默认为 THREE.MixOperation。

二、🍀THREE.MeshBasicMaterial网格材质、THREE.MeshLambertMaterial漫反射材质效果

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.DirectionalLight平行光源,设置平行光源位置,设置平行光源投影,scene添加平行光源。
  • 5、加载几何模型:创建SphereGeometry球体、BoxGeometry立方体、PlaneGeometry地面几何体以及AxisHelper辅助工具坐标系,Scene场景加入以上几何体和工具,其中SphereGeometry使用THREE.MeshBasicMaterial网格材质,其他几何体使用THREE.MeshLambertMaterial漫反射材质
  • 6、加入controls控制、gui控制,加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>learn19(THREE.MeshBasicMaterial材质、THREE.MeshLambertMaterial材质)</title><script src="lib/threejs/127/three.js-master/build/three.js"></script><script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script><script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script><script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
</head>
<style>body {margin: 0;}canvas {width: 100%;height: 100%;display: block;}
</style>
<body onload="draw()">
</body>
<script>var renderervar initRender = () => {renderer = new THREE.WebGLRenderer({antialias: true})renderer.setSize(window.innerWidth, window.innerHeight)renderer.shadowMap.enabled = truerenderer.shadowMap.type = THREE.PCFSoftShadowMapdocument.body.appendChild(renderer.domElement)}var scenevar initScene = () => {scene = new THREE.Scene()}var cameravar initCamera = () => {camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)camera.position.set(0, 40, 100)camera.lookAt(new THREE.Vector3(0, 0, 0))}var ambientLight, directionalLightvar initLight = () => {ambientLight = new THREE.AmbientLight('#111111')scene.add(ambientLight)directionalLight = new THREE.DirectionalLight('#ffffff')directionalLight.position.set(-40, 60, -10)directionalLight.shadow.camera.near = 20 //产生阴影的最近距离directionalLight.shadow.camera.far = 200 //产生阴影的最远距离directionalLight.shadow.camera.left = -50 //产生阴影距离位置的最左边位置directionalLight.shadow.camera.right = 50 //最右边directionalLight.shadow.camera.top = 50 //最上边directionalLight.shadow.camera.bottom = -50 //最下面directionalLight.shadow.mapSize.height = 1024directionalLight.shadow.mapSize.width = 1024directionalLight.castShadow = truescene.add(directionalLight)}var cube, plane, meshMaterialvar initModel = () => {var helper = new THREE.AxisHelper(10)scene.add(helper)var sphereGeometry = new THREE.SphereGeometry(10, 30, 30)meshMaterial = new THREE.MeshBasicMaterial({color: 0xaaafff})var sphere = new THREE.Mesh(sphereGeometry, meshMaterial)sphere.position.set(-20, 20, 0)sphere.castShadow = truescene.add(sphere)var cubeGeometry = new THREE.BoxGeometry(10, 10, 10)var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x00ffff})cube = new THREE.Mesh(cubeGeometry, cubeMaterial)cube.position.set(30, 5, -5)cube.castShadow = truescene.add(cube)var planeGeometry = new THREE.PlaneGeometry(5000, 5000, 20, 20)var planeMaterial = new THREE.MeshLambertMaterial({color: 0xaaaaaa})plane = new THREE.Mesh(planeGeometry, planeMaterial)plane.rotation.x = -0.5 * Math.PIplane.position.y = -0plane.receiveShadow = truescene.add(plane)}var paramsvar initGui = () => {params = {rotationSpeed: 0.02,bouncingSpeed: 0.03,opacity: meshMaterial.opacity,transparent: meshMaterial.transparent,overdraw: meshMaterial.overdraw,visible: meshMaterial.visible,side: "front",color: meshMaterial.color.getStyle(),wireframe: meshMaterial.wireframe,wireframeLinewidth: meshMaterial.wireframeLinewidth,wireFrameLineJoin: meshMaterial.wireframeLinejoin,}var gui = new dat.GUI()var spGui = gui.addFolder('Mesh')spGui.add(params, 'opacity', 0, 1).onChange(e => {meshMaterial.opacity = e})spGui.add(params, 'transparent').onChange(e => {meshMaterial.transparent = e})spGui.add(params, 'wireframe').onChange(e => {meshMaterial.wireframe = e})spGui.add(params, 'wireframeLinewidth', 0, 20).onChange(e => {meshMaterial.wireframeLinewidth = e})spGui.add(params, 'visible').onChange(e => {meshMaterial.visible = e})spGui.add(params, 'side', ['front', 'back', 'double']).onChange(e => {switch (e) {case 'front':meshMaterial.side = THREE.FrontSidebreakcase 'back':meshMaterial.side = THREE.BackSidebreakcase 'double':meshMaterial.side = THREE.DoubleSidebreak}meshMaterial.needsUpdate = true})spGui.addColor(params, 'color').onChange(e => {meshMaterial.color.setStyle(e)})spGui.open()}var statsvar initStats = () => {stats = new Stats()document.body.appendChild(stats.dom)}var controlsvar initControls = () => {controls = new THREE.OrbitControls(camera, renderer.domElement)controls.enableDamping = true}var render = () => {renderer.render(scene, camera)}var onWindowResize = () => {camera.aspect = window.innerWidth / window.innerHeightcamera.updateProjectionMatrix()render()renderer.setSize(window.innerWidth, window.innerHeight)}var animate = () => {render()stats.update()controls.update()requestAnimationFrame(animate)}var draw = () => {initRender()initScene()initCamera()initLight()initModel()initStats()initControls()initGui()animate()window.onresize = onWindowResize}
</script>
</html>

效果如下:
在这里插入图片描述


http://www.ppmy.cn/server/130113.html

相关文章

Kylin系统根分区扩容步骤

问题背景 工作中&#xff0c;有时候Linux操作系统的根分区空间不足&#xff0c;我们需要将已安装的系统根分区进行扩容。那么该如何进行操作呢&#xff1f;我以VMware虚拟机上的Kylin系统为例&#xff0c;进行了详细的实验操作。具体详情请见下面的文章。 虚拟机扩容硬盘 首…

Leetcode 24 Swap Nodes in Pairs

题意&#xff1a;给定一个list of nodes&#xff0c;要求交换相邻的两个节点 https://leetcode.com/problems/swap-nodes-in-pairs/description/ Input: head [1,2,3,4] Output: [2,1,4,3] 首先你需要思考&#xff0c;我要交换两个节点&#xff0c;对于每个节点&#xff0c;向…

STM32 USB CUBEMX

开发背景 使用的平台&#xff1a;STM32H750 注意事项 时钟必须是48MHZ&#xff0c;其它都不行 2. 将默认任务的堆栈设大一点 如果使用操作系统&#xff0c;USB任务跑在默认任务里&#xff0c;因此需要设置默认任务的堆栈缓存是直接定义的全局变量&#xff0c;需要设置编译器…

【操作系统】——进程(手把手教你学进程,学不会你呼我)

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 一、进程的概念、组成、特征 1.1 进程的概念&#xff08;理解“进程”和“程序”的区别&#xff09;…

连肝了多天学习MySQL索引与性能优化,详细总结一下索引的使用与数据库优化

文章目录 索引是什么&#xff1f;索引的作用初步认识索引索引的类型按照数据结构分类BTREE索引 哈希索引 按功能逻辑进行分类唯一索引普通索引主键索引全文索引 按照字段的个数进行划分单列索引多列&#xff08;组合&#xff0c;联合&#xff09;索引 小结索引的设计原则数据准…

Python 如何使用 Redis 作为缓存

Python 如何使用 Redis 作为缓存 一、引言 在现代 Web 应用程序和数据密集型服务中&#xff0c;性能 和 响应速度 是至关重要的因素。而当应用需要频繁访问相同的数据时&#xff0c;直接从数据库获取数据会耗费大量的时间和资源。因此&#xff0c;缓存系统成为了提升性能的重…

【Verilog学习日常】—牛客网刷题—Verilog进阶挑战—VL45

异步FIFO 描述 请根据题目中给出的双口RAM代码和接口描述&#xff0c;实现异步FIFO&#xff0c;要求FIFO位宽和深度参数化可配置。 电路的接口如下图所示。 双口RAM端口说明&#xff1a; 端口名 I/O 描述 wclk input 写数据时钟 wenc input 写使能 waddr input 写…

解决Docker环境下Next.js和FastAPI的跨容器通信问题

在开发使用Docker容器化的全栈应用时&#xff0c;我们经常会遇到前后端通信的问题。本文记录了我们在使用Next.js作为前端&#xff0c;FastAPI作为后端的项目中遇到的一个棘手问题&#xff0c;以及最终的解决方案。 问题背景 我们的应用架构如下&#xff1a; 前端&#xff1…