background

Recently, I have learned some basic knowledge of WebGL and three.js, so I want to decorate my homepage with the popular acidic design style, and summarize some knowledge I have learned. This article mainly introduces the use of React + three.js technology stack, load 3D model, add 3D text, add animation, click interaction, etc., with style design, achieve full of design 🤢 acidic style page.

Basic knowledge of

Three.js

Three. Js is a 3D engine running in the browser based on the native WebGL package, which can be used to create a variety of 3D scenes, including cameras, light and shadow, materials and other objects. It’s a very versatile 3D engine. You can further study in the official Chinese document of three.js.

Acidic design

Acid Design translates from Acid Graphics, and has its roots in the 1990s Acid House music, electronic dance music, and hippie culture. In the field of design, this kind of acidic aesthetics bears a kind of free proposition. Bizarre graphics, bold and bright color matching, special material texture, and various fonts constitute a unique acidic design style.

In short, vivid and highly saturated color combinations; Black gray with a high saturation fluorescent color embellishment screen colorful black; Liquid metal, glass, aluminum foil plastic and other materials full of futuristic, cool and scientific sense; Random elements, graphic layouts; Constant repetition, cutting, and combining geometric shapes are all acidic design styles. Acid styles are also becoming popular in music album covers, visual posters, book and movie covers, and web design.

Implementation effect

Online preview: Tricell.fun

implementation

The 3 d model

Scene initialization

🌏Create a scenario
scene = new THREE.Scene();
Copy the code
📷Initializing the camera

The four parameters of PerspectiveCamera PerspectiveCamera are field of view, aspect ratio, near view and far view.

camera = new THREE.PerspectiveCamera(70.window.innerWidth / window.innerHeight, 0.1.1000);
// Set the camera position
camera.position.set(600.20, -200);
// The camera focuses to the center of the screen
camera.lookAt(new THREE.Vector3(0.0.0));
Copy the code
💡Initialize the light source

Add light sources, HemisphereLight: Create light sources with more natural exterior effects

light = new THREE.HemisphereLight(0xffffff.0x444444);
light.position.set(0.20.0);
scene.add(light);
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0.20.10);
light.castShadow = true;
scene.add(light);
Copy the code

Add AmbientLight:

var ambiColor = '#0C0C0C';
var ambientLight = new THREE.AmbientLight(ambiColor);
scene.add(ambientLight);
Copy the code

Adding assistive Tools (Optional)

📦Add secondary mesh

GridHelper can be used for adding mesh assist lines as well as decorating, through GridHelper(Size, Divisions, colorCenterLine, colorGrid).

  • size: Grid width, default is10.
  • divisions: equal score. The default value is10.
  • colorCenterLine: Center line color. The default value is0x444444.
  • colorGrid: Grid line color, default is0x888888.
var grid = new THREE.GridHelper(1000.100.0x000000.0x000000);
grid.material.opacity = 0.1;
grid.material.transparent = true;
grid.position.set(0, -240.0);
scene.add(grid);
Copy the code
📦Adding camera Controls

Through the camera control OrbitControls, you can scale, translate and rotate the 3D scene. Essentially, what you change is not the scene, but the parameters of the camera. Orbitcontrols.js needs to be introduced separately during development.

controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0.0.0);
controls.update();
Copy the code
📦Add performance viewing plug-ins

Stats is an auxiliary library developed by three. js that detects the number of frames an animation runs in. Stats.js also needs to be introduced separately.

stats = new Stats();
container.appendChild(stats.dom);
Copy the code

Load model

The 3D model of the discus thrower statue used in this example comes from threedscans.com, which can be downloaded from 😄 for free. At the end of this article, there are several free model download sites, with more than 200 pages of free models. If you are interested, you can choose your favorite model to download and use. Of course, you can also use Blender, 3DMax and other professional modeling software to create your own model.

loadingobjfbxmodel

It is necessary to import fbxLoader.js or objLoader.js separately,.fbx and.obj format model loading method is the same.

// var loader = new THREE.FBXLoader();
var loader = new THREE.OBJLoader();
loader.load(model, function (object) {
  object.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true; }});object.rotation.y = Math.PI / 2;
  object.position.set(0, -200.0);
  object.scale.set(0.32.0.32.0.32);
  model = object;
  scene.add(object);
});
Copy the code
loadinggltfmodel

It is necessary to introduce gltFloader.js separately, and the method of loading the.gltf model is slightly different. Note that the model traverses the object and is eventually added to the scene with Object.scene instead of object.

var loader = new THREE.GLTFLoader();
loader.load(model, function (object) {
  object.scene.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true; }});object.scene.rotation.y = Math.PI / 2;
  object.scene.position.set(0, -240.0);
  object.scene.scale.set(0.33.0.33.0.33);
  model = object.scene;
  scene.add(object.scene);
});
Copy the code

