【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.rhkb.cn/news/313792.html

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

相关文章

Web3钱包开发获取测试币-Base Sepolia(二)

Web3钱包开发获取测试币-Base Sepolia(二) 基于上篇 Web3钱包开发获取测试币-Polygon Mumbai(一) &#xff1a;https://suwu150.blog.csdn.net/article/details/137949473 我们今天来说说Base Sepolia网络的添加。 一、添加Base Sepolia到钱包 什么是Base Sepolia&#xff1f…

如何在PostgreSQL中使用索引覆盖扫描提高查询性能?

文章目录 解决方案1. 创建合适的索引2. 确保查询能够使用索引覆盖扫描3. 调整查询以利用索引覆盖扫描4. 监控和调优 示例代码1. 创建索引2. 编写查询3. 检查是否使用索引覆盖扫描4. 调整索引 总结 在PostgreSQL中&#xff0c;索引是提高查询性能的关键工具之一。索引允许数据库…

【Hello算法】 > 第 3 关 >栈与队列

数据结构 之 数组与链表 1 栈 / 栈的常见操作、实现、应用2 队列 /队列的常见操作、实现、应用3 双向队列4 Tips ———————————————————————————————————————————————————————————- ————————————————…

LeetCode in Python 48. Rotate Image/Matrix (旋转图像/矩阵)

旋转图像/矩阵的重点是寻找旋转前后对应位置的坐标关系。 示例&#xff1a; 图1 旋转图像/矩阵的输入输出示意图 代码&#xff1a; class Solution:def rotate(self, matrix):n len(matrix)for i in range(n // 2):for j in range(i, n - 1 - i):topleft matrix[i][j]ma…

Navicat连接SQLSever报错:[08001] MicrosoftTCP Provider 远程主机强迫关闭了一个现有的连接

Navicat连接SQLSever报错&#xff1a;[08001] [Microsoft][SQL Server Native Client 10.0]TCP Provider: 远程主机强迫关闭了一个现有的连接 问题分析 旧版的MSSQL 如果不是最新版的&#xff0c;可以去这安装以下即可。 最新版的MSSQL 如果是安装最新版的MSSQL连接不上很正…

鸿蒙OpenHarmony【轻量系统 环境搭建】 (基于Hi3861开发板)

安装Hi3861开发板特有环境 除上述[安装库和工具集]和[安装编译工具]外&#xff0c;针对Hi3861开发板还需要安装特定的编译工具。 工具要求 表1 Hi3861 WLAN模组需要安装的编译工具 开发工具用途SCons3.0.4编译构建工具python模块&#xff1a;setuptools、kconfiglib、pycry…

Macs Fan Control Pro for Mac:全面优化Mac风扇控制软件

Macs Fan Control Pro for Mac是一款专为苹果电脑用户设计的风扇控制软件&#xff0c;旨在通过精确的风扇速度调节&#xff0c;全面优化Mac的散热性能&#xff0c;确保系统始终运行在最佳状态。 Macs Fan Control Pro for Mac中文版下载 该软件具备实时监控功能&#xff0c;能够…

java 词法分析练习

import parser.Parser;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class Main {public static void main(String[] args) {// 关键词List<String> keyList new ArrayList<>(Arrays.asList("int","String…

利用STM32 HAL库实现USART串口通信,并通过printf重定向输出“Hello World“

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 上一篇使用STM32F407的HAL库只需1行代码实现US…

AI大模型探索之路-训练篇1:大语言模型微调基础认知

文章目录 前言一、微调技术概述二、微调的必要性三、大模型的微调方法四、微调过程中的技术细节五、微调后的模型评估与应用总结 前言 在人工智能的广阔研究领域内&#xff0c;大型预训练语言模型&#xff08;Large Language Models, LLMs&#xff09;已经成为推动技术革新的关…

龙芯中标麒麟系统打包生成rpm包步骤

1、检查系统是否安装 rpmbuild 和 rpmdevtools 直至rpmdev-setuptree命令执行成功&#xff0c;执行成功后&#xff0c;此时会在用户根目录下创建文件rpmbuild打包文件夹。 rpmbuild为打包工作目录&#xff0c;结构如下&#xff1a; 解释目录结构&#xff1a; BUILD&#xff1…

Windows安装ElasticSearch

Windows安装ElasticSearch 安装完之后 ElasticSearch服务的段括号是9200&#xff0c;可以直接通过localhost:9200在浏览器里面访问 如下图&#xff1a; 而Kibana&#xff0c;也就是ElasticSearch的客户端的端口号是5601&#xff0c;我们可以直接通过localhost:5601访问 如下…

javaEE初阶——多线程(八)——常见的锁策略 以及 CAS机制

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享分治算法关于多线程进阶的章节——关于常见的锁策略以及CAS机制 如果有不足的或者错误的请您指出! 目录 多线程进阶1.常见的锁策略1.1乐观锁和悲观锁1.2重量级锁 和 轻量级锁1.…

Pytorch 学习路程 - 1:入门

目录 下载Pytorch 入门尝试 几种常见的Tensor Scalar Vector Matrix AutoGrad机制 线性回归尝试 使用hub模块 Pytorch是重要的人工智能深度学习框架。既然已经点进来&#xff0c;我们就详细的介绍一下啥是Pytorch PyTorch 希望将其代替 Numpy 来利用 GPUs 的威力&…

云赛道---AI开发框架

MindSpore 旨在提供端边云全场景的 AI 框架。 MindSpore 可部署于端、边、云不同的 硬件环境&#xff0c;满足不同环境的差异化需求&#xff0c;如支持端侧的轻量化部署&#xff0c;支持云侧丰富的 训练功能如自动微分、混合精度、模型易用编程等。 MindSpore 全场景的几个重…

IIR滤波器的设计与实现(内含设计IIR滤波器的高效方法)

写在前面&#xff1a;初学者学习这部分内容&#xff0c;要直接上手写代码可能会感到比较困难&#xff0c;我这里推荐一种高效快速的设计IIR,FIR滤波器的方法——MATLAB工具箱&#xff1a;filterDesigner。打开的方法很简单&#xff0c;就是在命令行键入&#xff1a;filterDesig…

Visual Studio安装MFC开发组件

MFC由于比较古老了&#xff0c;Visual Studio默认没有这个开发组件。最近由于一些原因&#xff0c;需要使用这个库&#xff0c;这就需要另外安装。 参考了网上的一些资料&#xff0c;根据实际使用&#xff0c;其实很多步骤不是必须的。 https://zhuanlan.zhihu.com/p/68117276…

TypeScript 装饰器

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:TypeScript 装饰器 目录 一、是什么 二、使用方式 类装饰 方法/属性装饰 参数装饰 访问器…

Objective-C网络数据捕获:使用MWFeedParser库下载Stack Overflow示例

概述 Objective-C开发中&#xff0c;网络数据捕获是一项常见而关键的任务&#xff0c;特别是在处理像RSS源这样的实时网络数据流时。MWFeedParser库作为一个优秀的解析工具&#xff0c;提供了简洁而强大的解决方案。本文将深入介绍如何利用MWFeedParser库&#xff0c;以高效、…

深度学习系列64:数字人wav2lip详解

1. 整体流程 第一步&#xff0c;加载视频/图片和音频/tts。用melspectrogram将wav文件拆分成mel_chunks。 第二步&#xff0c;调用face_detect模型&#xff0c;给出人脸检测结果&#xff08;可以改造成从文件中读取&#xff09;&#xff0c;包装成4个数组batch&#xff1a;img…