Shaderでライフゲーム
自分の実力ではないけど。
http://ja.doukaku.org/comment/5512/
使えるようにちょっとだけ変えた。
頂点シェーダを殺したのと、テクスチャ変数名の変更。
なんかおかしかったのを直したので差し替えといた。DXRuby1.1.9とruby1.8.7で確認。
このサイズのto_imageはかなり遅い。GetRenderTargetDataしてから更にMANAGEDで確保したテクスチャにコピーしているからだ。
新機能のパフォーマンスチューニングは必須だと思うが、それはまだ先。
require 'dxruby' hlsl = <<EOS // Cから変更できる変数の宣言。問題サイズに対応。座標計算に使う。 float F_X; float F_Y; // テクスチャの宣言 texture Tex0; // テクスチャの定義 sampler Samp1 = sampler_state { Texture = <Tex0>; MinFilter = POINT; MagFilter = POINT; MipFilter = NONE; AddressU = WRAP; AddressV = WRAP; }; // 頂点シェーダの出力形式 struct VS_OUTPUT { float4 Pos : POSITION; float2 Tex : TEXCOORD; }; // 頂点シェーダ(未使用) VS_OUTPUT VS_DEFAULT ( float4 Pos : POSITION, float2 Tex : TEXCOORD ){ VS_OUTPUT Out = (VS_OUTPUT)0; return Out; } // ピクセルシェーダ float4 PS_TEST ( VS_OUTPUT In ) : COLOR { float4 Color = {0.0f, 0.0f, 0.0f, 0.0f}; float2 TexA = {0.0f, 0.0f}; float4 Color0 = {0.0f, 0.0f, 0.0f, 0.0f}; int num; int sum; int ret; TexA = In.Tex; Color += tex2D( Samp1, TexA+float2(-F_X, -F_Y) ); Color += tex2D( Samp1, TexA+float2(0.0f, -F_Y) ); Color += tex2D( Samp1, TexA+float2( F_X, -F_Y) ); Color += tex2D( Samp1, TexA+float2(-F_X, 0.0f) ); Color0 = tex2D( Samp1, TexA+float2( 0.0f, 0.0f) ); Color += tex2D( Samp1, TexA+float2( F_X, 0.0f) ); Color += tex2D( Samp1, TexA+float2(-F_X, F_Y) ); Color += tex2D( Samp1, TexA+float2(0.0f, F_Y) ); Color += tex2D( Samp1, TexA+float2( F_X, F_Y) ); num = round(Color0.r); sum = round(Color.r); ret = (sum==3) + (sum==2) * num; /* // 上の行は以下の条件式をまとめたもの。 // 分岐をなくしたので多くのGPUで実行可能なはず。 if(num==0) { ret = sum==3; }else{ ret = ((sum==2)+(sum==3)) != 0; } */ return float4((float)(ret*0xff), 0.0f, 0.0f, 1.0f); // RGBA } // テクニック technique RenderScene { pass P0 { // VertexShader = compile vs_2_0 VS_DEFAULT(); PixelShader = compile ps_2_0 PS_TEST(); } } EOS shader = Shader.new(hlsl, "RenderScene") x = 1.0/640 y = 1.0/480 shader.setValue("F_X", x) shader.setValue("F_Y", y) rt = RenderTarget.new(640, 480) DXRUBY_RENDERTARGET.push rt image = Image.new(640, 480) for i in 0..99999 image[rand(640), rand(480)] = [255,0,0] end font = Font.new(32) Window.loop do Window.drawShader(0, 0, image, shader) Window.update(rt) image = rt.to_image Window.draw(0, 0, image) Window.drawFont(0,40,Window.fps.to_s, font) Window.drawFont(0,0,Window.getLoad.to_i.to_s, font) GC.start end