Shader

シェーダー

着色器

As of 1.12.0, Ebitengine has APIs to render custom shaders. This document explains how to use custom shaders.

バージョン 1.12.0 から、カスタムシェーダを描画する API が Ebitengine に入りました。このドキュメントでは、カスタムシェーダの使い方について説明します。

What's a shader?

シェーダとは

A shader is a program executed on GPU. A custom shader is a shader an Ebitengine user can write. With shaders, you can execute a complex rendering on GPU efficiently.

シェーダは GPU 上で実行されるプログラムです。カスタムシェーダは Ebitengine ユーザーが記述できるシェーダです。シェーダを使うことで、複雑な描画が GPU 上で効率的にできるようになります。

In Ebitengine, you can write a 'fragment shader'. A fragment shader is a shader executed on each pixel. Roughly speaking, this is a function to calculate a color for each pixel. This color calculation is executed on GPU in parallel.

Ebitengine はシェーダのうちフラグメントシェーダと呼ばれるものが記述できます。フラグメントシェーダはピクセルごとに実行されるシェーダです。大雑把に言うと、ピクセルごとに色を計算する関数です。この色の計算が、 GPU 上で並列に走ります。

With shaders, you can execute various effects like lighting or blur. For an example, see examples/shader.

シェーダを使うことでライティング、ブラーなどの様々な効果が実現できます。サンプルについては examples/shader を参照してください。

go run -tags=example github.com/hajimehoshi/ebiten/v2/examples/shader@latest

Ebitengine adopts an original shading language 'Kage'. This has a compatible syntax with Go, but the details are different. Kage has high portability. Ebitengine uses graphics libraries like OpenGL or Metal and this depends on environments, but Kage is compiled on the fly so that this works equally everywhere.

Ebitengine はシェーディング言語として Kage という独自言語を採用しています。これは Go 互換の文法を持ちますが、細部が Go とは異なります。 Kage は高いポータビリティを持ちます。 Ebitengine は環境によって OpenGL や Metal などをグラフィックスライブラリとして使いますが、 Kage はどの環境でも同様に動くように、動的にコンパイルされます。

Example

package main

// Uniform variables.
var Time float
var Cursor vec2
var ScreenSize vec2

// Fragment is the entry point of the fragment shader.
// Fragment returns the color value for the current position.
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
	// You can define variables with a short variable declaration like Go.
	lightpos := vec3(Cursor, 50)
	lightdir := normalize(lightpos - position.xyz)
	normal := normalize(imageSrc1UnsafeAt(texCoord) - 0.5)
	ambient := 0.25
	diffuse := 0.75 * max(0.0, dot(normal.xyz, lightdir))

	// You can treat multiple source images by
	// imageSrc[N]At or imageSrc[N]UnsafeAt.
	return imageSrc0UnsafeAt(texCoord) * (ambient + diffuse)
}

Ebitengine API

Ebitengine API

NewShader

func NewShader(src []byte) (*Shader, error)

NewShader compiles a shader program in the shading language Kage, and returns the result.

NewShader はシェーディング言語 Kage で記述されたシェーダプログラムをコンパイルし、結果を返します。

If the compilation fails, NewShader returns an error.

もしコンパイルエラーが起きたならば、 NewShader はエラーを返します。

(*Image).DrawRectShader

func DrawRectShader(width, height int, shader *Shader, options *DrawRectShaderOptions)

DrawRectShader draws a rectangle with the specified width and height with the specified shader.

DrawRectShader は指定された幅と高さ、指定されたシェーダを使って矩形を描画します。

DrawRectShaderOptions

type DrawRectShaderOptions struct {
    // GeoM is a geometry matrix to draw.
    // The default (zero) value is identity, which draws the rectangle at (0, 0).
    GeoM GeoM

    // CompositeMode is a composite mode to draw.
    // The default (zero) value is regular alpha blending.
    CompositeMode CompositeMode

    // Uniforms is a set of uniform variables for the shader.
    // The keys are the names of the uniform variables.
    // The values must be float or []float.
    // If the uniform variable type is an array, a vector or a matrix,
    // you have to specify linearly flattened values as a slice.
    // For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
    Uniforms map[string]interface{}

    // Images is a set of the source images.
    // All the image must be the same size with the rectangle.
    Images [4]*Image
}
type DrawRectShaderOptions struct {
    // GeoM は描画の幾何行列である。
    // デフォルト (ゼロ) 値は単位行列で、矩形を (0, 0) の位置に描画する。
    GeoM GeoM

    // CompositeMode は描画のコンポジットモードである。
    // デフォルト (ゼロ) 値は通常のアルファブレンディングである。
    CompositeMode CompositeMode

    // Uniforms はシェーダのための Uniform 変数の集合である。
    // キーは Uniform 変数の名前である。
    // 値は float または []float でなければならない。
    // もし Uniform 変数の型が配列、ベクターまたは行列ならば、
    // 線形に展開した値をスライスとして指定しなければならない。
    // たとえば、もし Uniform 変数の型が [4]vec4 ならば、スライスの値の数は 16 になる。
    Uniforms map[string]interface{}

    // Images は描画元画像の集合である。
    // すべての画像の大きさは矩形の大きさと同じでなければならない。
    Images [4]*Image
}

