HLSLでオセロ(うごきません)
ピクセルシェーダはピクセルを打つ点を出力するから、他の点をチェックしてひっくり返る条件を満たしていれば色を変えることで、オセロの判定を作ることができるかもしれない。
と思ったので試してみた。
が、なぜかコンパイルが終わらず、動かせられなかった。
whileはHLSLの文法では存在するが、うちのノートではコンパイルエラーになった。
たぶん内部的にループを展開していて、展開数が多くなりすぎるということなんだろうと思う。そんなエラーが出ていた。
有限回数のforループにしたらコンパイルが終わらなくなった。
コンパイラが無限ループして終了しないとか、普通に考えたらありえないのだが。
動かないのでコードが正しいかどうかはわからないが、とりあえずアップしとく。
・・・まあ、HLSLで作るようなもんではないのは確かにその通り。
#!ruby -Ks require 'dxruby' hlsl = <<EOS float4 color; texture Tex0; sampler Samp0 = sampler_state { Texture =<Tex0>; }; struct PixelIn { float2 UV : TEXCOORD0; }; struct PixelOut { float4 Color : COLOR0; }; PixelOut PS(PixelIn input) { PixelOut output; float4 current = tex2D( Samp0, input.UV ); float4 green = {0.0f, 1.0f, 0.0f, 1.0f}; if( (current.r == green.r && current.g == green.g && current.b == green.b) || (current.r == color.r && current.g == color.g && current.b == color.b) ) { output.Color = current; } else { float i, j; float2 vec[8] = {-1.0f, 0.0f, -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f}; float result = 0; for( i = 0; i < 4; i++ ) { float2 pos = input.UV + vec[i] / 7; float flag = 0; for( j = 0; j < 8 && flag == 0; j++ ) // whileがエラーになるので対策 { float4 c = tex2D( Samp0, pos ); if( (c.r == green.r && c.g == green.g && c.b == green.b) || pos.x < 0.0f || pos.y < 0.0f || pos.x > 1.0f || pos.y > 1.0f ) { flag = 1; // とりあえずこっちの方向では挟まれていない } else if( c.r == color.r && c.g == color.g && c.b == color.b ) { flag = 2; // とりあえずこっちの方向では挟まれているかもしれない } else { pos += vec[i] / 7; // 次に進む } } if( flag == 2 ) // 挟まれているかもしれない場合、反対方向に検索 { flag = 0; pos += vec[i+4] / 7; for( j = 0; j < 8 && flag == 0; j++ ) // whileがエラーになるので対策 { float4 c = tex2D( Samp0, pos ); if( (c.r == green.r && c.g == green.g && c.b == green.b) || pos.x < 0.0f || pos.y < 0.0f || pos.x > 1.0f || pos.y > 1.0f ) { flag = 1; // 挟まれてなかった } else if( c.r == color.r && c.g == color.g && c.b == color.b ) { flag = 2; // 挟まれていた } else { pos += vec[i+4] / 7; // 次に進む } } if( flag == 2 ) { result = 1; // 色を変えるフラグ i = 4; } } } if( result == 1 ) { output.Color = color; } else { output.Color = current; } } return output; } technique TShader { pass P0 { PixelShader = compile ps_2_0 PS(); } } EOS shader = Shader.new(hlsl, "TShader") shader.setValue("color", Vector.new(0.0, 0.0, 0.0, 0.0)) # 黒 rt = RenderTarget.new(8, 8) # 出力先 image = Image.new(8,8,[0,255,0]) # 盤 image[3,3] = [0,0,0] image[4,4] = [0,0,0] image[3,4] = [255,255,255] image[4,3] = [255,255,255] Window.magFilter = TEXF_POINT Window.loop do Window.drawShader(0, 0, image, shader) Window.update(rt) image = rt.to_image Window.drawScale(0,0,image, 8, 8, 0, 0) end