【threejs教程7】threejs聚光灯、摄影机灯和汽车运动效果

【图片完整效果代码位于文章末】

        在上一篇文章中我们实现了汽车模型的加载,这篇文章主要讲如何让汽车看起来像在运动。同时列出聚光灯和摄像机灯光的加载方法。

        查看上一篇👉【threejs教程6】threejs加载glb模型文件(小米su7)👈

         往期文章:

         threejs基础开发应用示例

        【threejs教程2】threejs物体点击交互事件

        【threejs教程3】threejs物体轮廓发光

        【threejs教程4】threejs添加跳动标注

        【threejs教程5】threejs添加文字标注,且始终面向屏幕

实现原理

        汽车实际还是在原地,只有底部的地面纹理在不断地偏移,使汽车看起来像在运动。

实现步骤

1. 添加地板

        纹理图如下,水印好像去不了,需要无水印纹理的话可以跟我要。也可以自己截取一下把水印裁掉,或者自己找个别的纹理也行。

// 加载地面
function loadGround() {// 加载纹理const textureLoader = new THREE.TextureLoader();const floorTexture = textureLoader.load('./img/shuini.jpg'); // 替换为你的jpg文件路径// 设置纹理重复以覆盖整个地板floorTexture.wrapS = THREE.RepeatWrapping;floorTexture.wrapT = THREE.RepeatWrapping;floorTexture.repeat.set(1, 10);// 创建地板的材质const floorMaterial = new THREE.MeshStandardMaterial({ map: floorTexture });// 创建地板的几何体const floorGeometry = new THREE.PlaneGeometry(10, 60); // 参数为宽度和长度// 结合几何体和材质创建网格const floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);// 将地板沿Y轴旋转-90度使其与相机视角垂直floorMesh.rotation.x = -Math.PI / 2;// 添加地板到场景scene.add(floorMesh);
}

