シェーダプログラムの利用方法を記述したドキュメントです。
本ドキュメントの対象バージョンは akashic-engine@2.3.2
以降です。
また、本機能を利用するには WebGL 1.0 が利用可能な環境が必要です。 こちらのページ で現在利用しているブラウザが WebGL をサポートしているか確認することができます。
WebGL, OpenGL などで、3 次元空間に存在する情報を 2 次元空間に描画するために用いられているプログラムのことを指します。詳細については他のドキュメントを参照ください。
本ドキュメントでは Akashic でシェーダを利用する方法について記述します。
akashic-engine@2.3.2
ではフラグメントシェーダのみをサポートします。
ゲーム開発の準備が終わっていない場合は Akashic を利用したゲーム開発 を読んでゲーム開発の環境を整えて下さい。
本ドキュメントの内容は akashic-sandbox@0.13.24
以降のバージョンでサポートされています。手元の akashic-sandbox のバージョンがこれより古い場合は以下のコマンドで最新のものをインストールしてください。
npm i @akashic/akashic-sandbox -g
コンテンツで WebGL を有効にするため、 game.json
の renderers
に webgl
を追加します。詳細は game.json の仕様 を参照してください。
まずはゲーム内でシェーダを利用するための準備をします。
以下は出力色をモノクロ化するフラグメントシェーダの記述になります。
#version 100
precision mediump float;
varying vec2 vTexCoord;
uniform sampler2D uSampler;
uniform float uAlpha;
void main(void)
{
// 対象ピクセルの色情報を取得
vec4 color = texture2D(uSampler, vTexCoord);
// 対象ピクセルのRGB値を加算
float sum = dot(color.rgb, vec3(1.0));
// モノクロ化
vec3 outColor = vec3(sum / 3.0);
// 最終出力色
gl_FragColor = vec4(outColor, color.a * uAlpha);
}
このシェーダをコンテンツ内で利用するために、 g.ShaderProgram
を生成します。
(注意: この生成方法は akashic-engine@2.3.2
時点での記述になります。今後のバージョンでは変更される可能性があります。)
// フラグメントシェーダのテキストデータ
const fragmentShader =
"#version 100\n" +
"precision mediump float;\n" +
"varying vec2 vTexCoord;\n" +
"uniform sampler2D uSampler;\n" +
"uniform float uAlpha;\n" +
"void main(void)\n" +
"{\n" +
" vec4 color = texture2D(uSampler, vTexCoord);\n" +
" float sum = dot(color.rgb, vec3(1.0));\n" +
" vec3 outColor = vec3(sum / 3.0);\n" +
" gl_FragColor = vec4(outColor, color.a * uAlpha);\n" +
"}";
const shader = new g.ShaderProgram({
fragmentShader: fragmentShader
});
g.ShaderProgram
は g.E
やそれを継承したクラス (g.Sprite
, g.Pane
など) に適用できます。以下のようにコンストラクタのパラメータに指定することができます。
var sprite = new g.Sprite({
scene: scene,
src: scene.assets["sample"],
width: 100,
height: 100,
shaderProgram: shader
});
既存の g.Sprite
に適用することもできます。その場合は変更後に g.Sprite#modified()
を呼ぶ必要があります。
sprite.shaderProgram = shader;
sprite.modified();
シェーダプログラムは親エンティティの値を継承します。そのため、シェーダプログラムを適用したエンティティに複数の子エンティティに追加することで、複数のエンティティに同一のシェーダプログラムを適用することができます。
設定したシェーダを戻したい場合、 undefined
または null
を指定します。
undefined
と null
は以下のように挙動が異なることにご留意ください。
undefined
null
undefined
)を利用する。注意点として、 g.ShaderProgram
は一度生成したら以降プロパティを変更することはできません。
(例外的に g.ShaderProgram#uniforms#value
のみ変更が許可されています。詳細は後述します。)
akashic-engine@2.3.2
時点では、以下の変数がエンジン側から暗黙的に与えられます。
varying
vec2 vTexCoord
uniform
sampler2D uSampler
float uAlpha
ユーザが独自に定義した変数をフラグメントシェーダに与えることができます。
先程のサンプルにおいて、各色の重み付けをコンテンツから指定した例が以下になります。
#version 100
precision mediump float;
varying vec2 vTexCoord;
uniform sampler2D uSampler;
uniform float uAlpha;
uniform float redScale;
uniform float greenScale;
uniform float blueScale;
vec3 monoScale = vec3(redScale, greenScale, blueScale);
float monoScaleSum = dot(monoScale, vec3(1.0));
void main(void)
{
// 対象ピクセルの色情報を取得
vec4 color = texture2D(uSampler, vTexCoord);
// 対象ピクセルのRGB値を加算
float sum = dot(color.rgb, monoScale);
// モノクロ化
vec3 outColor = vec3(sum / monoScaleSum);
// 最終出力色
gl_FragColor = vec4(outColor, color.a * uAlpha);
}
redScale
, greenScale
, blueScale
が uniform 値として渡されるようにフラグメントシェーダを修正しています。
g.ShaderProgram
の生成時に利用する uniform を定義します。
const shader = new g.ShaderProgram({
fragmentShader: fragmentShader,
uniforms: {
redScale: {
type: "float",
value: 0.299
},
greenScale: {
type: "float",
value: 0.587
},
blueScale: {
type: "float",
value: 0.114
}
}
});
uniform
は、フラグメントシェーダで利用する際の変数名をキーとしたオブジェクトによって定義されます。各キーは g.ShaderUniform
によって定義された形式で記述する必要があります。
type
は対象の uniform の型、value
はその値を示します。
type
には以下が指定できます。
float
int
vec2
vec3
vec4
ivec2
ivec3
ivec4
mat2
mat3
mat4
また、以下のように Array を利用することもできます。
フラグメントシェーダ
uniform param[3];
コンテンツ
const shader = new g.ShaderProgram({
fragmentShader: fragmentShader,
uniforms: {
param: {
type: "float",
value: [0.0, 1.0, 0.4]
}
}
});
g.ShaderProgram#uniform#value
の値はプログラムの実行中に任意に変更できます。
scene.update.add(() => {
shader.uniforms.time.value = scene.game.age;
});