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

news/2024/5/19 23:26:38

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

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

        查看上一篇👉【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.mrgr.cn/p/01522250

相关文章

七段数码管

import turtle, datetime def drawGap(): # 绘制数码管间隔 turtle.penup() turtle.fd(5) def drawLine(draw): # 绘制单段数码管 drawGap() turtle.pendown() if draw else turtle.penup() turtle.fd(40) drawGap() turtle.right(90) def drawDigit(d): # 根据数字绘制七段…

微软如何打造数字零售力航母系列科普02 --- 微软低代码应用平台加速企业创新 - 解放企业数字零售力

微软低代码应用平台推动企业创新- 解放企业数字零售力 微软在2023年GARTNER发布的魔力象限图中处于头部领先&#xff08;leader&#xff09;地位。 其LCAP产品是Microsoft Power Apps&#xff0c;扩展了AI Builder、Dataverse、Power Automate和Power Pages&#xff0c;这些都包…

git 命令怎么回退到指定的某个提交 commit hash 并推送远程分支?

问题 如下图&#xff0c;我要回退到 【002】Babel 的编译流程 这一次提交 解决 1、先执行下面命令&#xff0c;输出日志&#xff0c;主要就是拿到提交 commit 的 hash&#xff0c;上图红框即可 git log或者 vscode 里面直接右击&#xff0c;copy sha 2、执行下面命令回退 g…

条件格式实例

