Skip to content

Examples : Shiny Refraction

Description

<>

This example demonstrates,

  • Using the EffectComposer to add a Depth of Field (DOF) effect.
  • Dynamically changing the DOF depending on camera and ball distance.
  • Changing MeshPhysicalMaterial properties using the GUI.

Code

./src/client/client.ts

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
import { GUI } from 'dat.gui'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { BokehPass } from 'three/examples/jsm/postprocessing/BokehPass'
const scene = new THREE.Scene()
const envTexture = new THREE.CubeTextureLoader().load([
    'img/px_25.jpg',
    'img/nx_25.jpg',
    'img/py_25.jpg',
    'img/ny_25.jpg',
    'img/pz_25.jpg',
    'img/nz_25.jpg',
])
scene.background = envTexture
const ambientLight = new THREE.AmbientLight(0x444444)
scene.add(ambientLight)
const light1 = new THREE.PointLight(0xffffff, 1000)
light1.position.set(-6, 10, -6)
light1.castShadow = true
light1.shadow.mapSize.height = 1024
light1.shadow.mapSize.width = 1024
scene.add(light1)
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.01,
    100
)
camera.position.set(3, 1.5, 3)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
document.body.appendChild(renderer.domElement)
const renderPass = new RenderPass(scene, camera)
const bokehPass = new BokehPass(scene, camera, {
    focus: 1.0,
    aperture: 0.0001,
    maxblur: 1.0,
    width: window.innerWidth,
    height: window.innerHeight,
})
const composer = new EffectComposer(renderer)
composer.addPass(renderPass)
composer.addPass(bokehPass)
const orbitControls = new OrbitControls(camera, renderer.domElement)
orbitControls.enableDamping = true
orbitControls.target.set(1, 0, 0)
const planeGeometry = new THREE.PlaneGeometry(25, 25)
const texture = new THREE.TextureLoader().load('img/grid.png')
const plane = new THREE.Mesh(
    planeGeometry,
    new THREE.MeshPhongMaterial({ map: texture })
)
plane.rotateX(-Math.PI / 2)
plane.position.y = -1
plane.receiveShadow = true
scene.add(plane)
window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    composer.setSize(window.innerWidth, window.innerHeight)
}
const pivot = new THREE.Object3D()
scene.add(pivot)
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(2048)
const cubeCamera = new THREE.CubeCamera(0.1, 100, cubeRenderTarget)
scene.add(cubeCamera)
const material = new THREE.MeshPhysicalMaterial({
    reflectivity: 1.0,
    transmission: 1.0,
    roughness: 0,
    metalness: 0,
    clearcoat: 0.3,
    clearcoatRoughness: 0.25,
    color: new THREE.Color(0xffffff),
    ior: 1.5,
})
material.thickness = 50.0

//cubeRenderTarget.texture.mapping = THREE.CubeRefractionMapping;
const ball = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32), material)
ball.position.set(1.5, 0, 0)
ball.castShadow = true
pivot.add(ball)
const gui = new GUI()
const ballFolder = gui.addFolder('Ball1')
ballFolder.add(ball, 'visible').name('Visible')
ballFolder.add(material, 'metalness', 0, 1.0, 0.01).name('Metalness')
ballFolder.add(material, 'roughness', 0, 1.0, 0.01).name('Roughness')
ballFolder.add(material, 'transmission', 0, 1.0, 0.01).name('Transmission')
ballFolder.add(material, 'clearcoat', 0, 1.0, 0.01).name('Clearcoat')
ballFolder
    .add(material, 'clearcoatRoughness', 0, 1.0, 0.01)
    .name('ClearcoatRoughness')
ballFolder.add(material, 'reflectivity', 0, 1.0, 0.01).name('Reflectivity')
ballFolder.add(material, 'ior', 1.0, 2.333, 0.01).name('IOR')
ballFolder.add(material, 'thickness', 0, 50.0, 0.1).name('thickness')
ballFolder.open()
const stats = new Stats()
document.body.appendChild(stats.dom)
const clock = new THREE.Clock()
var animate = function () {
    requestAnimationFrame(animate)
    orbitControls.update()
    const ballWorldPosition = new THREE.Vector3()
    ball.getWorldPosition(ballWorldPosition)
    ;(bokehPass.uniforms as any).focus.value =
        camera.position.distanceTo(ballWorldPosition)
    const delta = clock.getDelta()
    ball.rotateY(-0.5 * delta)
    pivot.rotateY(0.5 * delta)
    render()
    stats.update()
}
function render() {
    cubeCamera.position.copy(camera.position)
    cubeCamera.update(renderer, scene)
    //renderer.render(scene, camera)
    composer.render(0.1)
}
animate()

Comments