Light and shadow

Make writing a habit together! This is the third day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

preface

In this paper, the simulated sunlight in smart city changes over time to produce corresponding scene effects. In order to make the scene more realistic, we usually synchronize various environmental factors such as weather and sunshine to the scene to make the scene more realistic. For example, some common weather systems, such as rain, snow, cloudy days and haze, will be withdrawn in an independent article later. This article mainly introduces a series of lights, mainly the imitation of the sun by parallel light, as well as some material problemsCopy the code

Lighting and material basics

Common lighting: - point light sources (point source can be understood as a emits light in all directions at the same time, we usually used to simulate the light bulb, can produce the shadow) - parallel light (parallel light can imagine into a beam of light from exposure to infinity, usually used to simulate the sun, can produce the shadow) - the spotlight (spotlight literally means like stage lights, - Ambient light (generally used to change the overall brightness of the scene, is also one of the most common light sources) (just to list the common ones) - MeshBasicMaterial, Shadow not supported) - FBR material - MeshStandardMaterial - MeshPhysicalMaterial - both of the above FBR materials are better than the highlights mesh material - MeshPhongMaterial (High light mesh material, high light surface, specular reflection) - MeshLambertMaterial (Lambert mesh material, dim, diffuse reflection) here is a brief introduction, students who do not understand the specific material to understandCopy the code

The light from the sun

Graph LR adds parallel lights -> Adjust position from east to west -> Adjust brightness and color -> Add transition to simulate sunlight
Next, how to simulate the change of solar illumination is the focus of this paper. In fact, the principle is very simple, is to add parallel light, adjust the shadow relationship of the scene model, according to the time to change the position of parallel light, light intensity and color can simulate ~Copy the code

Overall calling code

Because it is a demo, so pay attention to the effect, all from the simple implementation of the functionCopy the code
sun() { // Parallel light changes every 2 seconds
  let i=0
  setInterval(() = >{
    this.initSun(i)
    i++
  },2000)}Copy the code
Simple realization through the timer and write the corresponding position illumination information in advance. The sun should be adjusted according to the system time, including according to the weather, change the soup and do not change the clothes, mainly manually adjusted and stored as JSON through the incoming time and weather to make the transformation ~Copy the code
Viewer.prototype.initSun = function (type) {
  let position = {}
  let color = '#ffffff'
  let intensity = 1
  switch (type) {
    case 0:
      position = {
        x: 270.y: 150.z: 0
      }
      intensity = 5
      break
    case 1:
      position = {
        x: 258.y: 170.z: 0
      }
      intensity = 7
      color = '#fcffc9'
      break
    case 2:
      position = {
        x: 245.y: 180.z: 0
      }
      intensity = 10
      color = '#ffe69f'
      break
    case 3:
      position = {
        x: 0.y: 100.z: 0
      }
      intensity = 15
      color = '#ffe69f'
      break
    case 4:
      position = {
        x: -245.y: 180.z: 0
      }
      intensity = 10
      color = '#e3894d'
      break
    case 5:
      position = {
        x: -258.y: 160.z: 0
      }
      intensity = 10
      color = '#ff8400'
      break
    default :
      position = {
        x: -270.y: 150.z: 0
      }
      intensity = 8
      color = '#ff8400'
      break
  }
  if (this.directionalLight) {
    this.directionalLight.setSun(position,color,intensity)
  } else {
    this.directionalLight = new zhdSun()
    this.directionalLight.renderFn(this.renderFunction)
    this.directionalLight.init({
      position,
      color,
      intensity,
      scene: this.scene,
      currentlayers: this.currentlayers
    })
  }
}
Copy the code

The sun’s rays class

Here is mainly on the sunlight disassembly and analysis, the packaging is rough, as appropriate, individual can be optimizedCopy the code
import TWEEN from '@tweenjs/tween.js'
import {zhdObject} from './zhdObject'

export class zhdSun extends zhdObject {
  constructor() {
    super(a)this.light = null}}Since the TWEEN library is added, remember to update TWEEN in animate in real time
TWEEN.update()
Copy the code

Initialize the

Here to do is to add a parallel light in the scene, set its properties such as shadow and the range of distance, because my side involves hierarchy, so set up a parallel light levels Parallel light is all light shadow adjustments in the most trouble, want to can produce parallel light to shadow, shadow model and receive shadows to adjust, And the irradiation range of parallel light should also be adjusted. In my renderings, I don't know if you noticed that at noon the sun shines on the ground and creates a rectangular area of shadow. Here is a less perfect version. Cause: The parallel light range is too small, but once you adjust the parallel light range too large, since the ground is loaded by multiple tiles, there will be striped shadows as shown in the picture belowCopy the code

init({position, color, intensity , currentlayers, scene}) {
  const directionalLight = new THREE.DirectionalLight(color, intensity) // Create a new parallel light source. The color is not white and the intensity is 1
  this.light = directionalLight
  directionalLight.position.set(position.x, position.y, position.z) // Adjust the parallel light source to a suitable position
  directionalLight.castShadow = true // Turn on the shadow casting property for this parallel light source
  // Set the shadow attribute of the parallel light, i.e. the length, width and height of a cuboid. Only objects within the range of the set value will generate shadows
  const d =100 // Shadow rangedirectionalLight.shadow.camera.left = -d directionalLight.shadow.camera.right = d directionalLight.shadow.camera.top = d  directionalLight.shadow.camera.bottom = -d directionalLight.shadow.camera.near =20
  directionalLight.shadow.camera.far = 8000
  directionalLight.shadow.mapSize.x = 2048 // Define the width and height of the shadow map, which must be an integer power of 2
  directionalLight.shadow.mapSize.y = 2048 // Higher values provide better shadow quality at the cost of calculation time
  directionalLight.shadow.bias = -0.0005 // Resolve the appearance of stripe shadows
  this.setlayers(directionalLight, currentlayers)
  scene.add(directionalLight) // Add the parallel light source to the scene, we can see the light source
  return directionalLight
}
Copy the code

Set the parallel light information

Set the information of parallel light, including position, color and intensityCopy the code
setSun(position, color, intensity) {
  this.setTweens(this.light.position, position, 2000)
  this.light.color = new THREE.Color( color )
  this.light.intensity = intensity
}
Copy the code

Tween

Here is a brief introduction to what TWEEN does not understand and you can read my previous article, mainly an animation library, here to do a simple encapsulationCopy the code
setTweens(obj, newObj, duration = 1500) {
  var ro = new TWEEN.Tween(obj)
  ro.to(newObj, duration) // Change the position and animation time
  ro.easing(TWEEN.Easing.Sinusoidal.InOut)
  ro.onUpdate(function () {
  })
  ro.start()
}
Copy the code