#!ruby -Ks # -*- mode: ruby; encoding: sjis -*- # Last updated: <2014/06/07 15:38:11 +0900> # # Shaderを使ってラスタスクロールのテスト # 天井、壁、床をラスタースクロールさせるっぽい感じの処理 # 画像を読み込んで表示する版 require 'dxruby' class BgRasterScroll3 attr_accessor :gridsize attr_accessor :imgs attr_accessor :shaders # コンストラクタ # # @param [Number] gridsize 1マス分のドットサイズ # @param [Array] imgs 天井、壁、床のImageオブジェクトを配列に入れて渡す # def initialize(gridsize, imgs) hlsl = <; // こっちだと画面がチラチラする (´・ω・`) // MinFilter = LINEAR; // MagFilter = LINEAR; // MipFilter = LINEAR; // こっちならチラチラしない MinFilter = POINT; MagFilter = POINT; MipFilter = NONE; AddressU = WRAP; AddressV = WRAP; }; struct PixelIn { float2 UV : TEXCOORD0; }; struct PixelOut { float4 Color : COLOR0; }; PixelOut PS1(PixelIn input) { PixelOut output; input.UV.x = input.UV.x + ((d + (d * input.UV.y * dd)) / size.x); output.Color = tex2D( Samp0, input.UV ); return output; } PixelOut PS2(PixelIn input) { PixelOut output; input.UV.x = input.UV.x + ((d + (d * (1.0 - input.UV.y) * dd)) / size.x); output.Color = tex2D( Samp0, input.UV ); return output; } PixelOut PS3(PixelIn input) { PixelOut output; input.UV.x = input.UV.x + d / size.x; output.Color = tex2D( Samp0, input.UV ); return output; } // float4 PS(float2 input : TEXCOORD0) : COLOR0 // { // float4 output; // // input.x -= ((d / size.x) + ((d / size.x) * input.y * dd)); // input.x = input.x - ((d + (d * input.y * dd)) / size.x); // output = tex2D( Samp0, input); // return output; // } technique FloorScroll { pass P0 { PixelShader = compile ps_2_0 PS1(); } } technique CeilingScroll { pass P0 { PixelShader = compile ps_2_0 PS2(); } } technique WallScroll { pass P0 { PixelShader = compile ps_2_0 PS3(); } } EOS core = Shader::Core.new(hlsl, {:size=>:float, :d=>:float, :dd=>:float}) self.shaders = [] self.imgs = [] self.gridsize = gridsize shader_names = [ ["CeilingScroll", 1.0], ["WallScroll", 1.0], ["FloorScroll", 1.0] ] shader_names.each_with_index do |dt, i| sname, dd = dt img = imgs[i] self.imgs.push(img) shr = Shader.new(core, sname) shr.size = [img.width, img.height] shr.d = 0 # スクロール量 shr.dd = dd # 上辺と下辺で、x方向に何ドットずれるか self.shaders.push(shr) end end # スクロール量を更新 # # @param [Number] d スクロール量 # def update(d) d = (d % self.gridsize) self.shaders.each do |shr| shr.d = d end end # 描画 # # @param [Number] bx 描画位置 x # @param [Number] by 描画位置 y # def draw(bx, by) x, y = bx - self.gridsize * 2, by 3.times do |i| Window.drawShader(x, y, self.imgs[i], self.shaders[i]) y += self.imgs[i].height end end end if __FILE__ == $0 # ---------------------------------------- # 動作確認 imgs = [] # 画像ファイル名一覧に従って画像ロード [ "bg_ras_a.png", # 天井 "bg_ras_b.png", # 壁 "bg_ras_c.png" # 床 ].each {|fn| imgs.push(Image.load(fn)) } # ラスタースクロール用オブジェクトを発生 ras = BgRasterScroll3.new(64, imgs) # 柱スプライトを発生 pole = Image.load("pole.png") sprs = [] 4.times do |i| spr = Sprite.new(i * (96 * 2) + 72, 480 - (160 /2) - 128 + 8, pole) sprs.push(spr) end font = Font.new(14) x = 0 Window.loop do break if Input.keyPush?(K_ESCAPE) # マウス位置に応じてスクロール量を変化 dx = ((Window.width / 2) - Input.mousePosX).to_f / Window.width * 32 x -= dx ras.update(x) # スクロール量を指定 ras.draw(0, 0) # 描画 # 柱を描画 tdx = dx + dx * 0.5 sprs.each do |spr| spr.x += tdx spr.x += Window.width + 128 if dx < 0 and spr.x + 64 < 0 spr.x -= (Window.width + 128) if dx > 0 and spr.x > Window.width end Sprite.update(sprs) Sprite.draw(sprs) Window.drawFont(4, 4, "dx = #{dx} , x = #{x}", font) end end