5
头图
Disclaimer: The graphic and model materials involved in this article are only for personal study, research and appreciation. Please do not re-modify, illegally spread, reprint, publish, commercialize, or conduct other profit-making activities.

background

When I was browsing the sketchfab website, I saw a lot of model examples of converting 2D planes to 3D , so I followed their example and used the Three.js + React technology stack to convert 2D cartoon pictures into 3D visual effects. The contents of this article mainly include: THREE.Group level model, MeshPhongMaterial highlight mesh material, sine and cosine function to create model movement trajectory, etc.

Effect

The realization effect is shown in the following figure of 👇 : the page mainly consists of the background image, the main body of the comic image and the background image of the explosion of 💥 Boom . Press and hold the left mouse button to move the model to obtain different views, so that the image has a visual depth of field effect of 3D .

Adapted:

  • 💻 PC side
  • 📱 mobile terminal
👀 online preview: https://dragonir.github.io/3d/#/comic

accomplish

The implementation of this article is relatively simple, and it is basically the same as my previous articles, and the process is relatively simple, mainly because the material preparation process is more complicated. Let's take a look at the specific implementation method.

Material production

Prepare a picture you like as the original material. It is best to divide the picture content into multiple levels to achieve the 3D depth of field effect. In this example, a cartoon picture is used, which can just be divided into multiple levels.

Open the picture in Photoshop , create several layers according to the number of layers you need, and copy the map to each layer, then edit each layer according to the division of the depth of the layer scene, and use the magic of Stick Tool and Lasso Tool Remove the excess, then export each layer individually as footage. I divided it into 👆 as above 7 layers, plus a border, a total of 8 layers.

resource introduction

Among them, OrbitControls is used for lens track control, and TWEEN is used for lens tween animation.

import React from 'react';
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";

scene initialization

Initialize rendering containers, scenes, cameras, and light sources. The initial position of the camera is set to (-12, 0, 0) on the left side, so that TWEEN can be used to achieve the flip animation effect later.

// 场景
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
// 添加背景图片
scene.background = new THREE.TextureLoader().load(background);
// 相机
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(-12, 0, 0);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// 直射光
light = new THREE.DirectionalLight(0xffffff, 1);
light.intensity = .2;
light.position.set(10, 10, 30);
light.castShadow = true;
light.shadow.mapSize.width = 512 * 12;
light.shadow.mapSize.height = 512 * 12;
light.shadow.camera.top = 100;
light.shadow.camera.bottom = - 50;
light.shadow.camera.left = - 50;
light.shadow.camera.right = 100;
scene.add(light);
// 环境光
ambientLight = new THREE.AmbientLight(0xdddddd);
scene.add(ambientLight);

Create a manga body

First create a Group for adding the layer mesh, then iterate over the layer background image array, create a mesh for each face in the loop body, the mesh uses the plane cube PlaneGeometry , the material uses the physical material MeshPhysicalMaterial , for each The grid position sets the same x- and y-axis values and different z-axis values to create a depth-of-field effect. Finally add Group to scene Scene .

var layerGroup = new THREE.Group();
let aspect = 18;
for (let i=0; i<layers.length; i++) {
  let mesh = new THREE.Mesh(new THREE.PlaneGeometry(10.41, 16), new THREE.MeshPhysicalMaterial({
    map: new THREE.TextureLoader().load(layers[i]),
    transparent: true,
    side: THREE.DoubleSide
  }));
  mesh.position.set(0, 0, i);
  mesh.scale.set(1 - (i / aspect), 1 - (i / aspect), 1 - (i / aspect));
  layerGroup.add(mesh);
  // 文字
  if (i === 5) {
    mesh.material.metalness = .6;
    mesh.material.emissive = new THREE.Color(0x55cfff);
    mesh.material.emissiveIntensity = 1.6;
    mesh.material.opacity = .9;
  }
  // 会话框
  if (i === 6) {
    mesh.scale.set(1.5, 1.5, 1.5);
    animateLayer = mesh;
  }
}
layerGroup.scale.set(1.2, 1.2, 1.2);

At this point, the effect is as shown in the following figure:

💡 THREE.Group Hierarchy Model

Meshes with the same body can be merged together by Group for easier operation. The base class of Three.js hierarchical model Group is Object3D , which is the base class of most objects in Three.js , and provides a series of properties and methods to manipulate objects in three-dimensional space. For example, objects can be combined by the .add(object) method, which adds the object as a child object.

But it is better to use Group as the parent object, because Group is more semantic than Object3D , you can use Group as the parent object of point, line, grid and other models to build a hierarchical model.

Create a Boom Background

In order to enhance the visual effect, I added a 💥 Boom explosion graphic plane as the background. When moving with the mouse, as the light changes, you can see that the pattern has metal gradient effect , which is mainly through the highlight material MeshPhongMaterial specular and shininess properties are implemented.

