Template Dasar Aplikasi WebGL menggunakan three.js

Sangat disarankan untuk membuat aplikasi WebGL dengan menggunakan web server. Anda dapat menggunakan web server favorit Anda. Pada tutorial ini digunakan node.js dengan Parcel karena parcel berfungsi sebagai bundler dan web server.

Pada direktori project, install three.js dengan menggunakan npm install.

npm install --save three

Lalu pada root direktori, buat file index.html, tambahkan code berikut sebagai template awal.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three</title>
    <style>
        body{margin:0; padding:0;}
        canvas{display: block;}
        #container{width: 100vw;height: 100vh}
    </style>
</head>
<body>
    <div id="container"></div>
    <script src="js/app.js"></script>
</body>
</html>

Kemudian buat direktori js untuk menyimpan file javascript. Kemudian buat file app.js pada direktori tersebut. File ini berisi code yang berhubungan dengan three.js.

import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import fragment from './shaders/fragment.glsl';
import vertex from './shaders/vertex.glsl';

export default class Sketch{
	constructor(opt){
		this.time = 0;
		this.container = opt.dom;

		this.scene = new THREE.Scene();

		this.width = this.container.offsetWidth;
		this.height = this.container.offsetHeight;

		this.camera = new THREE.PerspectiveCamera( 70, this.width / this.height, 0.01, 10 );
		this.camera.position.z = 1;

		this.renderer = new THREE.WebGLRenderer( { antialias: true } );
		
		this.container.appendChild( this.renderer.domElement );
	
		this.controls = new OrbitControls(this.camera, this.renderer.domElement);

		this.resize();
		this.setupResize();
		this.addObject();
		this.render();
	}
	
	setupResize(){
		window.addEventListener('resize', this.resize.bind(this));
	}

	resize(){
		this.width = this.container.offsetWidth;
		this.height = this.container.offsetHeight;
		this.renderer.setSize (this.width, this.height);
		this.camera.aspect = this.width/this.height;
		this.camera.updateProjectionMatrix();
	}

	addObject(){
		this.geometry = new THREE.PlaneBufferGeometry( 0.5, 0.5, 10, 10);
		this.material = new THREE.MeshNormalMaterial();

		this.material = new THREE.ShaderMaterial({
			side: THREE.DoubleSide,
			fragmentShader: fragment,
			vertexShader: vertex,
			wireframe: true,
		});		

		this.mesh = new THREE.Mesh( this.geometry, this.material );
		this.scene.add( this.mesh );
	}

	render(){
		this.time+=0.05;

		this.mesh.rotation.x = this.time / 2000;
		this.mesh.rotation.y = this.time / 1000;
	
		this.renderer.render( this.scene, this.camera );

		window.requestAnimationFrame(this.render.bind(this));

	}
}


new Sketch({
	dom: document.getElementById('container')
});

Masih pada direktori js, tambahkan folder shaders, untuk menyimpan file fragment dan vertex shader.

Buat fie baru dengan nama fragment.glsl yang akan digunakan untuk memberikan pewarnaan pada object three.js.

Berikut isi lengkap file js/shaders/fragment.glsl

void main(){
	gl_FragColor = vec4(1.,0.,1.,1.);
}

Buat file baru dengan nama file vertex.glsl yang akan digunakan untuk manipulasi vertex pada object three.js.

Berikut isi lengkap file js/shaders/vertex.glsl

void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}

Pembahasan Code

Kita akan buat class Sketch untuk aplikasi WebGL. Dengan 5 fungsi utama:

  • constructor, untuk inisialisasi object yang diperlukan, seperti scene, camera, renderer dan control.
  • setupResize, untuk menambahkan event listener saat window resizer terjadi.
  • resize, fungsi untuk menangani resize.
  • addObject, dalam fungsi ini dilakukan penambahan object 3D yang diperlukan.
  • render, fungsi untuk melakukan rendering ke element canvas.

