Home
GLSL
Three.jsにおけるシェーダー(GLSL)の基本知識

Three.jsにおけるシェーダー(GLSL)の基本知識

Three.jsにおけるシェーダー(GLSL)の基本知識

どうも!かけちまるです!

Three.jsを学習する中で必然的に学習しなければいけないのがシェーダー(GLSL)についてです。

シェーダー(GLSL)が描けるようになるとThree.jsの表現力が格段に上がります。
しかし、GLSLはC言語をベースにしているため取っ付きづらい人も多いはず。

そこで初心者向けにシェーダー(GLSL)について解説していきます。

この記事では、

  • ・シェーダー(GLSL)とは?
  • ・シェーダーを読み込む方法
  • ・GLSLの記述方法

がわかります。

GLSLとは?

GLSL(OpenGL Shading Language)はC言語構文をベースとしたシェーディング言語です。 シェーダーにはVertexShader(バーテックスシェーダー)とFragmentShader(フラグメントシェーダー)の2種類があります。

VertexShaderは、頂点情報を管理します。
FragmentShaderは、色の出力を管理します。

それぞれのファイル拡張子は、

  • VertexShader・・・.glsl または .vert
  • FragmentShader・・・.glsl または .frag

です。

Three.jsでは、ShaderMaterialRawShaderMaterialの引数でVertexShaderFragmentShaderを読み込みます。

シェーダーの読み込み方法

Three.jsでシェーダーを読み込む方法は、scriptタグにシェーダーを記述し、JavaScriptで読み込みます。

ポイント
  • scriptタグのtype属性には
    VertexShaderの場合、type="x-shader/x-vertex"
    FragmentShaderの場合、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.js
開く&閉じるコピー
import * 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の記述方法

ここでは具体的にGLSLをどのように記述するのか解説していきます。

基本的な記述

VertexShaderとFragmentShaderは、どちらもmain()関数を定義します。
その中に実行したい処理を書いていきます。

基本的にVertexShader → FragmentShaderの順に処理が実行されます。

GLSL
開く&閉じるコピー
void main(){ // この中に書いた処理が実行される }

VertexShaderについて

VertexShader
開く&閉じるコピー
void main(){ gl_Position = projectionMatrix * modelMatrix * viewMatrix * vec4(position,1.0); }

VertexShaderでは、頂点情報を管理します。
gl_Positionという組み込み変数に頂点座標を渡す必要があります。

3次元空間を表現しようとするとき、出力するのは2次元(モニター)なので奥行きや遠近法を表現するために座標変換する必要があるのです。
VertexShaderは主に座標変換する処理をしているという具合でしょうか。

  • projectionMatrix・・・カメラが三次元空間のどの領域を撮影するかの情報
  • modelMatrix・・・物体が三次元空間のどこに位置しているかのの情報
  • viewMatrix・・・カメラの位置や向きなどの情報
  • position・・・頂点情報をシェーダーで受け取るための変数

FragmentShaderについて

FragmentShader
開く&閉じるコピー
void main(){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //(r, g, b, a) }

FragmentShaderは、色の出力を管理します。
gl_FlagColorという組み込み変数に色情報を渡すことで色を表現できます。
GLSLでは0.01.0で色を表現するようです。

ストレージ修飾子について

GLSLでは、型の前に修飾子を持たせる場合があります。
修飾子は、JavaScriptでいうconstletのことです。

  • attribute・・・頂点情報などを入れる
  • uniform・・・グローバル変数を入れる
  • varying・・・VertexShaderからFragmentShaderに変数を渡すときに使う

こんな感じで使います。

GLSL
開く&閉じるコピー
uniform mat4 projectionMatrix; uniform mat4 modelMatrix; uniform mat4 viewMatrix; attribute vec3 position; varying vec2 vUv;

変数の型について

今まで説明に出てきたvec4mat4が何かというと型です。
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); }

おわり

かけちまる
かけちまる
Webエンジニアをしています。
HTML/CSS/JavaScript/jQuery/PHPができます。
WEB制作を中心に日々学びになったこと、興味が沸いたことについて初心者の方でもわかりやすいようにアウトプットしていくブログです。

関連記事

mix-blend-modeが効かない時はスタックコンテキストを考えよう

mix-blend-modeが効かない時はスタックコンテキストを考えよう

【Macユーザー向け】ngrokでローカル環境のサイトを外部へ公開

【Macユーザー向け】ngrokでローカル環境のサイトを外部へ公開

GLSLの修飾子varyingの使い方【Three.js】

GLSLの修飾子varyingの使い方【Three.js】

Amazonみたいな商品の拡大プレビュー機能を実装

Amazonみたいな商品の拡大プレビュー機能を実装

【macOS】よく使うターミナルコマンド一覧

【macOS】よく使うターミナルコマンド一覧

【Contact Form 7】ログインユーザーのためにselectのデフォルト値を設定する

【Contact Form 7】ログインユーザーのためにselectのデフォルト値を設定する