After adding the mesh and loading the finished model, the effect is shown below.

Add a turntable animation

Add the carouche animation effect by refreshing the page with requestAnimationFrame. Tell the browser window. RequestAnimationFrame () want to perform an animation, and require the browser until the next redraw calls the specified callback function to update the animation. This method takes as an argument a callback function that is executed before the browser’s next redraw.

function animate () {
  requestAnimationFrame(animate);
  // Change the scene's rotation.y as the page is redrawn to achieve rotation
  scene.rotation.y -= 0.015;
  renderer.render(scene, camera);
}
Copy the code

Add click interaction

When you click on a model in a three.js scene to get information about it, or do something else, you use Raycaster, which shoots a ray at the location of your mouse click, and the objects in the ray are recorded. The basic syntax is Raycaster(origin, direction, near, far), where:

  • origin: the starting vector of a ray.
  • direction: Direction vector of ray.
  • near: All returned results should be better thannearFar away. The value cannot be negative. The default value is0.
  • far: All returned results should be better thanfarNearly. Not less thannear, the default value isinfinity.

Code implements the basic steps are: to obtain the coordinates of the mouse on the screen to screen coordinates to device coordinates to standard equipment turn to the world coordinate system to get the mouse in the world coordinates of the scene, according to the world coordinate and camera generated ray projection direction unit vector – according to the X-ray projection direction vector objects created beam projector.

Declare rayCaster and Mouse variables
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
onMouseClick = event= > {
  // Convert the screen coordinates of the mouse click position to the standard coordinates in threejs, starting at the center of the screen, with values ranging from -1 to 1.
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
  // Calculate the RayCaster from the mouse position and the current camera matrix
  raycaster.setFromCamera(mouse, camera);
  // Get the array of rayCaster lines that intersect all models
  let intersects = raycaster.intersectObjects(scene.children);
  if (intersects.length > 0) {
    alert('HELLO WORLD')
    // Different interactions can be triggered by clicking different mesh through traversal, for example:
    let selectedObj = intersects[0].object;
    if (selectedObj.name === 'car') {
      alert('car 🚗')}}}window.addEventListener('click', onMouseClick, false);
Copy the code

Add 3D text

Add 3D text to TextGeometry(TEXT: String, parameters: Object) and the following is the description of the settable attributes:

  • size: Type size, usually the height of uppercase letters.
  • height: Text thickness.
  • weight: the value ofnormalboldIndicates whether to bold.
  • font: font, the default ishelvetiker, the font file must be referenced.
  • style: the value ofnormalitalicsIs italic or not
  • bevelThickness: Chamfering thickness.
  • bevelSize: Chamfer width.
  • curveSegments: The number of arcs to make the text curve smoother.
  • bevelEnabled: Boolean value, whether to use chamfering, meaning cutting diagonally at the edge.
var loader = new THREE.FontLoader();
loader.load('gentilis_regular.typeface.json'.function (font) {
  var textGeo = new THREE.TextGeometry('HELLO WORLD', {
    font: font,
    size: 8..height: 8..curveSegments: .05.bevelThickness: .05.bevelSize: .05.bevelEnabled: true
  });
  var textMaterial = new THREE.MeshPhongMaterial({ color: 0x03c03c });
  var mesh = new THREE.Mesh(textGeo, textMaterial);
  mesh.position.set(0.3.8.0);
  scene.add(mesh);
});
Copy the code

To optimize the

Now the loading of the model has been basically completed, but the volume of THE 3D model is generally large. After the deployment, I found that the loading of the web page was very slow, which affected the user experience. Therefore, it was necessary to reduce the size of the model. Obj2gltf can transform the bulky OBJ format model into GLTF model, effectively optimize the model volume, and improve the speed of web page loading.

The installation
npm install obj2gltf --save
Copy the code
Copy the OBJ model to the following directory
node_modules\obj2gltf\bin
Copy the code
Execute transcoding instructions
node obj2gltf.js -i demo.obj -o demo.gltf
Copy the code

In this example, the initial file size of Kas. obj is 9.7m, and the converted file kas. GLTF is only 4.6m, with its volume reduced by half. When the transformed model is loaded on the page, the naked eye can hardly see the change of model effect. At the same time, the page loading speed has been significantly improved.

Obj2gltf can also be used as a library, transforming the model in real time through the Node service. Interested students can follow the link at the end of this article. Alternatively, you can use 3D modeling software such as Blender to compress and optimize the model manually by reducing the number of faces and the size of the model.

The complete code

