シェーダーの基本
シェーダーの動きを確認する
まずは普通に画像を表示させてみます。
function love.load()
img = love.graphics.newImage("img/sample_bg.jpg")
end
function love.draw()
love.graphics.draw(img, 0, 0)
end
次に、シェーダーを適用して画像を表示させてみましょう。
function love.load()
shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
vec4 pixel = Texel(texture, texture_coords);
pixel.g = 0;
return pixel;
}
]]
img = love.graphics.newImage("img/sample_bg.jpg")
end
function love.draw()
love.graphics.setShader(shader)
love.graphics.draw(img, 0, 0)
love.graphics.setShader()
end
表示が先程とは異なっています。全体的に赤っぽくなりました。これはシェーダーで緑色(G)の成分を0にしたためです。love.drawではシェーダーの適用は行っていますが、love.graphics.setColorなどで画像の描画をコントロールしていません。
大まかな処理の説明
3行目
effect関数の中にシェーダーの処理を書いていきます。ここからはLuaではなくGLSLで書いていきます。
4行目
現在のピクセルの情報を取得します。vec4型のpixelにはr, g, b, aの情報が含まれています。
5行目
pixelのrを0に変更します。これでこのピクセルから赤の成分がなくなります。
6行目
ピクセルの情報を返します。
Love2Dからシェーダーに値を渡す
上記のシェーダーは赤色の成分を0にするという処理をGLSLで固定してコーディングされています。この「0」の部分をプログラムから変更できるようにしてみます。
シェーダーはexternを使うことで外部から値を受け取ることができます。また、Love2DではShaderのsend使うことでシェーダーに値を渡すことができます。
function love.load()
shader = love.graphics.newShader[[
extern number red;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
vec4 pixel = Texel(texture, texture_coords);
pixel.r = red;
return pixel;
}
]]
img = love.graphics.newImage("img/sample_bg.jpg")
red = 0
dir = 1
end
function love.draw()
shader:send("red", red)
love.graphics.setShader(shader)
love.graphics.draw(img, 0, 0)
love.graphics.setShader()
end
function love.update(dt)
red = red + (dir * dt * 0.5)
if red >= 1 then
dir = -1
elseif red <= 0 then
dir = 1
end
end
動的にredの値を変えてシェーダーに渡しています。画面が赤っぽくなったり青緑っぽくなったりします。