2.让地板的纹理运动

        不断更新地板在y轴方向的偏移量,即可达到不断重复运动的效果。

  function animate() {requestAnimationFrame(animate);// 更新纹理偏移量,这里只在V轴(纵向)上移动floorTexture.offset.y += 0.004; // 每帧偏移0.004,根据需要调整速度if (floorTexture.offset.y > 1) {floorTexture.offset.y -= 1; // 当偏移到下一个重复时重置}}animate(); // 开始动画循环

3.添加光源

我们添加了一个聚光灯和一个摄像机灯光效果,可以根据需求自己调整参数。如果觉得显示不佳也可以添加辅助灯光PointLight点光源和DirectionalLight平行光源等。

function addspotLight() {// 创建聚光灯const spotLight = new THREE.SpotLight(0xffffff, 1); // 光的颜色和强度spotLight.position.set(0, 5, 0); // 调整光源位置,这里假设汽车位于原点附近spotLight.castShadow = true; // 开启阴影投射spotLight.angle = Math.PI / 4; // 灯光锥角,控制光照的圆形范围大小spotLight.penumbra = 0.1; // 半影软边宽度,增加真实感spotLight.decay = 1; // 光照随着距离增加的衰减系数,影响光照范围// 设置目标为汽车的位置,假设carMesh是您的汽车模型spotLight.target = carMesh;// 将聚光灯添加到场景中scene.add(spotLight);scene.add(spotLight.target);
}
function addCameraLight() {// 创建光源const cameraLight = new THREE.PointLight(0xffffff, 0.8); // 白色点光,强度1cameraLight.castShadow = true; // 允许投射阴影(如果需要)scene.add(cameraLight);function updateCameraLight() {// 更新光源的位置cameraLight.position.copy(camera.position);// 更新光源的方向(对于DirectionalLight,确保它指向相机的前方)cameraLight.target.position.copy(camera.position);cameraLight.target.position.add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(-1));cameraLight.lookAt(cameraLight.target.position);}function animate() {requestAnimationFrame(animate);// 保持光源与相机同步updateCameraLight();renderer.render(scene, camera);}animate();
}

4.完整效果代码如下所示

<template></template>
<script setup>
import * as THREE from 'three';
import { onMounted, ref } from 'vue';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
const scene = new THREE.Scene();
let carMesh;
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
const controls = new OrbitControls(camera, renderer.domElement);onMounted(() => {init();
});
function init() {camera.position.set(-5, 3, -3);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);controls.update();function animate() {requestAnimationFrame(animate);controls.update();renderer.render(scene, camera);}animate();// addLight();loadGround();
}
// 添加汽车模型
const loader = new GLTFLoader();
const dracoloader = new DRACOLoader();
dracoloader.setDecoderPath('./draco/gltf/');
loader.setDRACOLoader(dracoloader);
loader.load('./model/xiaomisu7.glb', (gltf) => {carMesh = gltf.scene;scene.add(carMesh);carMesh.position.y = 0.1;console.log(carMesh);carMesh.traverse((child) => {if (child.isMesh && child.name.includes('车轮')) {function animate() {requestAnimationFrame(animate);child.rotation.x -= 0.05;}animate();}});addspotLight();addCameraLight()
});
// 加载地面
function loadGround() {// 加载纹理const textureLoader = new THREE.TextureLoader();const floorTexture = textureLoader.load('./img/shuini.jpg'); // 替换为你的jpg文件路径// 设置纹理重复以覆盖整个地板floorTexture.wrapS = THREE.RepeatWrapping;floorTexture.wrapT = THREE.RepeatWrapping;floorTexture.repeat.set(1, 10);// 创建地板的材质const floorMaterial = new THREE.MeshStandardMaterial({ map: floorTexture });// 创建地板的几何体const floorGeometry = new THREE.PlaneGeometry(10, 60); // 参数为宽度和长度// 结合几何体和材质创建网格const floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);// 将地板沿Y轴旋转-90度使其与相机视角垂直floorMesh.rotation.x = -Math.PI / 2;// 添加地板到场景scene.add(floorMesh);function animate() {requestAnimationFrame(animate);// 更新纹理偏移量,这里只在U轴(横向)上移动floorTexture.offset.y += 0.004; // 每帧偏移0.01,根据需要调整速度if (floorTexture.offset.y > 1) {floorTexture.offset.y -= 1; // 当偏移到下一个重复时重置}}animate(); // 开始动画循环
}
function addspotLight() {// 创建聚光灯const spotLight = new THREE.SpotLight(0xffffff, 1); // 光的颜色和强度spotLight.position.set(0, 5, 0); // 调整光源位置,这里假设汽车位于原点附近spotLight.castShadow = true; // 开启阴影投射spotLight.angle = Math.PI / 4; // 灯光锥角,控制光照的圆形范围大小spotLight.penumbra = 0.1; // 半影软边宽度,增加真实感spotLight.decay = 1; // 光照随着距离增加的衰减系数,影响光照范围// 设置目标为汽车的位置,假设carMesh是您的汽车模型spotLight.target = carMesh;// 将聚光灯添加到场景中scene.add(spotLight);scene.add(spotLight.target);
}function addCameraLight() {// 创建光源const cameraLight = new THREE.PointLight(0xffffff, 0.8); // 白色定向光,强度1cameraLight.castShadow = true; // 允许投射阴影(如果需要)scene.add(cameraLight);function updateCameraLight() {// 更新光源的位置cameraLight.position.copy(camera.position);// 更新光源的方向(对于DirectionalLight,确保它指向相机的前方)cameraLight.target.position.copy(camera.position);cameraLight.target.position.add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(-1));cameraLight.lookAt(cameraLight.target.position);}function animate() {requestAnimationFrame(animate);// 保持光源与相机同步updateCameraLight();renderer.render(scene, camera);}animate();
}
</script>

 文章如有技术相关错误请各位批评指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes学习-核心概念篇(一) 初识Kubernetes

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Kubernetes渐进式学习-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. 什么是Kubernetes 3. 为什么需要Kubernetes 3.1. 应…