The others

その他

For more primitive rendering, there are also (*Image).DrawTrianglesShader and DrawTrianglesShaderOptions.

よりプリミティブな描画のために、 (*Image).DrawTrianglesShaderDrawTrianglesShaderOptions もあります。

Shading language Kage

シェーディング言語 Kage

Syntax

文法

The syntax is basically same as Go. This is completely same in the syntax level. You can do even gofmt.

基本的に Go と同じです。文法レベルでは完全互換です。 gofmt を実行することさえ出来ます。

Kage doesn't have these Go's features so far.

Kage には現在 Go の以下の機能がありません。

Entry point

エントリーポイント

Kage can define only a fragment shader. The Fragment function with the below signature is the entrypoint.

Kage が現在定義できるのはフラグメントシェーダのみです。以下のシグニチャを持つ Fragment 関数がエントリーポイントになります。

func Fragment(position vec4, texCoord vec2, color vec4) vec4
Name名前TypeDescription説明
positionvec4The destination position in pixels. The 3rd and 4th components are always 0 and 1.描画先の座標。単位はピクセル。第 3、第 4 要素は常にそれぞれ 0、 1。
texCoordvec2The source texture's position in texels.描画元テクスチャの座標。単位はテクセル。
colorvec4Supplemental color information given from vertices. Each component values are in between 0 and 1. This value is meaningful only when DrawTrianglesShader is used.頂点から与えられる補助的な色情報。各要素は 0 から 1 の値。 DrawTrianglesShader 関数使用時にのみ意味を持つ。
(Returning value)(戻り値)vec4The current position's color. Each component values are in between 0 and 1.現在の座標の色。各要素は 0 から 1 の値。

Built-in types

組み込み型

Kage has these built-in types.

Kage は次の組み込み型を持ちます。

float is a floating point number. Unlike Go's float32 and float64, float doesn't have a guarantee for the precision.

float は浮動小数点型です。 Go の float32float64 とは異なり精度の保証がありません。

vec2, vec3, vec4, called vectors, are tuples that has 2, 3, and 4 components respectively. Each component is float. Swizzling operation is available on vector values.

vec2vec3vec4 はベクターと呼ばれ、それぞれ 2、 3、 4 つの値の組を表す型です。各要素は float です。 Swizzling と呼ばれる操作を行えます。

mat2, mat3, mat4 are 2, 3 and 4 dimensional square matrices. Each component is float.

mat2mat3mat4 はそれぞれ 2、 3、 4 次の正方行列を表す型です。各要素は float です。

Kage also supports arrays. Kage doesn't support structs yet.

Kage は他に配列型をサポートします。構造体はまだサポートされていません。

Initializing functions for built-in types

組み込み型の初期化関数

Similar to Go, you can get the type's value by using the type name as a function. Vector types and matrix types are so special that they can take flexible arguments.

Go と似ていますが、型名を関数のように使うことでその型の値を得ることが出来ます。ベクター型と行列型だけ特殊で、引数を柔軟に取りえます。

v1 := vec4(0)              // Returns a vec4 whose components are all 0.
v2 := vec4(1, 2, 3, 4)     // Returns a vec4 whose components are 1, 2, 3 and 4.
v3 := vec3(5, 6, 7)
v4 := vec4(1, v3)          // Returns a vec4 whose components are 1, 5, 6 and 7.

m1 := mat4(2)              // Returns a mat4 whose diagonal components are 2 and the others are 0.
m2 := mat4(v1, v2, v3, v1) // Returns a mat4 whose columns are v1, v2, v3 and v1.

Swizzling

Swizzling

There is a special operation called Swizzling for vector types. You can read and write multiple components at the same time.

ベクター型には Swizzling と呼ばれる特殊な操作があります。要素の一部また全部を一度に読み書きできます。

v1 := vec4(1, 2, 3, 4)
v2 := v1.xyz           // Get vec3(1, 2, 3) and initialize v2 with this.
v2.xyz = v2.xxx        // Get vec3(1, 1, 1), and set it to all the components to v2.
                       // Then, v2 is now (1, 1, 1).

Each component is represent like below. You can mix them in the same group, but you cannot in different groups. For example, .xxyy and .abgr are available, but .xxgg is invalid.