var model = require('@/assets/models/kas.gltf');
var container, stats, controls;
var camera, scene, renderer, light, model;
class Kas extends React.Component {
  render () {
    return (
      <div id="kas"></div>
    )
  }
  componentDidMount () {
    this.initThree();
  }
  initThree () {
    init();
    animate();
    function init () {
      container = document.getElementById('kas');
      scene = new THREE.Scene();
      scene.fog = new THREE.Fog(0xa0a0a0.200.1000);
      // Perspective camera: field of view, aspect ratio, near side, far side
      camera = new THREE.PerspectiveCamera(70.window.innerWidth / window.innerHeight, 0.1.1000);
      camera.position.set(600.20, -200);
      camera.lookAt(new THREE.Vector3(0.0.0));
      // Hemisphere light source: Create a more natural outdoor light source
      light = new THREE.HemisphereLight(0xffffff.0x444444);
      light.position.set(0.20.0);
      scene.add(light);
      light = new THREE.DirectionalLight(0xffffff);
      light.position.set(0.20.10);
      light.castShadow = true;
      scene.add(light);
      / / the ambient light
      var ambiColor = '#0C0C0C';
      var ambientLight = new THREE.AmbientLight(ambiColor);
      scene.add(ambientLight);
      / / grid
      var grid = new THREE.GridHelper(1000.100.0x000000.0x000000);
      grid.material.opacity = 0.1;
      grid.material.transparent = true;
      grid.position.set(0, -240.0);
      scene.add(grid);
      // Load the GLTF model
      var loader = new THREE.GLTFLoader();
      loader.load(model, function (object) {
        object.scene.traverse(function (child) {
          if (child.isMesh) {
            child.castShadow = true;
            child.receiveShadow = true; }});object.scene.rotation.y = Math.PI / 2;
        object.scene.position.set(0, -240.0);
        object.scene.scale.set(0.33.0.33.0.33);
        model = object.scene;
        scene.add(object.scene);
      });
      renderer = new THREE.WebGLRenderer({ antialias: true.alpha: true });
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearAlpha(0);
      renderer.shadowMap.enabled = true;
      container.appendChild(renderer.domElement);
      window.addEventListener('resize'.() = > {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
      }, false);
      stats = new Stats();
      container.appendChild(stats.dom);
    }
    function animate () {
      var clock = new THREE.Clock()
      requestAnimationFrame(animate);
      var delta = clock.getDelta();
      scene.rotation.y -= 0.015;
      renderer.render(scene, camera);
      stats.update();
    }
    // Add click events
    Declare rayCaster and Mouse variables
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    function onMouseClick(event) {
      // Calculate the location of the raycaster points using the mouse click position, starting at the center of the screen, with values ranging from -1 to 1.
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
      // Calculate the RayCaster from the mouse position and the current camera matrix
      raycaster.setFromCamera(mouse, camera);
      // Get the array of rayCaster lines that intersect all models
      var intersects = raycaster.intersectObjects(scene.children);
      if (intersects.length > 0) {
        alert('HELLO WORLD')}}window.addEventListener('click', onMouseClick, false); }}Copy the code

Other Design elements

This article mainly introduces the loading of 3D elements. Due to the limited space and time (the blogger is too lazy 😂), the implementation of other elements will not be explained in detail (maybe later there will be time to summarize maybe). Interested students can expand to read the following excellent articles of other Dagod.

Fluid background

Static liquid backgrounds can be done using SVG Filters, read Creating Patterns With SVG Filters for dynamic fluid backgrounds, and use three.js With native GLSL. See the CodePen Shader Template example for this.

The acid effect such as metal, neon, fault effect font can read my another article “only a few paces with CSS implementation cyber punk style 2077 visual effect”, can also use the design, in the interest of time, the metal effect text project in this paper, and the paper banner first figure is the text in the generated using online art font generated web site, Interested students can try to design their own.

Future further optimization

  • #todoAcidic style liquid background implementation.
  • #todo The 3 d modelLiquid metal effect.

three.jsExcellent case recommendation

Finally, I recommend several amazing three.js projects for you to experience and learn together, from which you can learn a lot in terms of page interaction, visual design and performance optimization.

  • Making the home page:3 d earthReal-time display of global hot warehouses.
  • kodeclubs: low surface3 d cityThird person mini-game.
  • Shoe show:720 degreesDynamic display of sneakers.
  • Sand sculpture Dance: Sand sculpture animal dancer.
  • Zenly software:Zenly AppChinese homepage.

The resources

  • three.js: threejs.org
  • Obj2gltf: github.com/CesiumGS/ob…
  • 200 + pages of free 3D models www.turbosquid.com
  • Free 3D statues: threedscans.com
  • Free 3D models: free3d.com
  • Art font generation online: cooltext.com
  • What is acid design: www.shejipi.com/361258.html