【高校科研前沿】东北地理所在遥感领域顶刊RSE发布中国主要红树植物群落遥感分类成果

目录 01 文章简介 02 研究内容 03 文章引用 01 文章简介 论文名称&#xff1a;Mangrove species mapping in coastal China using synthesized Sentinel-2 high-separability images&#xff08;基于Sentinel-2高分离度图像的中国沿海红树群落制图&#xff09; 第一作者及…

口才培训需要多久才能看到成效?

口才培训需要多久才能看到成效&#xff1f; 口才培训需要多久才能看到成效&#xff0c;这个问题的答案因个体差异而异&#xff0c;受到多种因素的影响。以下是对此问题的详细分析&#xff1a; 首先&#xff0c;每个人的口才基础和学习能力不同。有些人可能天生具备良好的口才…

面试C++(基础篇)- C++是如何工作的?

1:C是如何工作的&#xff1f; 首先以一个最简单的Hello word程序入门来看&#xff1a; #include <iostream>int main() {std::cout << "Hello World!\n"<< std::endl;std::cin.get(); }1&#xff1a;#include是预编译命令&#xff0c;发生在编译…

WoodMart主题下载:为您的电商网站带来自然而优雅的购物体验

在电子商务的激烈竞争中&#xff0c;一个设计精良、用户友好的在线商店是吸引和保留客户的关键。WoodMart主题&#xff0c;作为一款专为Shopify平台设计的高级主题&#xff0c;以其自然美学和强大的功能&#xff0c;帮助您的商店在众多竞争对手中脱颖而出。 [WoodMart主题的核…

开源框架-链路追踪(SkyWalking)

SkyWalking 极简入门 | Apache SkyWalking 开发环境配置&#xff1a; -javaagent:D:\xxxxx\yyyy\skywalking-agent.jar -DSW_AGENT_NAMEspringboot-xxxx-demo -DSW_AGENT_COLLECTOR_BACKEND_SERVICES127.0.0.1:11800

多行Textview 计算切分后的长度,并回退长度

实现类似的效果&#xff0c;一个多行的 textview&#xff0c; 如果赋值一个超长的字符&#xff0c;尾部长度回退部分&#xff0c;并添加 ... 最后添加一个详情按钮。 如果不超长则不显示详情 效果如图&#xff1a; 获取截断之后的字符长度 fun getLimitedCharacterCount(textV…

Docker与Linux容器:“探索容器化技术的奥秘”

目录 一、Docker概述 二、容器技术的起源&#xff1a; 三、Linux容器 四、Docker的出现 五、Docker容器特点&#xff1a; 六、Docker三大概念&#xff1a; 容器&#xff1a; 镜像&#xff1a; 仓库&#xff1a; 七、Docker容器常用命令 一、Docker概述 在云原生时代&…

每周题解:拯救大兵瑞恩

题目描述 1944 年&#xff0c;特种兵麦克接到国防部的命令&#xff0c;要求立即赶赴太平洋上的一个孤岛&#xff0c;营救被敌军俘虏的大兵瑞恩。 瑞恩被关押在一个迷宫里&#xff0c;迷宫地形复杂&#xff0c;但幸好麦克得到了迷宫的地形图。 迷宫的外形是一个长方形&#x…

架构师的六大生存法则与价值创造

目录 什么影响架构的成败 架构师的六大生存法则 一、所有的架构规划必须有且只有一个正确的目标 二、架构活动需要尊重和顺应人性 三、架构活动在有限的资源下最大化商业价值 四、架构师要考虑依赖的商业模块和技术生命周期 五、架构师为什么要关注技术体系的外部适应性…

【DINO】环境配置

