preface

The previous section implemented the color gradient effect and diffusion sweep effect, this section to add the background sky box, diffusion wall, diffusion circle.

Added skybox idea

There are two formats for adding sky box. One is to form sky box with six pictures, one is to create a big enough ball and paste a picture scene on the surface of the ball to form sky ball.

  1. Six pictures: This way is clearancethreetheTHREE.CubeTextureLoader().loadMethod, add six map addresses to this object and set the scene background to this object. The schematic diagram is shown below
  2. A picture: BecausethreeThere is no loadhdrThe way of sky box can imitate the way of loading six pictures, because loading six pictures is equivalent to creating a cube, each face is pasted with a picture material, and the camera forms a sky box in the cube. thenhdrA single image can be achieved by creating a sphere with a surface map and the camera inside the sphere (this approach is suggested by my colleague’s imagination 😂). Here is a recommended website where you can download the HDR material (this material can be used as an empty box or as an environment map)polyhaven.com/hdris 。

Skybox implementation

I chose the first method for skybox implementation here (because the data is six images), the code is as follows

   const textureCube = new THREE.CubeTextureLoader().load(['1.jpg'.'2.jpg'.'3.jpg'.'4.jpg'.'5.jpg'.'6.jpg']); scene.background = textureCube;// as a background map
Copy the code

The following data

The effect

Diffusion circle realization idea

Create a circle by using three. RingGeometry, then add the desired texture to the circle, and then change the size of the circle for each frame of the Render loop.

Diffusion circle realization

Create the THREE.RingGeometry model by creating three.textureLoader (), where this.img is the image address, and assign the read texture to THREE.MeshBasicMaterial. Then change the scale of the model in the Render loop to simulate the diffusion effect. The following code

/* eslint-disable */
import * as THREE from 'three';
/** * ripple scattering layer *@param  Options. img Photo address *@param  Options. speed Flow speed *@param  Options. Scene three *@param  Options. radius Radius of the circle *@param  Options. thing Position of the circle *@param  Options. meshrings store circular data *@example* /

class RunRing {
  constructor(option) {
    this.img = option.img || ' ';
    this.speed = option.speed / 100 || 0.01;
    this.scene = option.scene;
    this.radius = option.radius || 100;
    this.position = option.position || [0.0.0];
    this.meshrings = [];
    this.CreatRing();
  }
  CreatRing() {
    // Create an object to read the photo texture
    const textureLoader = new THREE.TextureLoader();
    textureLoader.load(this.img, (texture) = > {
      // Create a circle structure
      const geometry = new THREE.RingGeometry(0.this.radius, 500);
      // Create a material and assign the read image to the material
      const material2 = new THREE.MeshBasicMaterial({
        color: 0xffffff.side: THREE.DoubleSide,
        depthTest: true.blending: THREE.AdditiveBlending,
        map: texture,
      });
      // Multiple models are generated when multiple points are passed in
      for (let i = 0; i < this.position.length; i += 1) {
        // Combine to generate model
        this.meshring = new THREE.Mesh(geometry, material2);
        // Set the X-axis offset of the model so that the model is tiled on the x-plane
        this.meshring.rotateX(Math.PI / 2);
        // Set the initial state model scale
        this.meshring.scale.set(0.1.0.1.0.1);
        // Set the model position
        this.meshring.position.set(this.position[i][0].this.position[i][1].this.position[i][2]);
        // Store model objects for render to change properties and destroy objects
        this.meshrings.push(this.meshring)
        // Add it to the scene
        this.scene.add(this.meshrings[i]); }});// Create render with model changes per frame
    this.thing = setInterval(() = > {
      // Loop through all created models to make changes
      for (let i = 0; i < this.position.length; i += 1) {
        // If the model is already created
        if (this.meshrings[i]) {
          // When the scale of the model is less than 1, the model is enlarged
          if (this.meshrings[i].scale.x < 1) {
            this.meshrings[i].scale.set(
              this.meshrings[i].scale.x + 0.01.this.meshrings[i].scale.x + 0.01.this.meshrings[i].scale.x + 0.01,); }else {
            // When the model ratio is greater than 1, the model is reset
            this.meshrings[i].scale.set(0.1.0.1.0.1); }}}},50);

  }
  delete() {
    // Delete the corresponding model in scene
    for (let i = 0; i < this.position.length; i += 1) {
      if (this.meshrings[i]) {
        this.scene.remove(this.meshrings[i]); }}if (this.thing) {
      // Clear the render event
      clearInterval(this.thing); }}}export default RunRing;
Copy the code

The data format

 {
        img: "clice.png".scene: scene,
        speed: 1.radius: 400.position: [[400.30.400],
          [100.30.1200]],}Copy the code

rendering

Diffusion wall implementation ideas

As in the previous section, the diffusion wall is achieved through ShaderMaterial. The effect to be achieved is that the transparency of the wall increases with the height, so the transparency of the model point is inversely proportional to the height. The diffusion effect of the model is to mod the position of the model point by mod function to carry out the mod operation (%), the calculation result is limited to 0-1.

Diffusion wall implementation

/* eslint-disable */
import * as THREE from "three";
/** * wave wall *@param  Options. Scene three *@param  * the options. The radius center@param  Options. Height Wall height *@param  Opacity *@param  Options. color Wall color *@example* /

class Wall {
  constructor(option) {
    this.scene = option.scene;
    this.radius = option.radius || 420;
    this.height = option.height || 120;
    this.opacity = option.opacity || 0.5;
    this.color = option.color || "#efad35";
    this.speed = option.speed || 0.5;
    this.mesh = ""; // Generated model data
    this.CreatRing();
  }
  CreatRing() {
    const vertexShader = ` uniform vec3 u_color; uniform float time; uniform float u_height; varying float v_opacity; Void main() {// Multiply the model point position by a coefficient of 0.0-1.0 to simulate the diffusion effect. Vec3 vPosition = position * mod(time/20.0, 1.0); // Opacity of the model is inversely proportional to the height of the model v_opacity = 1.0-position. y/u_height; Gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1.0); } `;
    const fragmentShader = ` uniform vec3 u_color; uniform float u_opacity; varying float v_opacity; V_opacity * u_opacity is the product of the opacity effect generated by the height and passed in by the model. gl_FragColor = vec4(u_color, v_opacity * u_opacity); } `;
// Get parameters
    const { radius, height, opacity, color, speed, renderOrder } = this;
// Generate the model structure
    const geometry = new THREE.CylinderGeometry(
      radius,
      radius,
      height,
      32.1.true
    );
    // Set the model position
    geometry.translate(0, height / 2.0);
    // Customize the model material
    const material = new THREE.ShaderMaterial({
      uniforms: {
        u_height: {
          value: height,
        },
        u_opacity: {
          value: opacity,
        },
        u_color: {
          value: new THREE.Color(color),
        },
        time: {
          value: 0,}},transparent: true.depthWrite: false.depthTest: false.side: THREE.DoubleSide,
      vertexShader: vertexShader,
      fragmentShader: fragmentShader,
    });
    // Combine materials and structures to generate objects
    const mesh = new THREE.Mesh(geometry, material);
    // Set model occlusion, put the model first to prevent occlusion
    mesh.renderOrder = renderOrder || 1;
    this.mesh = mesh; }}export default Wall;

Copy the code

rendering

Project address: github.com/lixiaochjaj…