love.graphics.newShader (日本語)

LÖVE 0.9.0 から使用可能
love.graphics.newPixelEffect から名称変更。


O.png この関数は love.update または love.draw などから繰り返し呼び出すと動作が重くなることがあります。もし、特定の資源を何度も使う必要がある場合は、一括で作成と格納を行うことで効率的に再利用できます!  


ハードウェア加速化による頂点またはピクセル・エフェクトで Shader オブジェクトを新規作成します。 Shader は頂点シェーダーやピクセル・シェーダーのコードの一方あるいは両方を有しています。

Shader は描画時にグラフィックス・カードで実行される小型のプログラムです。頂点シェーダーは各頂点に対して一括で実行されます (例えば Image の頂点は4つです。 - 角ごとに1つずつ。 Mesh では、それ以上あります)。ピクセル・シェーダーは描画されたオブジェクトが関係する画面上の各ピクセルに対して一括で実行します。全てのオブジェクトの頂点を頂点シェーダーで処理した後にピクセル・シェーダーのコードを実行します。

関数

概要

shader = love.graphics.newShader( code )

引数

string code
頂点シェーダー、あるいはピクセル・シェーダーで用いるコード (テキスト、またはファイル名)。

返値

Shader shader
描画操作で用いるShader オブジェクト。

関数

概要

shader = love.graphics.newShader( pixelcode, vertexcode )

引数

string pixelcode
ピクセル・シェーダーで用いるコード (テキスト、またはファイル名)。
string vertexcode
頂点シェーダーで用いるコード (テキスト、またはファイル名)。

返値

Shader shader
描画操作で用いるShader オブジェクト。

注釈

引数 pixelcode と vertexcode は任意順です。

シェーダー言語

シェーダーのプログラミングは Lua ではなく、シェーダー専用言語である GLSL を使用します。ただし、便宜上の都合でエイリアスとエントリポイントは少し異なります。 GLSL のシンタックスは C と非常によく似ています。 LÖVE で用意されているエイリアスの使用は一切強制していませんが、 GLSL 3 では texture2D は動作しません。ですが、 Texel は全 GLSL のバージョンで動作します。よって、 texture2D ではなく Texel の使用を推奨します。

GLSL LÖVE シェーダー言語
sampler2D Image
sampler2DArray ArrayImage
samplerCube CubeImage
sampler3D VolumeImage
texture2D(tex, uv) (GLSL 1 の場合) Texel(tex, uv)
texture(tex, uv) (GLSL 3 の場合) Texel(tex, uv)
float number (廃止予定)
uniform extern (廃止予定)


使用する GLSL のバージョンはシェーダーのソースコードファイルの先頭行に #pragma language glsl3 を記述したかどうか、あるいは LÖVE をデスクトップ、またはモバイル機器のどちらで実行しているかどうかによります:

LÖVE シェーダー言語 デスクトップ版 GLSL バージョン モバイル版 GLSL バージョン
glsl1 (デフォルト) GLSL 1.20 GLSL ES 1.00
glsl3 GLSL 3.30 GLSL ES 3.00

一部の旧式システムで GLSL 3 は非対応です。起動時に love.graphics.getSupported で対応状況を確認してください。


頂点シェーダーのコードには最低でも一本の関数があります。名前は position です。関数は画面空間へ描画されたオブジェクトから変換した頂点の位置を生成します。

ピクセルシェーダーのコードには最低でも一本の関数があります。名前は effect です。関数は描画されたオブジェクトが接触する各ピクセルに対して画面上へ混合処理をした色を生成します。

デフォルトで LÖVE には実用的なシェーダー変数 が用意されています。さらに、 LÖVE は色値を与えるために VideoTexel(uv) 関数により描画を行って現在の位置に Video を描画します。Video は複数のテクスチャにより、 YUV データとして描画とシェーダーへの変換が行われるため、 Texel (テクセル) 関数は使用できません。

ピクセルシェーダー関数

オブジェクト描画時にピクセルシェーダ関数 effect は何百~何千回も呼び出されます: 画面において各ピクセルがオブジェクトが接触するとき。その場合、ピクセルシェーダは頂点シェーダーの後に実行されます。

概要

vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )

引数

vec4 color
love.graphics.setColor にて設定する描画色、または頂点ごとの Mesh の色。
Image tex
テクスチャとして描画される画像または Canvas です。
vec2 texture_coords
ピクセルデータ取得先のテクスチャ内の位置です。左上角 (0, 0) を起点とするテクスチャ座標のとき、通常は (0, 0) から (1, 1) までの範囲を正規化します。
vec2 screen_coords
画面上のピクセルの座標。ピクセルの座標は正規化されません (テクスチャの座標とは異なります)。 (0.5, 0.5) は画面左上 (LÖVE version 0.10.0 以前では画面左下) を表します。

返値

vec4 output_color
ピクセルの色。

注釈