const boom = new THREE.Mesh(new THREE.PlaneGeometry(36.76, 27.05), new THREE.MeshPhongMaterial({
  map: new THREE.TextureLoader().load(boomImage),
  transparent: true,
  shininess: 160,
  specular: new THREE.Color(0xff6d00),
  opacity: .7
}));
boom.scale.set(.8, .8, .8);
boom.position.set(0, 0, -3);
layerGroup.add(boom)
scene.add(layerGroup);

After adding:

💡 MeshPhongMaterial Specular mesh material

MeshPhongMaterial is a material for glossy surfaces with specular highlights . This material uses the non-physical Blinn-Phong model to calculate reflectance. Unlike the MeshLambertMaterial model used in Lambertian , this material can simulate glossy surfaces with specular highlights, such as painted wood.

constructor :

MeshPhongMaterial(parameters: Object)

parameters : Optional, an object that defines the appearance of the material, with one or more properties. Any properties of the material can be passed in from here (including any properties inherited from Material ).

special properties :

  • .emissive[Color] : The emitted light color of the material, basically an inherent color unaffected by other lights. Default is black.
  • .emissiveMap[Texture] : Sets the irradiance map. The default value is null . The emission map color is adjusted by the emission color and intensity.
  • .emissiveIntensity[Float] : The emitted light intensity. Adjust the glow color. Defaults to 1 .
  • .envMap[TextureCube] : Environment map. The default value is null .
  • .isMeshPhongMaterial[Boolean] : Used to check if this class or a derived class is a Phong mesh material. The default value is true .
  • .lightMap[Texture] : Lightmaps. The default value is null .
  • .lightMapIntensity[Float] : The intensity of the baked light. The default value is 1 .
  • .reflectivity[Float] : How much the environment map affects the surface. The default value is 1 , and the valid range is between 0 (no reflection) and 1 (full reflection).
  • .refractionRatio[Float] : The index of refraction of air divided by the index of refraction of the material. The refractive index should not exceed 1 . The default value is 0.98 .
  • .shininess[Float] : The degree of highlighting of .specular , the higher the value, the brighter it is. The default value is 30 .
  • .skinning[Boolean] : Whether the material uses skinning. The default value is false .
  • .specular[Color] : The specular color of the material. The default is 0x111111 for the color Color . This defines the glossiness and glossy color of the material.
  • .specularMap[Texture] : The specular map value affects how much the specular and the environment map affect the surface. The default value is null .
📌 uses the Phong shading model to compute shading, which computes per-pixel shading, which yields more accurate results than the MeshLambertMaterial model used by Gouraud , at the cost of some performance loss.

Lens control, zoom adaptation, animation

Motion tweening of the shot, where the shot switches to the correct position.

Animations.animateCamera(camera, controls, { x: 0, y: 0, z: 20 }, { x: 0, y: 0, z: 0 }, 3600, () => { });

Camera control, in this example the model translation and horizontal and vertical rotation angles are shown for the best preview.

controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.enableDamping = true;
controls.enablePan = false;
// 垂直旋转角度限制
controls.minPolarAngle = 1.2;
controls.maxPolarAngle = 1.8;
// 水平旋转角度限制
controls.minAzimuthAngle = -.6;
controls.maxAzimuthAngle = .6;

Screen zoom adaptation.

window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}, false);

For the dialog box layer mesh, I animate it left and right on a smooth curve, mainly by modifying its x axis and y axis position .

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
  controls && controls.update();
  TWEEN && TWEEN.update();
  // 会话框摆动动画
  step += 0.01;
  animateLayer.position.x = 2.4 + Math.cos(step);
  animateLayer.position.y = .4 + Math.abs(Math.sin(step));
}

💡 Sine cosine function to create model movement trajectory

Using the step variable and with the help of the functions Math.cos() and Math.sin() , a smooth trajectory is created. step+= 0.01 defines how fast the ball bounces.

At this point, the complete implementation of this example has been described. If you are interested, you can try to transform your favorite picture into a 3D view. Please, it would be cool to use Three.js to show pictures like this! 😂

🔗 full code: https://github.com/dragonir/3d/tree/master/src/containers/Comic

Summarize

The new knowledge mainly included in the knowledge points of this article:

  • THREE.Group Hierarchical Model
  • MeshPhongMaterial mesh material
  • sine cosine function creates a model movement trajectory
To learn about scene initialization, lighting, shadows, basic geometry, meshes, materials and other Three.js related knowledge, you can read my previous articles. Please indicate the original address and author . If you think the article is helpful to you, don't forget to one-click three links 👍 .

appendix


dragonir
1.8k 声望3.9k 粉丝

Accepted ✔