Tujuannya agar code lebih clean dan mudah dibaca karena kita pisahkan code berdasarkan fungsi dan tujuannya masing-masing.

Code ini hanya berupa boilerplate atau template dasar, jadi bisa berkembang dan berubah saat kita membuat aplikasi.

constructor

constructor adalah fungsi yang pertama kali dipanggil saat object dicreate.

constructor menerima parameter opt yang berisi informasi element container yang digunakan untuk rendering.

Untuk menampilkan object dalam three.js, kita memerlukan 3 object: scene, camera and renderer. Ketiga object tersebut kita inisialisasi dalam fungsi constructor.

Setelah proses inisialisasi selesai, selanjutnya kita panggil fungsi-fungsi yang kita buat untuk menangani penambahan object, dan resize.

constructor(opt){
    this.time = 0;
    this.container = opt.dom;

    this.scene = new THREE.Scene();

    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;

    this.camera = new THREE.PerspectiveCamera( 70, this.width / this.height, 0.01, 10 );
    this.camera.position.z = 1;

    this.renderer = new THREE.WebGLRenderer( { antialias: true } );
    
    this.container.appendChild( this.renderer.domElement );

    this.controls = new OrbitControls(this.camera, this.renderer.domElement);

    this.resize();
    this.setupResize();
    this.addObject();
    this.render();
}

resize

Fungsi resize akan dipanggil saat window browser berubah ukuran. Yang perlu dihitung ulang saat browser di resize adalah lebar dan tinggi dari container serta aspect ratio.

Ukuran yang sudah dihitung ulang diset ke object renderer dengan perintah renderer.setSize.

resize(){
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;
    this.renderer.setSize (this.width, this.height);
    this.camera.aspect = this.width/this.height;
    this.camera.updateProjectionMatrix();
}

setupResize

Fungsi setupResize hanya fungsi sederhana untuk menambahkan event listener.

setupResize(){
    window.addEventListener('resize', this.resize.bind(this));
}

addObject

Fungsi addObject adalah fungsi dimana kita akan menambahkan object kedalam scene. Untuk boilerplate, digunakan Plane.

Perhatikan kita akan menggunakan ShadderMaterial. Berikut property yang digunakan

side: untuk menentukan sisi mana yang akan dirender. Pada tutorial kedua sisi akan dirender.
fragmentShadder: shadder untuk mengatur coloring, akan digunakan file ./shaders/fragment.glsl.
vertextShadder: untuk manipulasi vertex, akan digunakan file ./shaders/vertex.glsl.
wireframe: menentukan tampilan sebagai wireframe. Akan mempermudah proses debuging tampilan.

addObject(){
    this.geometry = new THREE.PlaneBufferGeometry( 0.5, 0.5, 10, 10);
    this.material = new THREE.MeshNormalMaterial();

    this.material = new THREE.ShaderMaterial({
        side: THREE.DoubleSide,
        fragmentShader: fragment,
        vertexShader: vertex,
        wireframe: true,

    });		

    this.mesh = new THREE.Mesh( this.geometry, this.material );
    this.scene.add( this.mesh );
}

render

fungsi untuk rendering object. Untuk melakukan rendering digunakan perintah renderer.render dengan parameter scene dan camera.

render(){
    this.time+=0.05;

    this.mesh.rotation.x = this.time / 2000;
    this.mesh.rotation.y = this.time / 1000;

    this.renderer.render( this.scene, this.camera );

    window.requestAnimationFrame(this.render.bind(this));

}

Menjalankan Parcel

Jika Anda belum menginstall parcel, jalankan pertama kali dengan perintah npx parcel index.html.

Jika sudah memiliki parcel, cukup jalankan dengan perintah parcel index.html.

Jika tidak ada masalah, maka pada web browser akan tampil seperti berikut.

Dokumentasi

Sharing is caring:

Leave a Comment