各要素は次のように表されます。同じグループ内ならば自由に組み合わせができますが、違うグループのものを混ぜることはできません。例えば .xxyy.abgr は問題ありませんが、 .xxgg などは無効です。

Uniform variables

Uniform 変数

A uniform variable is a global variable whose value is given externally. This value is the same regardless of the position of the pixel.

Uniform 変数はシェーダの外部から値が与えられるグローバル変数です。この値はピクセルの位置に依らず一定となります。

In Kage, uniform variables are global variables that start with upper cases (i.e., exported variables).

Kage では Uniform 変数は大文字から始まる (export される) グローバル変数になります。

You cannot assign a value into a uniform variable in Kage.

Uniform 変数は Kage の中では代入することができません。

You cannot define other global variables than uniform variables in Kage.

Kage では Uniform 変数以外のグローバル変数を定義することができません。

Built-in functions (Go)

組み込み関数 (Go)

Function関数Description説明
cap(x T) intT is an array type. Returns the length of the array. (v2.1.0)T は配列型。配列の長さを返す。 (v2.1.0)
len(x T) intT is an array type. Returns the length of the array.T は配列型。配列の長さを返す。

Built-in functions (Control)

組み込み関数 (制御)

Function関数Description説明
discard()Stop outputting the current fragment. (v2.4.0)現在のピクセルの出力を中断する (v2.4.0)

Built-in functions (mathematics)

組み込み関数 (数学)

Most of the built-in functions are generic. T represents float, vec2, vec3 or vec4 unless otherwise noted. When the type is a vector, the function is applied for each component.

多くの組み込み関数はジェネリックです。断りがない場合、 Tfloatvec2vec3vec4 のいずれかを表します。ベクター型の場合、各要素に関数が適用されます。

Function関数Description説明
sin(x T) TReturns \sin{x}\sin{x} を返す。
cos(x T) TReturns \cos{x}\cos{x} を返す。
tan(x T) TReturns \tan{x}\tan{x} を返す。
asin(x T) TReturns \arcsin{x}\arcsin{x} を返す。
acos(x T) TReturns \arccos{x}\arccos{x} を返す。
atan(y_over_x T) TReturns \arctan(\mathit{y\_over\_x})\arctan(\mathit{y\_over\_x}) を返す。
atan2(y, x T) TReturns \arctan(y/x)\arctan(y/x) を返す。
pow(x, y T) TReturns x^yx^y を返す。
exp(x T) TReturns e^{x}e^{x} を返す。
log(x T) TReturns \log_e{x}\log_e{x} を返す。
exp2(x T) TReturns 2^{x}2^{x} を返す。
log2(x T) TReturns \log_2{x}\log_2{x} を返す。
sqrt(x T) TReturns \sqrt{x}\sqrt{x} を返す。
inversesqrt(x T) TReturns 1/\sqrt{x}1/\sqrt{x} を返す。
abs(x T) TReturns x if x \ge 0, or -x otherwisex \geq 0 ならば x を、それ以外の場合は -x を返す。
sign(x T) TReturns 1 if x \gt 0, 0 if x = 0, or -1 otherwisex \gt 0 ならば 1 を、x = 0 ならば 0 を、それ以外の場合は -1 を返す。
floor(x T) TReturns a value equal to the nearest integer that is less than or equal to xx 以下の最も近い整数と同じ値を返す。
ceil(x T) TReturns a value equal to the nearest integer that is greater than or equal to xx 以上の最も近い整数と同じ値を返す。
fract(x T) TReturns x - \mathrm{floor}(x)x - \mathrm{floor}(x) を返す。
mod(x, y T) TReturns x - y \cdot \mathrm{floor}(x/y)x - y \cdot \mathrm{floor}(x/y) を返す。
min(x, y T) TReturns x if x \lt y, or y otherwisex \lt y ならば x を、それ以外の場合は y を返す。
max(x, y T) TReturns y if x \lt y, or x otherwisex \lt y ならば y を、それ以外の場合は x を返す。
clamp(x, min_value, max_value T) TReturns \min(\max(x, \mathit{min\_value}), \mathit{max\_value})\min(\max(x, \mathit{min\_value}), \mathit{max\_value}) を返す。
mix(x, y, a T) TReturns x \cdot (1 - a) + y \cdot ax \cdot (1 - a) + y \cdot a を返す。
step(edge, x T) TReturns 0 if x \lt \mathit{edge}, or 1 otherwisex \lt \mathit{edge} ならば 0 を、それ以外の場合は 1 を返す。
smoothstep(edge0, edge1, x T) TReturns 0 if x \le \mathit{edge0}, 1 if x \ge \mathit{edge1}, or performs smooth Hermite interpolation between 0 and 1 otherwisex \le \mathit{edge0} ならば 0 を、 x \ge \mathit{edge1} ならば 1 を、それ以外の場合はエルミート補間を 0 から 1 の値で行った値を返す。
length(x T) floatReturns \sqrt{x[0]^2 + x[1]^2 + \cdots}\sqrt{x[0]^2 + x[1]^2 + \cdots} を返す。
distance(p0, p1 T) floatReturns \mathrm{length}(p0 - p1)\mathrm{length}(p0 - p1) を返す。
dot(x, y T) floatReturns x[0] \cdot y[0] + x[1] \cdot y[1] + \cdotsx[0] \cdot y[0] + x[1] \cdot y[1] + \cdots を返す。
cross(x, y vec3) vec3Returns x \times y (cross product)x \times y (クロス積) を返す。
normalize(x T) TReturns a vector in the same direction as x but with a length of 1x と同じ向きを持つが長さが 1 のベクターを返す。
faceforward(n, i, nref T) TReturns n if \mathrm{dot}(\mathit{nref}, i) \lt 0, or -n otherwise\mathrm{dot}(\mathit{nref}, i) \lt 0 ならば n を、それ以外の場合は -n を返す。
reflect(i, n T) TReturns i - 2 \cdot \mathrm{dot}(n, i) \cdot ni - 2 \cdot \mathrm{dot}(n, i) \cdot n を返す。
refract(i, n T, eta float) T(v2.4.0)
transpose(m T) TT is a matrix type. Returns a matrix that is the transpose of xT は行列型。x の転置行列を返す。
dfdx(p T) T
dfdy(p T) T
fwidth(p T) T

