ThreeJS: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
 
(9 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
 
  https://threejs.org/editor/ (Szenen und Objekte erstellen und expportieren)
 
  https://threejs.org/editor/ (Szenen und Objekte erstellen und expportieren)
 
  https://threejs-journey.com/ Bruno Simon Course (registriert mit dev@stephanschlegel.de)
 
  https://threejs-journey.com/ Bruno Simon Course (registriert mit dev@stephanschlegel.de)
 +
https://discoverthreejs.com/tips-and-tricks/ Tipps zu Performance und vielem mehr.
  
 
  [[ThreeJS - Snippets]]
 
  [[ThreeJS - Snippets]]
Zeile 118: Zeile 119:
 
  const aspectRatio = width/height // width and height of renderer viewport
 
  const aspectRatio = width/height // width and height of renderer viewport
 
  const camera = new THREE.OrthographicCamera(-1 * aspectRatio,1 * aspectRatio,1,-1)
 
  const camera = new THREE.OrthographicCamera(-1 * aspectRatio,1 * aspectRatio,1,-1)
 +
 +
== Debugging ==
 +
=== Debug UI ===
 +
Mit einer Debug UI kann man beliebige '''Properties von Objekten''' komfortabel '''verändern'''. Das funktioniert mit allen Objekten  und ist nicht spezifisch für ThreeJS. Einzige Voraussetzung ist, dass es sich um Objekte und Eigenschaften handelt (also nicht eine normale Variable).
 +
 +
Dat.GUI ist (Ende 21) nicht mehr aktuell. Stattdessen kann man lil-gui verwenden.
 +
 +
    Dat.GUI https://github.com/dataarts/dat.gui
 +
    lil-gui https://lil-gui.georgealways.com/
 +
    control-panel https://github.com/freeman-lab/control-panel
 +
    ControlKit https://github.com/automat/controlkit.js
 +
    Uil https://github.com/lo-th/uil
 +
    Tweakpane https://cocopon.github.io/tweakpane/
 +
    Guify https://github.com/colejd/guify
 +
    Oui https://github.com/wearekuva/oui
 +
    Bruno Simon's debug panel https://bruno-simon.com/#debug
 +
==== lil-gui ====
 +
https://www.npmjs.com/package/lil-gui
 +
Mit Webpack / npm
 +
npm i --save lil-gui
 +
 +
Beispiel inkl. kleiner GSAP Animation:
 +
<syntaxhighlight lang="javascript">
 +
// https://lil-gui.georgealways.com/#
 +
import GUI from 'lil-gui';
 +
/**
 +
* Debug
 +
*/
 +
const gui = new GUI({
 +
    width:400
 +
})
 +
gui.close()
 +
const params = {
 +
    color: 0xff0000,
 +
    spin: () =>
 +
    {
 +
        console.log('spin')
 +
        let tl = new gsap.timeline
 +
        tl.to(mesh.rotation,{y: mesh.rotation.y + 0.5*Math.PI, duration: 1.5, ease: "circ"})
 +
        //...
 +
    }
 +
}
 +
//...
 +
// Debug
 +
//gui.add(mesh.position,'y',-2,2,0.1) // OR
 +
gui.add(mesh.position,'y')
 +
  .min(-2)
 +
  .max(3)
 +
  .step(0.1)
 +
  .name('elevation') // chain version
 +
gui.add(mesh,'visible')
 +
gui.add(material,'wireframe')
 +
// we can not use material.color as it's not an object
 +
// thus we use a separately created object...
 +
gui.addColor(params,'color')
 +
// ... and update material when this param changed:
 +
.onChange( ()=>
 +
{
 +
    material.color.set(params.color)
 +
})
 +
gui.add(params, 'spin')
 +
</syntaxhighlight>
 +
Viele Eigenschaften erkennt das gui selbst. Manche Eigenschaften die keine Objekteigenschaften sind kann man vorher in ein Objekt packen und diesen Wert verändern (hier z.b. Color). Danach kann man über onChange den tatsächlichen Wert ändern.
 +
 +
Auch Funktionen kann man übergeben, diese werden dann per Klick ausgelöst.
 +
 +
=== JavaScript Module oder Vanilla ===
 +
In moderneren Setups nutzt man heute Loader wie Webpack und lädt Plugins als Module. Es gibt aber alle Plugins auch als konventionelle Skripte.
 +
 +
Konventionell:
 +
<syntaxhighlight lang="javascript">
 +
<script src="\node_modules\three\build\three.js"></script>
 +
<script src="\node_modules\three\examples\js\loaders\GLTFLoader.js"></script>
 +
<script src="index.js"></script> 
 +
// Achtung bei manchen Modulen geht das hier anders als bei den Modulimporten:
 +
// You should instantiate the GLTFLoader constructor using its parent class constructor that is the 'THREE' constructor
 +
var loader = new THREE.GLTFLoader();
 +
</syntaxhighlight>
 +
 +
Modern:
 +
<syntaxhighlight lang="javascript">import './style.css'
 +
import * as THREE from 'three'
 +
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
 +
import * as dat from 'lil-gui'
 +
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
 +
import { gsap } from "gsap";
 +
import { ScrollTrigger } from "gsap/ScrollTrigger.js";
 +
gsap.registerPlugin(ScrollTrigger)
 +
//...
 +
// Hier kann die Loader Klasse direkt angesprochen werden.
 +
const gltfLoader = new GLTFLoader()
 +
</syntaxhighlight>
 +
 +
You should instantiate the GLTFLoader constructor using its parent class constructor that is the 'THREE' constructor, like I have shown above. This will resolve the issue.

Aktuelle Version vom 17. März 2022, 21:20 Uhr

https://threejs.org/
https://threejsfundamentals.org/
https://threejs.org/editor/ (Szenen und Objekte erstellen und expportieren)
https://threejs-journey.com/ Bruno Simon Course (registriert mit dev@stephanschlegel.de)
https://discoverthreejs.com/tips-and-tricks/ Tipps zu Performance und vielem mehr.
ThreeJS - Snippets

Basics[Bearbeiten]

Basic Scene[Bearbeiten]

// Canvas
const canvas = document.querySelector('canvas')
console.log(canvas)
// Scene
const scene = new THREE.Scene()
// Red cube
const geometry = new THREE.BoxGeometry(1,1,1);
const material = new THREE.MeshBasicMaterial({
  color: '#ff0000'
})
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

// Sizes
const sizes = {
  width: 800,
  height: 600,
}
const fov = 75

// Camera (field of view, aspect ratio)
const camera = new THREE.PerspectiveCamera(fov, sizes.width / sizes.height)
camera.position.z = 3 // move camera a little backward
scene.add(camera)

// Renderer
const renderer = new THREE.WebGLRenderer({
  canvas: canvas
})
renderer.setSize(sizes.width, sizes.height) // renderer needs size too
renderer.render(scene, camera)

Basic animation example[Bearbeiten]

// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ 
    color: 0xff0000 
})
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