1. DINO简介 作为一款基于Transformer性能强劲的计算机视觉算法&#xff0c;一经发布即受追捧&#xff0c;本文记录下在DINO官方代码在集群上的环境配置及训练自己的数据集过程。 DINO原文&#xff1a;https://arxiv.org/abs/2203.03605 DINO源代码&#xff1a;https://github.…

2021长城杯(部分复现)

2021年4月25日&#xff0c;上午8点左右&#xff0c;警方接到被害人金某报案&#xff0c;声称自己被敲诈数万元&#xff1b;经询问&#xff0c;昨日金某被嫌疑人诱导裸聊&#xff0c;下载了某“裸聊”软件&#xff0c;导致自己的通讯录和裸聊视频被嫌疑人获取&#xff0c;对其进…

Oracle数据库的AI能力分析,释放企业数据价值

解锁Oracle数据库的AI潜力 Oracle数据库提供了一系列的AI能力&#xff0c;旨在帮助企业和开发者更高效地利用人工智能技术。以下是Oracle数据库AI能力的一些关键点&#xff1a;1. AI向量相似性搜索&#xff1a;Oracle Database 23c引入了AI Vector Search功能&#xff0c;该功…

看企业中很多老师傅都说没前途,该不该放弃嵌入式单片机行业?

在企业中&#xff0c;我们经常会听到很多老师傅感叹嵌入式单片机行业没有前途&#xff0c;这也让不少人陷入了迷茫&#xff0c;不知道该不该放弃这个行业。其实&#xff0c;我发现很多新手在嵌入式和单片机领域都存在一个误区&#xff0c;那就是他们过于专注于工作技能的提升&a…

Win10装机(EasyU优启通制作优盘装机)

文章目录 EasyU优启通制作U盘WIndow 10 环境下载将Win10环境放在C盘之外的磁盘目录下&#xff0c;如D:/ 安装1. 进入BIOS2. 格式化C盘3. WinNTSetup4. 设置5.就绪&#xff1f;无需其他选项开始即可6. 重启&#xff0c;拔出U盘&#xff0c;就将自动安装6. 安装好后配置即可 参考…

C++中的queue(容器适配器)

目录 一、成员函数 一、构造函数 二、入栈 push 三、出栈 pop 四、判空 empty 五、队列大小 size 六、取队头元素 front 七、取队尾元素 back 八、入栈 emplace 九、交换函数 swap 二、非成员函数重载 一、关系运算符重载 二、交换函数 swap C中的queue不再是容…

JUC之线程、线程池

一、start与run方法 start方法开启一个新线程&#xff0c;异步执行。 run方法同步执行&#xff0c;不会产生新的线程。 start方法只能执行一次&#xff0c;run方法可以执行多次。 二、一些方法 sleep() 线程睡眠 两种方式调用&#xff1a; Thread.sleep(1000);TimeUnit.…

SAP MRP中的滚动提前期简介(MRP自动删除已固定计划订单)

通常被标记了固定标识的计划订单在运行MRP的时候系统是不会自动删除这部分计划订单的,但是SAP提供了“滚动提前期”这一功能,允许我们通过设定规则,在MRP运算的同时,自动删除在规定期间范围内的被固定的计划订单,从而避免这种干扰MRP运算的现象发生。 下面我们模拟这个场…

SignalR中的重连机制和心跳监测机制详解

一. 重连机制 声明&#xff1a;   本节仅介绍重连机制和心跳监测机制&#xff0c;基于Core 3.1框架&#xff0c;至于SignalR其它的一些基本使用&#xff0c;包括引入、Hub、配置等常规操作&#xff0c;在本节中不介绍&#xff0c;后续写Core下的SignalR 说明   默认是没有重…

钥匙和房间

题目链接 钥匙和房间 题目描述 注意点 所有 rooms[i] 的值 互不相同如果能进入所有房间返回true&#xff0c;否则返回falserooms[i] 是进入 i 号房间可以获得的钥匙集合 解答思路 可以通过深度优先遍历找到所有可以访问的房间&#xff0c;需要注意的是同一个房间不能重复访…