どうも!かけちまるです!
Three.jsを学習する中で必然的に学習しなければいけないのがシェーダー(GLSL)についてです。
シェーダー(GLSL)が描けるようになるとThree.jsの表現力が格段に上がります。
しかし、GLSLはC言語をベースにしているため取っ付きづらい人も多いはず。
そこで初心者向けにシェーダー(GLSL)について解説していきます。
この記事では、
がわかります。
GLSL(OpenGL Shading Language)はC言語構文をベースとしたシェーディング言語です。 シェーダーにはVertexShader(バーテックスシェーダー)とFragmentShader(フラグメントシェーダー)の2種類があります。
VertexShaderは、頂点情報を管理します。
FragmentShaderは、色の出力を管理します。
それぞれのファイル拡張子は、
.glsl
または .vert
.glsl
または .frag
です。
Three.jsでは、ShaderMaterial
かRawShaderMaterial
の引数でVertexShader
とFragmentShader
を読み込みます。
Three.jsでシェーダーを読み込む方法は、script
タグにシェーダーを記述し、JavaScriptで読み込みます。
script
タグのtype
属性にはtype="x-shader/x-vertex"
type="x-shader/x-fragment"
こんな感じになると思います。
ディレクトリ構成index.html js/ -main.js
index.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script async src="https://unpkg.com/es-module-shims@1.5.8/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.142.0/build/three.module.js" } } </script> <script src="./js/main.js" type="module"></script> <style> *{ margin: 0; padding: 0; box-sizing: border-box; } canvas{ position: fixed; top: 0; left: 0; z-index: -1; } </style> </head> <body> <script id="v-shader" type="x-shader/x-vertex"> void main(){ gl_Position = projectionMatrix * modelMatrix * viewMatrix * vec4(position,1.0); } </script> <script id="f-shader" type="x-shader/x-fragment"> void main(){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } </script> </body> </html>
main.jsimport * as THREE from 'three'; /** * シーン・カメラ・レンダラーを用意する */ const fov = 50; const fovRad = (fov / 2) * (Math.PI / 180); // 視野角をラジアンに変換 let distance = (window.innerHeight / 2) / Math.tan(fovRad); // カメラ距離を求める const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 0.1, 2000 ); camera.position.z = distance; const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); /** * ジオメトリ+マテリアル=メッシュを用意する */ const planeGeometry = new THREE.PlaneGeometry(200, 200); const shaderMaterial = new THREE.ShaderMaterial({ //バーテックスシェーダを設定 vertexShader: document.querySelector('#v-shader').textContent, //フラグメントシェーダを設定 fragmentShader: document.querySelector('#f-shader').textContent, }); let mesh = new THREE.Mesh(planeGeometry, shaderMaterial); scene.add(mesh); // アニメーション function animate() { renderer.render(scene, camera); requestAnimationFrame(animate); } animate(); // ブラウザのリサイズに対応させる window.addEventListener('resize', onWindowResize); function onWindowResize() { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = window.innerWidth / window.innerHeight; distance = (window.innerHeight / 2) / Math.tan(fovRad); camera.position.z = distance; camera.updateProjectionMatrix(); }
ここでは具体的にGLSLをどのように記述するのか解説していきます。
VertexShaderとFragmentShaderは、どちらもmain()
関数を定義します。
その中に実行したい処理を書いていきます。
基本的にVertexShader → FragmentShaderの順に処理が実行されます。
GLSLvoid main(){ // この中に書いた処理が実行される }
VertexShadervoid main(){ gl_Position = projectionMatrix * modelMatrix * viewMatrix * vec4(position,1.0); }
VertexShaderでは、頂点情報を管理します。gl_Position
という組み込み変数に頂点座標を渡す必要があります。
3次元空間を表現しようとするとき、出力するのは2次元(モニター)なので奥行きや遠近法を表現するために座標変換する必要があるのです。
VertexShaderは主に座標変換する処理をしているという具合でしょうか。
FragmentShadervoid main(){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //(r, g, b, a) }
FragmentShaderは、色の出力を管理します。gl_FlagColor
という組み込み変数に色情報を渡すことで色を表現できます。
GLSLでは0.0
〜1.0
で色を表現するようです。
GLSLでは、型の前に修飾子を持たせる場合があります。
修飾子は、JavaScriptでいうconst
やlet
のことです。
attribute
・・・頂点情報などを入れるuniform
・・・グローバル変数を入れるvarying
・・・VertexShaderからFragmentShaderに変数を渡すときに使うこんな感じで使います。
GLSLuniform mat4 projectionMatrix; uniform mat4 modelMatrix; uniform mat4 viewMatrix; attribute vec3 position; varying vec2 vUv;
今まで説明に出てきたvec4
やmat4
が何かというと型です。
GLSLでは、変数に型を指定する必要があります。
ここでは、よく使うであろう型をご紹介します。
型 | 意味 |
---|---|
bool |
条件型、true またはfalse の値を取る |
int |
整数 |
float |
浮動小数点 |
vec2 |
2要素の浮動小数点ベクトル |
vec3 |
3要素の浮動小数点ベクトル |
vec4 |
4要素の浮動小数点ベクトル |
mat2 |
2×2の浮動小数点行列 |
mat3 |
3×3の浮動小数点行列 |
mat4 |
4×4の浮動小数点行列 |
sampler2D |
2Dテクスチャへアクセスするハンドル |
GLSLでのコメントアウトは、
1行の場合は、//
で複数行の場合は/**/
です。
GLSL/*void main(){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }*/ void main(){ // gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); }
おわり
フィードバックを送信
記事についてのフィードバックはTwitterかお問い合わせフォームから受け付けております。