// Sizes
const sizes = {
    width: 800,
    height: 600
}

// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)

// Renderer
const renderer = new THREE.WebGLRenderer({
    canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)

// ANIMATIONS
const clock = new THREE.Clock()

const tick = () =>
{
    const elapsedTime = clock.getElapsedTime()
    //console.log(elapsedTime)
    
    // rotate the cube
    mesh.rotation.y = elapsedTime * Math.PI * 0.1

    // circular movement of camera
    camera.position.y = Math.sin(elapsedTime)
    camera.position.x = Math.cos(elapsedTime)
    camera.lookAt(mesh.position)
    
    // Render new setting
    renderer.render(scene, camera)
    
    // tell JS to call tick on the next frame
    window.requestAnimationFrame(tick) 
}

// GO...
tick()

Camera[Bearbeiten]

Perspective Camera[Bearbeiten]

Entspricht etwa einem regulären Objektiv.

const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );

Field of View (FOV) Gibt die Brennweite vor. Gute Werte sind zwischen 45 (Weitwinkel) und 75 (Tele)

Aspect Ratio Das Seitenverhältnis des Renderbereichs. Da hier nur eine Zahl angegeben wird muss man dem Renderer noch die Endbreite mitgeben.

renderer.setSize(breite, hoehe)

Near, Far - gibt an ab welcher Entfernung Objekte nicht mehr angezeigt werden. Vermeide Extreme Werte, da diese zu Glitches führen können (z-fighting)

