three.js实现信号波效果

three.js实现信号波效果

图例

在这里插入图片描述

步骤

  1. 创建平面,添加贴图,平移几何体
  2. 缩放

代码

<template>
  <div class="app">
    <div ref="canvesRef" class="canvas-wrap"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

const canvesRef = ref(null);
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;
let scene;
let camera;
let renderer;
let axesHelper;
let cameraControls;
let mesh;
var l = 60; //波动距离
var s = 1; // 缩放倍数
init();
render();
function init() {
  // 场景
  scene = new THREE.Scene();

  // 相机
  camera = new THREE.PerspectiveCamera(
    45,
    canvasWidth / canvasHeight,
    1,
    10000
  );
  camera.position.set(0, 0, 350);
  camera.lookAt(0, 0, 0);
  // 模型
  addModel();
  // 坐标辅助对象
  axesHelper = new THREE.AxesHelper(200);
  scene.add(axesHelper);

  // 渲染器
  //antialias - 是否执行抗锯齿。默认为false.
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(canvasWidth, canvasHeight);
  // 相机轨道控制器
  cameraControls = new OrbitControls(camera, renderer.domElement);
}

function addModel() {
  const g = new THREE.PlaneGeometry(2, 1);
  g.translate(-1, 0, 0);

  const m = new THREE.MeshBasicMaterial({
    color: 0x00ffff,
    map: new THREE.TextureLoader().load("../src/assets/img/信号波.png"),
    side: THREE.DoubleSide,
    transparent: true,
  });
  mesh = new THREE.Mesh(g, m);
  console.log(mesh);
  scene.add(mesh);
}

function render() {
  renderer.render(scene, camera);
  s += 0.6;
  mesh.scale.set(s, s, s);
  if (s <= l * 0.2) {
    mesh.material.opacity = (s - 1) / (l * 0.2 - 1); //保证透明度在0~1之间变化
  } else if (s > l * 0.2 && s <= l) {
    mesh.material.opacity = 1 - (s - l * 0.2) / (l - l * 0.2); //保证透明度在0~1之间变化
  } else {
    s = 1.0;
  }

  requestAnimationFrame(render);
}
onMounted(() => {
  canvesRef.value.appendChild(renderer.domElement);
});
</script>

<style lang="scss" scoped>
.app {
  position: relative;
}
</style>

图片(透明的)

在这里插入图片描述

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现模型效果,可以使用three.js中的ShaderMaterial和RenderTarget实现。具体步骤如下: 1. 创建两个RenderTarget,一个用于存储模型的深度信息,另一个用于存储效果的纹理信息。 ```javascript var depthRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter } ); var rippleRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter } ); ``` 2. 创建一个ShaderMaterial,该材质需要使用深度RenderTarget和纹RenderTarget中的信息来计算出效果的纹理。 ```javascript var rippleMaterial = new THREE.ShaderMaterial( { uniforms: { depthTexture: { value: depthRenderTarget.texture }, rippleTexture: { value: rippleRenderTarget.texture }, time: { value: 0 }, resolution: { value: new THREE.Vector2( window.innerWidth, window.innerHeight ) } }, vertexShader: document.getElementById( 'rippleVertexShader' ).textContent, fragmentShader: document.getElementById( 'rippleFragmentShader' ).textContent } ); ``` 3. 将该ShaderMaterial应用到模型上,并将模型渲染到深度RenderTarget中。 ```javascript var model = ...; // 创建模型 var scene = new THREE.Scene(); scene.add( model ); var camera = ...; // 创建相机 var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); renderer.setRenderTarget( depthRenderTarget ); renderer.render( scene, camera ); ``` 4. 创建一个平面,使用上面创建的ShaderMaterial来渲染该平面,并将该平面渲染到纹RenderTarget中。 ```javascript var ripplePlaneMaterial = new THREE.MeshBasicMaterial( { map: rippleRenderTarget.texture } ); var ripplePlaneGeometry = new THREE.PlaneGeometry( window.innerWidth, window.innerHeight ); var ripplePlane = new THREE.Mesh( ripplePlaneGeometry, ripplePlaneMaterial ); scene.add( ripplePlane ); var rippleCamera = ...; // 创建相机 var rippleRenderer = new THREE.WebGLRenderer(); rippleRenderer.setSize( window.innerWidth, window.innerHeight ); rippleRenderer.setRenderTarget( rippleRenderTarget ); rippleRenderer.render( rippleScene, rippleCamera ); ``` 5. 在循环渲染中更新ShaderMaterial的uniform变量,并重新渲染纹RenderTarget。 ```javascript function animate() { requestAnimationFrame( animate ); rippleMaterial.uniforms.time.value += 0.1; rippleRenderer.setRenderTarget( rippleRenderTarget ); rippleRenderer.render( rippleScene, rippleCamera ); rippleRenderer.setRenderTarget( null ); renderer.render( scene, camera ); } ``` 6. 在ShaderMaterial的vertexShader和fragmentShader中实现效果的计算。 vertexShader: ```glsl uniform float time; varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); // 计算效果 float frequency = 10.0; float amplitude = 0.2; float speed = 1.0; vec3 pos = position; pos.z += sin( pos.x * frequency + time * speed ) * amplitude; pos.z += sin( pos.y * frequency + time * speed ) * amplitude; gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 ); } ``` fragmentShader: ```glsl uniform sampler2D depthTexture; uniform sampler2D rippleTexture; uniform vec2 resolution; varying vec2 vUv; void main() { // 获取深度信息 float depth = texture2D( depthTexture, vUv ).r; // 获取纹信息 float ripple = texture2D( rippleTexture, vUv ).g; // 根据深度和纹信息计算出颜色 vec3 color = vec3( depth * ripple ); gl_FragColor = vec4( color, 1.0 ); } ``` 这样就可以在模型上实现效果了。具体实现可以参考以下示例代码: https://codepen.io/wanbo/pen/XWpXzjV
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值