MeshToonMaterial
Video Lecture
Description
Toon shading or Cel shading is a type of non-photorealistic rendering technique designed to make 3D computer graphics appear more cartoonish by using less shading color instead of a smooth gradient effect.
Start 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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | // If using Relative Import References import * as THREE from '/build/three.module.js' import { OrbitControls } from '/jsm/controls/OrbitControls' import Stats from '/jsm/libs/stats.module' import { GUI } from '/jsm/libs/dat.gui.module' // If using Module Specifiers //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 'three/examples/jsm/libs/dat.gui.module' const scene: THREE.Scene = new THREE.Scene() const axesHelper = new THREE.AxesHelper(5) scene.add(axesHelper) const light = new THREE.PointLight(0xffffff, 1); light.position.set(5, 5, 5); scene.add(light); const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer() renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement) const controls = new OrbitControls(camera, renderer.domElement) const boxGeometry: THREE.BoxGeometry = new THREE.BoxGeometry() const sphereGeometry: THREE.SphereGeometry = new THREE.SphereGeometry() const icosahedronGeometry: THREE.IcosahedronGeometry = new THREE.IcosahedronGeometry(1, 0) const planeGeometry: THREE.PlaneGeometry = new THREE.PlaneGeometry() const torusKnotGeometry: THREE.TorusKnotGeometry = new THREE.TorusKnotGeometry() const threeTone = new THREE.TextureLoader().load("img/threeTone.jpg") threeTone.minFilter = THREE.NearestFilter; threeTone.magFilter = THREE.NearestFilter; const fourTone = new THREE.TextureLoader().load("img/fourTone.jpg") fourTone.minFilter = THREE.NearestFilter; fourTone.magFilter = THREE.NearestFilter; const fiveTone = new THREE.TextureLoader().load("img/fiveTone.jpg") fiveTone.minFilter = THREE.NearestFilter; fiveTone.magFilter = THREE.NearestFilter; const material: THREE.MeshToonMaterial = new THREE.MeshToonMaterial() const cube: THREE.Mesh = new THREE.Mesh(boxGeometry, material) cube.position.x = 5 scene.add(cube) const sphere: THREE.Mesh = new THREE.Mesh(sphereGeometry, material) sphere.position.x = 3 scene.add(sphere) const icosahedron: THREE.Mesh = new THREE.Mesh(icosahedronGeometry, material) icosahedron.position.x = 0 scene.add(icosahedron) const plane: THREE.Mesh = new THREE.Mesh(planeGeometry, material) plane.position.x = -2 scene.add(plane) const torusKnot: THREE.Mesh = new THREE.Mesh(torusKnotGeometry, material) torusKnot.position.x = -5 scene.add(torusKnot) camera.position.z = 5 window.addEventListener('resize', onWindowResize, false) function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) render() } const stats = Stats() document.body.appendChild(stats.dom) var options = { side: { "FrontSide": THREE.FrontSide, "BackSide": THREE.BackSide, "DoubleSide": THREE.DoubleSide, }, gradientMap: { "Default": null, "threeTone": "threeTone", "fourTone": "fourTone", "fiveTone": "fiveTone" } } const gui = new GUI() var data = { lightColor : light.color.getHex(), color: material.color.getHex(), gradientMap: "fiveTone" } material.gradientMap = fiveTone const lightFolder = gui.addFolder('THREE.Light') lightFolder.addColor(data, 'lightColor').onChange(() => { light.color.setHex(Number(data.lightColor.toString().replace('#', '0x'))) }) lightFolder.add(light, "intensity", 0, 4) const materialFolder = gui.addFolder('THREE.Material') materialFolder.add(material, 'transparent') materialFolder.add(material, 'opacity', 0, 1, 0.01) materialFolder.add(material, 'depthTest') materialFolder.add(material, 'depthWrite') materialFolder.add(material, 'alphaTest', 0, 1, 0.01).onChange(() => updateMaterial()) materialFolder.add(material, 'visible') materialFolder.add(material, 'side', options.side).onChange(() => updateMaterial()) //materialFolder.open() var meshToonMaterialFolder = gui.addFolder('THREE.MeshToonMaterial') meshToonMaterialFolder.addColor(data, 'color').onChange(() => { material.color.setHex(Number(data.color.toString().replace('#', '0x'))) }) meshToonMaterialFolder.add(material, 'flatShading').onChange(() => updateMaterial()) meshToonMaterialFolder.add(data, 'gradientMap', options.gradientMap).onChange(() => updateMaterial()) meshToonMaterialFolder.open() function updateMaterial() { material.side = Number(material.side) material.gradientMap = eval(data.gradientMap as any) material.needsUpdate = true } var animate = function () { requestAnimationFrame(animate) icosahedron.rotation.y += .005 icosahedron.rotation.x += .005 cube.rotation.y += .005 cube.rotation.x += .005 torusKnot.rotation.y += .005 torusKnot.rotation.x += .005 sphere.rotation.y += .005 sphere.rotation.x += .005 plane.rotation.y += .005 plane.rotation.x += .005 render() stats.update() }; function render() { renderer.render(scene, camera) } animate(); |