import pandas as pd import numpy as np import datetime todaystr(datetime.date.today())filepath/Users/kangyongqing/Documents/kangyq/202311/班均及合班储备/z拆班校验/ file102查询结果.csv file2工具-国家对应大洲表格_副本.xlsxdf1pd.read_csv(filepathfile1,dtypeob…

golang学习笔记(net/http库基本使用)

关于net/http库 我们先看看标准库net/http如何处理一个请求。 import ("fmt""log""net/http" )var count 0func main() {http.HandleFunc("/", handler)http.HandleFunc("/count", counter)log.Fatal(http.ListenAndServ…

OpenHarmony音视频—opus

简介 Opus是一种用于在互联网上进行交互式语音和音频传输的编解码器。它可以从低比特率窄带语音扩展到非常高的高品质立体声音乐。 下载安装 直接在OpenHarmony-SIG仓中搜索opus并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 将下载的opus库代码存在以下路径&a…

猿人学内部练习平台6~10题

第六题:session保持检测 使用session请求即可:session = requests.Session() 第七题:请求规律检测1-post 根据请求接口找规律,在每一页请求前请求一次https://www.python-spider.com/cityjson即可 requests.post(https://www.python-spider.com/cityjson, verify=False) re…

Sound Siphon for Mac:音频处理与录制工具

Sound Siphon for Mac是一款专为Mac用户设计的音频处理与录制工具&#xff0c;以其出色的性能、丰富的功能和简便的操作而备受赞誉。 Sound Siphon for Mac v3.6.8激活版下载 该软件支持多种音频格式&#xff0c;包括MP3、WAV、AAC、FLAC等&#xff0c;用户可以轻松导入各种音频…

qt 使用hid开源库 ,搜索所有的hid设备

效果: cmakeLists.txt :cmake_minimum_required(VERSION 3.5)project(TF_Hid_UseANDTest VERSION 0.1 LANGUAGES CXX)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)file(GLOB include…

在PostgreSQL中如何创建和使用自定义函数,包括内置语言(如PL/pgSQL)和外部语言(如Python、C等)?

文章目录 一、使用内置语言 PL/pgSQL 创建自定义函数示例代码使用方法 二、使用外部语言 Python 创建自定义函数安装 PL/Python 扩展示例代码使用方法 三、使用外部语言 C 创建自定义函数编写 C 代码编译为共享库在 PostgreSQL 中注册函数注意事项 总结 PostgreSQL 是一个强大的…

上班族必备的便签备忘录app 好用的便签备忘录软件

上班族每天都需要处理大量的工作事项&#xff0c;从策划方案到客户沟通&#xff0c;每一个环节都至关重要。然而&#xff0c;仅仅依靠大脑记忆&#xff0c;很容易遗漏某些细节&#xff0c;甚至可能错过重要的截止日期。为了避免这种情况&#xff0c;许多人选择使用一款优秀的便…

探索 DTD 在 XML 中的作用及解析:深入理解文档类型定义

DTD 是文档类型定义(Document Type Definition)的缩写。DTD 定义了 XML 文档的结构以及合法的元素和属性。为什么使用 DTD 通过使用 DTD,独立的团体可以就数据交换的标准 DTD 达成一致。 应用程序可以使用 DTD 来验证 XML 数据的有效性。 内部 DTD 声明 如果 DTD 在 XML 文件…

ubuntu16安装docker及docker-compose

ubuntu16安装docker及docker-compose 一、环境前期准备 检查系统版本 系统版本最好在16及以上&#xff0c;可以确保系统的兼容性 lsb_release -a查看内核版本及系统架构 建议用 x86_64的系统架构&#xff0c;安装是比较顺利的 uname -a32的系统不支持docker&#xff0c;安…

鸿蒙HarmonyOS实战-ArkUI事件(键鼠事件)

🚀前言 键鼠事件是指在计算机操作中,用户通过键盘和鼠标来与计算机进行交互的行为。常见的键鼠事件包括按下键盘上的键、移动鼠标、点击鼠标左键或右键等等。键鼠事件可以触发许多不同的操作,比如在文本编辑器中输入文字、在游戏中移动角色、在网页上点击链接等等。计算机操…

linux下 Mysql8.0 离线安装

环境&#xff1a;centos7.9 MysqlL8.0.36安装包 链接&#xff1a;https://pan.baidu.com/s/1bKwHr05z8Ye82dT9tntdUA 提取码&#xff1a;3a5z 参考Centos安装MYSQL8(离线可用) 文章目录 1、解压安装2、配置启动2.1 修改配置文件2.2 mysql 启动 3、mysql 测试 1、解压安装 #…

uniapp-css:拼图(不规则图片拼插)、碎片

拼图案例样式 高斯模糊的地方可以对应的使用fliter属性和opacity来调节样式。 其余碎片和图片对应: 这段代码实现了一个拼图效果的Vue组件。以下是对代码的详细解析: 模板部分: 在模板中使用v-for指令遍历imgs数组中的每个图片对象,为每个图片创建一个元素。 使用:cla…

基于DEAP数据集的四种机器学习方法的情绪分类

在机器学习领域&#xff0c;KNN&#xff08;K-Nearest Neighbors&#xff09;、SVM&#xff08;Support Vector Machine&#xff09;、决策树&#xff08;Decision Tree&#xff09;和随机森林&#xff08;Random Forest&#xff09;是常见且广泛应用的算法。 介绍 1. KNN&am…

程序员学CFA——数量分析方法(四)

数量分析方法&#xff08;四&#xff09; 常见概率分布基本概念离散型随机变量与连续型随机变量离散型随机变量连续型随机变量 分布函数概率密度函数&#xff08;PDF&#xff09;累积分布函数&#xff08;CDF&#xff09; 离散分布离散均匀分布伯努利分布二项分布定义股价二叉树…

OpenWrt软件包各主题样式预览

Openwrt软件包主题luci-theme-alpha登录界面: 主界面:luci-theme-Argon 登录界面:主界面: luci-theme-Bootstrap 登录界面:主界面: luci-theme-Bootstrap_mmdvm 登录界面:主界面: luci-theme-Design 登录界面: 主界面: luci-theme-Edge 登录界面: 主界面: lu…

BM25检索算法 python

1.简介 BM25&#xff08;Best Matching 25&#xff09;是一种经典的信息检索算法&#xff0c;是基于 TF-IDF算法的改进版本&#xff0c;旨在解决、TF-IDF算法的一些不足之处。其被广泛应用于信息检索领域的排名函数&#xff0c;用于估计文档D与用户查询Q之间的相关性。它是一种…