シェーダーの基本

シェーダーの動きを確認する

まずは普通に画像を表示させてみます。

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ではShadersend使うことでシェーダーに値を渡すことができます。

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
Love2Dからシェーダーに値を渡す

動的にredの値を変えてシェーダーに渡しています。画面が赤っぽくなったり青緑っぽくなったりします。