DXRuby1.1でRGSSのトランジション

Window.drawShaderの引数にImageオブジェクト(もしくはRenderTargetオブジェクト)を複数指定できるようにした。
これを使うとシェーダに描画する画像と加工する材料を渡すことができる。
RGSSのトランジションも実現できそうだったので作ってみた。

RGSSのデフォルトはクロスフェード
アルゴリズムはFreeRGSSで作ったものとほぼ同じだ。

#!ruby -Ks
require 'dxruby'

map = [[0, 0, 0, 0, 0, 0, 0, 0, 29, 11, 11, 30, 34, 66, 67, 67],
       [0, 0, 0, 24, 25, 26, 0, 0, 29, 11, 11, 39, 40, 6, 34, 34],
       [0, 0, 24, 17, 31, 35, 0, 0, 12, 20, 11, 11, 11, 39, 40, 40],
       [0, 24, 17, 34, 7, 44, 0, 28, 28, 29, 11, 11, 11, 11, 11, 11],
       [0, 33, 31, 34, 35, 0, 28, 3, 37, 38, 11, 11, 11, 18, 19, 19],
       [0, 42, 43, 43, 44, 28, 3, 38, 11, 11, 11, 18, 19, 13, 28, 28],
       [0, 0, 0, 0, 3, 37, 38, 11, 11, 18, 19, 13, 28, 28, 28, 0],
       [0, 0, 0, 3, 38, 11, 11, 11, 18, 13, 28, 28, 51, 52, 52, 52],
       [0, 0, 3, 38, 11, 11, 18, 19, 13, 51, 52, 52, 86, 58, 61, 76],
       [28, 0, 29, 11, 11, 18, 13, 28, 51, 86, 58, 58, 61, 61, 58, 62],
       [0, 28, 29, 11, 18, 13, 28, 0, 60, 58, 61, 61, 61, 61, 76, 71],
       [0, 28, 29, 11, 27, 28, 28, 51, 86, 61, 61, 58, 76, 70, 71, 0],
       [0, 0, 29, 11, 36, 4, 28, 60, 58, 61, 58, 76, 71, 0, 1, 2],
       [0, 28, 29, 11, 11, 36, 4, 69, 70, 70, 70, 71, 0, 1, 2, 0],
       [0, 0, 12, 20, 11, 11, 27, 0, 1, 0, 1, 1, 1, 2, 2, 0],
       [0, 0, 28, 12, 20, 11, 27, 0, 0, 0, 2, 2, 0, 2, 2, 0],
       [0, 0, 0, 2, 29, 11, 27, 1, 2, 2, 2, 0, 0, 2, 2, 2],
       [0, 0, 0, 2, 29, 11, 27, 1, 0, 1, 1, 2, 2, 0, 0, 2],
       [0, 0, 0, 0, 29, 11, 27, 1, 0, 2, 2, 2, 1, 1, 2, 2],
       [0, 45, 47, 2, 29, 11, 36, 4, 1, 2, 2, 0, 0, 2, 2, 0],
       [45, 82, 56, 0, 29, 11, 11, 36, 4, 1, 2, 2, 2, 2, 0, 0],
       [54, 0, 56, 0, 12, 20, 11, 11, 36, 37, 4, 0, 2, 2, 2, 2],
       [54, 55, 81, 46, 47, 12, 20, 11, 11, 11, 36, 4, 1, 1, 1, 2],
       [54, 55, 0, 0, 56, 0, 12, 19, 20, 11, 11, 36, 37, 4, 1, 1],
       [54, 0, 55, 55, 56, 0, 0, 0, 12, 20, 11, 11, 11, 36, 37, 37],
       [63, 73, 55, 55, 56, 0, 0, 2, 2, 29, 11, 11, 11, 11, 11, 11],
       [0, 54, 0, 55, 81, 47, 0, 2, 3, 38, 11, 11, 11, 11, 11, 11],
       [0, 54, 0, 0, 55, 56, 2, 0, 29, 11, 11, 11, 21, 22, 22, 22],
       [0, 63, 64, 64, 64, 65, 0, 0, 29, 11, 11, 21, 15, 48, 49, 49],
       [0, 0, 0, 0, 0, 0, 0, 0, 29, 11, 11, 30, 34, 57, 34, 34],
      ]

require 'dxruby'

hlsl = <<EOS
float g_min;
float g_max;
texture Tex0;
texture Tex1;
sampler Samp0 = sampler_state
{
 Texture =<Tex0>;
};
sampler Samp1 = sampler_state
{
 Texture =<Tex1>;
};

struct PixelIn
{
  float2 UV : TEXCOORD0;
};
struct PixelOut
{
  float4 Color : COLOR0;
};

PixelOut PS(PixelIn input)
{
  PixelOut output;
  output.Color = tex2D( Samp0, input.UV );
  output.Color.a = smoothstep(g_min, g_max, tex2D( Samp1, input.UV ).r );

  return output;
}

technique TShader
{
 pass P0
 {
  PixelShader = compile ps_2_0 PS();
 }
}
EOS

shader = Shader.new(hlsl, "TShader")

rt = RenderTarget.new(640, 480)
DXRUBY_RENDERTARGET.push(rt)
transition = Image.new(640, 480, [255,255,255])

image = Image.loadToArray("image/maptile.png", 9, 10)

min = 0.0
max = 1.0
Window.loop do
  min += 0.01
  max += 0.01
  Window.drawTile(150, 16, map, image, 0, 0, 12, 14)
  Window.update(rt)
  Window.drawTile(150, 16, map, image, 0, 160, 12, 14)
  shader.setValue("g_min", min)
  shader.setValue("g_max", max)
  Window.drawShader(0, 0, [rt, transition], shader)
end

また、こちらのブログからトランジション素材を頂くと、このような描画もできる。
http://myomua.blog50.fc2.com/blog-entry-36.html

これは上のソースにちょっと手を加えて動かした途中の画面だ。
transitionに画像を読み込み、minを-1.0、maxを0.0にして見やすいようにdrawTileを片方消した。
このぶんだとまったく同じ動作を再現するメソッドとかも作れそうだ。