ピクセルシェーダー未使用時、 LÖVE 内部にある下記のデフォルト・コードを使用します:

vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords)
{
    vec4 texturecolor = Texel(tex, texture_coords);
    return texturecolor * color;
}

Video では、

vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords)
{
    vec4 texturecolor = VideoTexel(texture_coords);
    return texturecolor * color;
}

複数の Canvas を同時表示するときは (複数の Canvas を love.graphics.setCanvas への引数として渡したとき)、各 Canvas ごとに個別の色を出力するために vec4 effect ではなく void effect (引数なし!) 関数を使用します。このために下記のプロトタイプ (原型) があります:

void effect()
{
    // love_Canvases は書き込み可能な vec4 color の配列です。各インデックスは Canvas に対応しています.
    // IMPORTANT: 重要: 使用中の全ての Canvas へ値を代入しなければ、不具合が発生します。
    love_Canvases[0] = color;
    love_Canvases[1] = color + vec4(0.5);
    // など。
}

Canvas が一枚のバージョン (vec4 effect) に渡された引数を取得したいならば、組み込みシェーダー変数を参照してください。

colorVaryingColor であり、 texture_coordsVaryingTexCoord です。そして screen_coordslove_PixelCoord です。

描画操作で用いられたテクスチャにアクセスしたいならば、 MainTex の名前で uniform テクスチャを定義するか、または Shader:send へ送信します。

頂点シェーダー関数

概要

vec4 position( mat4 transform_projection, vec4 vertex_position )

引数

mat4 transform_projection
変換行列は love.graphics.translate および関連関数により影響を受けて正投影の行列と組み合わされます。
vec4 vertex_position
現在の頂点における生の未変換位置。

返値

vec4 output_pos
The final transformed position of the current vertex.

注釈

頂点シェーダー未使用時、 LÖVE はデフォルト・コードを使用します:

vec4 position(mat4 transform_projection, vec4 vertex_position)
{
    // 行列乗算時の演算順序は重要です。
    return transform_projection * vertex_position;
}

注釈

頂点シェーダーのコードは、画面に描画される全ての頂点 (例えば love.graphics.rectangle では頂点を4つ生成します) と元座標から画面空間への頂点座標の変換処理、さらにピクセル・シェーダーへ頂点毎の配色とテクスチャ座標の値などの情報送信時に実行されます。

ピクセル・シェーダー (別名はフラグメント・シェーダー) のコードは描画されたオブジェクトに接触している画面上の全ピクセルに対して実行します。大抵は画像から読み込んで、画面上の対象ピクセルと混合する色を生成するのに使用します。

varying キーワードは頂点シェーダー、および頂点間の補間、さらにピクセル・シェーダーへ渡す値を設定するために使用します。

頂点シェーダーのコードを #ifdef VERTEX .. #endif で、ピクセル・シェーダーのコードは #ifdef PIXEL .. #endif のブロックで囲むことで、頂点とピクセル・シェーダーのコードをファイル、または文字列内で併用できます。

組み込み変数

LÖVE ではピクセル・シェーダー、および頂点シェーダーで使える組み込み関数を用意しています。こちらに全リストがあります: シェーダー変数

用例

頂点とピクセル・シェーダーのコードでシェーダーを作成します (シェーダー未設定時に動作)。

local pixelcode = [[
    vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
    {
        vec4 texcolor = Texel(tex, texture_coords);
        return texcolor * color;
    }
]]
 
local vertexcode = [[
    vec4 position( mat4 transform_projection, vec4 vertex_position )
    {
        return transform_projection * vertex_position;
    }
]]
 
shader = love.graphics.newShader(pixelcode, vertexcode)
 
function love.draw()
    love.graphics.setShader(shader)
    -- 描画処理
    love.graphics.setShader()
    -- 描画処理の続き
end

varying キーワードでピクセルシェーダー内の事前変換した頂点位置へアクセスします。

頂点シェーダーのコード

varying vec4 vpos;
 
vec4 position( mat4 transform_projection, vec4 vertex_position )
{
    vpos = vertex_position;
    return transform_projection * vertex_position;
}

ピクセルシェーダーのコード

varying vec4 vpos;
 
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
    texture_coords += vec2(cos(vpos.x), sin(vpos.y));
    vec4 texcolor = Texel(tex, texture_coords);
    return texcolor * color;
}

#ifdef で上述の用例に記述されている文字列、またはファイルを一つにまとめます。

varying vec4 vpos;
 
#ifdef VERTEX
vec4 position( mat4 transform_projection, vec4 vertex_position )
{
    vpos = vertex_position;
    return transform_projection * vertex_position;
}
#endif
 
#ifdef PIXEL
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
    texture_coords += vec2(cos(vpos.x), sin(vpos.y));
    vec4 texcolor = Texel(tex, texture_coords);
    return texcolor * color;
}
#endif

関連



そのほかの言語