まっぷたつシェーダ
マウスでドラッグするとその位置、方向の直線で画像を真っ二つにするシェーダ。
どうやっているのかというと、マウスでドラッグした範囲をベクトルとしてシェーダに渡し、ドラッグ開始位置と描画する点のベクトルとの外積を計算して線の右か左かを判別して描画するしないを決めている。言い換えればベクトルを使ったマスク処理だ。
これをうまく使えばトランジションにもできるんじゃないかな。そのへんの思考は変数名にも表れているけど、そこまでは作りこんでない。
画像はきまぐれアフター様
http://gakaiblog.at.webry.info/
require 'dxruby' hlsl = <<EOS float3 p1, p2; texture tex0; sampler Samp0 = sampler_state { Texture =<tex0>; }; float4 PS1(float2 input : TEXCOORD0) : COLOR0 { clip( cross( float3(p2.x - p1.x, p2.y - p1.y, 0), float3(input.x - p1.x, input.y - p1.y, 0) ).z ); return tex2D( Samp0, input ); } float4 PS2(float2 input : TEXCOORD0) : COLOR0 { clip( cross( float3(p1.x - p2.x, p1.y - p2.y, 0), float3(input.x - p1.x, input.y - p1.y, 0) ).z ); return tex2D( Samp0, input ); } technique Zan1 { pass P0 { PixelShader = compile ps_2_0 PS1(); } } technique Zan2 { pass P0 { PixelShader = compile ps_2_0 PS2(); } } EOS Window.width, Window.height = 800, 600 core = Shader::Core.new(hlsl,{:p1=>:float, :p2=>:float}) shader1 = Shader.new(core, "Zan1") shader2 = Shader.new(core, "Zan2") image = Image.load("bgimage/BG42a.jpg") image1 = image2 = nil rt = RenderTarget.new(image.width, image.height) point = nil transition_flg = false x1 = y1 = x2 = y2 = 0 angle = 0 alpha = 255 Window.loop do if !transition_flg if Input.mouse_push?(M_LBUTTON) point = [Input.mouse_pos_x, Input.mouse_pos_y] end if point if Input.mouse_down?(M_LBUTTON) Window.draw_line(point[0], point[1], Input.mouse_pos_x, Input.mouse_pos_y, C_WHITE, 1) else transition_flg = true shader1.p1 = shader2.p1 = [point[0].quo(image.width), point[1].quo(image.height),0] shader1.p2 = shader2.p2 = [Input.mouse_pos_x.quo(image.width), Input.mouse_pos_y.quo(image.height),0] angle = Math.atan2( Input.mouse_pos_y - point[1], Input.mouse_pos_x - point[0] ) image1 = rt.draw_shader(0, 0, image, shader1).update.to_image image2 = rt.draw_shader(0, 0, image, shader2).update.to_image alpha = 255 point = nil x1 = y1 = x2 = y2 = 0 end end Window.draw(0, 0, image) else x1 -= Math.cos(angle) * 5 y1 -= Math.sin(angle) * 5 x2 += Math.cos(angle) * 5 y2 += Math.sin(angle) * 5 alpha -= 3 Window.draw_alpha(x1, y1, image1, alpha) Window.draw_alpha(x2, y2, image2, alpha) transition_flg = false if alpha < 10 end end