【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); // 白色点光,强度1
  cameraLight.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); // 白色定向光,强度1
  cameraLight.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>

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

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
three.js中,可以通过添加不同类型的光来为模型增加光照效果,以下是一个简单的示例: 1. 创建场景、相机和渲染器: ```javascript var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); ``` 2. 加载模型并创建一个基础材质: ```javascript var loader = new THREE.GLTFLoader(); loader.load('model.gltf', function(gltf) { var material = new THREE.MeshBasicMaterial({color: 0xffffff}); gltf.scene.traverse(function(child) { if (child instanceof THREE.Mesh) { child.material = material; } }); scene.add(gltf.scene); }); ``` 3. 创建多种类型的光: ```javascript var ambientLight = new THREE.AmbientLight(0x404040); // 环境光 scene.add(ambientLight); var directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 平行光 directionalLight.position.set(0, 1, 0); scene.add(directionalLight); var pointLight = new THREE.PointLight(0xffffff, 1, 100); // 点光源 pointLight.position.set(0, 0, 5); scene.add(pointLight); var spotLight = new THREE.SpotLight(0xffffff, 1, 100); // 聚光灯 spotLight.position.set(0, 0, 5); spotLight.target.position.set(0, 0, 0); scene.add(spotLight); ``` 4. 渲染场景: ```javascript function render() { requestAnimationFrame(render); renderer.render(scene, camera); } render(); ``` 在这个例子中,我们首先加载了一个模型,并创建了一个基础材质。然后,我们创建了四种类型的光:环境光、平行光、点光源和聚光灯,并将它们添加到场景中。最后,我们渲染场景。 如果需要更细腻的效果,可以通过调整光的位置、颜色、强度等属性来达到不同的效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有只老羊在发呆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值