const camera = new THREE.PerspectiveCamera( 55, width / height, 0.1, 100 );

Orthographic Camera[Bearbeiten]

Diese Kamera hat keine Brennweite / Perspektive. D.h. entfernte Objekte erscheinen gleich groß wie nahe Objekte. Man übergibt 4 Werte: links, rechts, oben, unten

const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );

Achtung das Bild kann verzerrt erscheinen, wenn die Höhe und Breite des Renderers nicht zu diesen Werten passen. Kann man z.B. so einstellen:

const aspectRatio = width/height // width and height of renderer viewport
const camera = new THREE.OrthographicCamera(-1 * aspectRatio,1 * aspectRatio,1,-1)

Debugging[Bearbeiten]

Debug UI[Bearbeiten]

Mit einer Debug UI kann man beliebige Properties von Objekten komfortabel verändern. Das funktioniert mit allen Objekten und ist nicht spezifisch für ThreeJS. Einzige Voraussetzung ist, dass es sich um Objekte und Eigenschaften handelt (also nicht eine normale Variable).

Dat.GUI ist (Ende 21) nicht mehr aktuell. Stattdessen kann man lil-gui verwenden.

   Dat.GUI https://github.com/dataarts/dat.gui
   lil-gui https://lil-gui.georgealways.com/
   control-panel https://github.com/freeman-lab/control-panel
   ControlKit https://github.com/automat/controlkit.js
   Uil https://github.com/lo-th/uil
   Tweakpane https://cocopon.github.io/tweakpane/
   Guify https://github.com/colejd/guify
   Oui https://github.com/wearekuva/oui
   Bruno Simon's debug panel https://bruno-simon.com/#debug

lil-gui[Bearbeiten]

https://www.npmjs.com/package/lil-gui

Mit Webpack / npm

npm i --save lil-gui

Beispiel inkl. kleiner GSAP Animation:

// https://lil-gui.georgealways.com/#
import GUI from 'lil-gui'; 
/**
 * Debug
 */
const gui = new GUI({
    width:400
})
gui.close()
const params = {
    color: 0xff0000,
    spin: () =>
    {
        console.log('spin')
        let tl = new gsap.timeline
        tl.to(mesh.rotation,{y: mesh.rotation.y + 0.5*Math.PI, duration: 1.5, ease: "circ"})
        //...
    }
}
//...
// Debug
//gui.add(mesh.position,'y',-2,2,0.1) // OR
gui.add(mesh.position,'y')
  .min(-2)
  .max(3)
  .step(0.1)
  .name('elevation') // chain version
gui.add(mesh,'visible')
gui.add(material,'wireframe')
// we can not use material.color as it's not an object
// thus we use a separately created object...
gui.addColor(params,'color')
// ... and update material when this param changed:
.onChange( ()=>
{
    material.color.set(params.color)
})
gui.add(params, 'spin')

Viele Eigenschaften erkennt das gui selbst. Manche Eigenschaften die keine Objekteigenschaften sind kann man vorher in ein Objekt packen und diesen Wert verändern (hier z.b. Color). Danach kann man über onChange den tatsächlichen Wert ändern.

Auch Funktionen kann man übergeben, diese werden dann per Klick ausgelöst.

JavaScript Module oder Vanilla[Bearbeiten]

In moderneren Setups nutzt man heute Loader wie Webpack und lädt Plugins als Module. Es gibt aber alle Plugins auch als konventionelle Skripte.

Konventionell:

 <script src="\node_modules\three\build\three.js"></script>
 <script src="\node_modules\three\examples\js\loaders\GLTFLoader.js"></script>
 <script src="index.js"></script>   
 // Achtung bei manchen Modulen geht das hier anders als bei den Modulimporten:
 // You should instantiate the GLTFLoader constructor using its parent class constructor that is the 'THREE' constructor
 var loader = new THREE.GLTFLoader();

Modern:

import './style.css'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as dat from 'lil-gui'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger.js";
gsap.registerPlugin(ScrollTrigger)
//...
// Hier kann die Loader Klasse direkt angesprochen werden.
const gltfLoader = new GLTFLoader()

You should instantiate the GLTFLoader constructor using its parent class constructor that is the 'THREE' constructor, like I have shown above. This will resolve the issue.