Built-in functions (images)

組み込み関数 (画像)

Function関数Description説明
imageSrcNAt(pos vec2) vec4Returns the color value as vec4 at the given position pos in texels of the source image N. N is 0 to 3.描画画像 N の、与えられたテクセル単位の位置 pos の色を vec4 で返す。 N は 0 から 3 の値を取る。
imageSrcNUnsafeAt(pos vec2) vec4Returns the color value as vec4 at the given position pos in texels of the source image N. N is 0 to 3. The difference from the safe version (imageSrcNAt) is the returning value when the position is out of the bounds. The safe version returns vec4(0) in this case, while the unsafe version's returning value is undefined. The unsafe version is faster. If you are sure that the position is in the bounds, you can use the unsafe version for performance.描画画像 N の、与えられたテクセル単位の位置 pos の色を vec4 で返す。 N は 0 から 3 の値を取る。セーフバージョン (imageSrcNAt) との違いは、画像の境界外の位置を指定したときの戻り値である。セーフバージョンはこの場合 vec4(0) を返すが、アンセーフバージョンは未定義である。アンセーフバージョンは高速に動作する。もし位置が画像の境界内にあることが確実ならば、パフォーマンスのためにアンセーフバージョンを使ってもよい。
imageSrcTextureSize() vec2Returns the source image's texture size in pixels描画元画像のテクスチャの大きさをピクセル単位で返す。
imageDstTextureSize() vec2Returns the destination image's texture size in pixels描画先画像のテクスチャの大きさをピクセル単位で返す。
imageSrcRegionOnTexture() (vec2, vec2)Returns the source image's origin position and the size on the texture in texels描画元画像の、テクスチャ上の原点位置と大きさをテクセル単位で返す。
imageDstRegionOnTexture() (vec2, vec2)Returns the destination image's origin position and the size on the texture in texels (v2.1.0)描画先画像の、テクスチャ上の原点位置と大きさをテクセル単位で返す。 (v2.1.0)

Textures and images

テクスチャと画像

Ebitengine's image (ebiten.Image) is actually a part of an internal texture. Then, position calculations in shaders are a little complex.

Ebitengine の画像 (ebiten.Image) は実際には内部のテクスチャ上の一部です。そのためシェーダ上での座標計算が少々複雑になります。

A pixel is a unit for one color dot. On the other hand, texel is a unit covering the whole area with values in between 0 and 1. The meaning of texels depends on a texture, then you cannot mix texels with different textures.

ピクセルは 1 画素を 1 とする単位です。一方テクセルは 0 から 1 の範囲が全体を表す単位です。テクセルの意味はテクスチャに依存するため、異なるテクスチャのテクセルを混ぜることは出来ません。

To convert pixels and texels each other, you can use these formulas.

ピクセルとテクセルを相互に変換するには次の式を使います。

\begin{aligned} (\text{texels}) &= \frac{(\text{pixels})}{(\text{the texture's size in pixels})} \\ (\text{pixels}) &= (\text{texels}) \cdot (\text{the texture's size in pixels}) \\ \end{aligned}

Editor Plugins

エディタのプラグイン

There are plugins for some editors by volunteers to edit Kage programs.

Kage プログラムを編集するための、有志によるエディタプラグインがあります。