[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
エリア総和テーブル(Summed Area table)を作る実験をまたやってみました。
前回は横方向にだけ足しましたが、今回は縦方向にも足します。
驚いたことに、ちょっとした修正をするだけで縦方向にも足せるようになりますね。
これでようやくエリア総和テーブルとして使えるようになるはずです。(たぶん)
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
public class MyGame : Game
{
GraphicsDeviceManager graphics;
Texture2D texture;
BasicEffect basicEffect;
VertexDeclaration vertexDeclaration;
Effect tableCreationEffect;
RenderTarget2D renderTarget;
public MyGame()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
//指定したサイズのテクスチャを作ります。
//サイズをいろいろ変えると、
//いろいろなサイズのエリア総和テーブルが作れます。
initTexture(8, 8);
renderTarget = new RenderTarget2D(
GraphicsDevice,
texture.Width, texture.Height,
1,
SurfaceFormat.Vector4
);
tableCreationEffect = Content.Load<Effect>("SummedAreaTableCreator");
basicEffect = new BasicEffect(GraphicsDevice, null);
vertexDeclaration = new VertexDeclaration(
GraphicsDevice,
VertexPositionTexture.VertexElements
);
GraphicsDevice.VertexDeclaration = vertexDeclaration;
}
private void initTexture(int width, int height)
{
texture = new Texture2D(
GraphicsDevice,
width, height,
1,
TextureUsage.None,
SurfaceFormat.Vector4
);
Vector4[] data = new Vector4[texture.Width * texture.Height];
for (int i = 0; i < data.Length; i++)
data[i] = Vector4.One / data.Length;
texture.SetData<Vector4>(data);
}
protected override void UnloadContent()
{
texture.Dispose();
renderTarget.Dispose();
basicEffect.Dispose();
vertexDeclaration.Dispose();
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(0, renderTarget);
GraphicsDevice.Clear(Color.CornflowerBlue);
drawTexture(texture);
createSummedAreaTable();
GraphicsDevice.SetRenderTarget(0, null);
GraphicsDevice.Clear(Color.CornflowerBlue);
drawTexture(renderTarget.GetTexture());
}
//GraphicsDeviceにセットされているレンダーターゲットを、
//自分自身のエリア総和テーブルに変えます。
private void createSummedAreaTable()
{
tableCreationEffect.Parameters["Width"].SetValue(renderTarget.Width);
tableCreationEffect.Parameters["Height"].SetValue(renderTarget.Height);
tableCreationEffect.Begin();
//横方向に足す
for (int i = 0; i < System.Math.Log(renderTarget.Width, 2); i++)
{
tableCreationEffect.CurrentTechnique.Passes["SumXPass"].Begin();
GraphicsDevice.SetRenderTarget(0, null);
tableCreationEffect.Parameters["PreviousProduct"].SetValue(renderTarget.GetTexture());
GraphicsDevice.SetRenderTarget(0, renderTarget);
tableCreationEffect.Parameters["PassIndex"].SetValue(i);
drawRect();
tableCreationEffect.CurrentTechnique.Passes["SumXPass"].End();
}
//縦方向に足す
for (int i = 0; i < System.Math.Log(renderTarget.Height, 2); i++)
{
tableCreationEffect.CurrentTechnique.Passes["SumYPass"].Begin();
GraphicsDevice.SetRenderTarget(0, null);
tableCreationEffect.Parameters["PreviousProduct"].SetValue(renderTarget.GetTexture());
GraphicsDevice.SetRenderTarget(0, renderTarget);
tableCreationEffect.Parameters["PassIndex"].SetValue(i);
drawRect();
tableCreationEffect.CurrentTechnique.Passes["SumYPass"].End();
}
tableCreationEffect.End();
}
private void drawTexture(Texture2D texture)
{
basicEffect.TextureEnabled = true;
basicEffect.Texture = texture;
basicEffect.Begin();
basicEffect.CurrentTechnique.Passes[0].Begin();
drawRect();
basicEffect.CurrentTechnique.Passes[0].End();
basicEffect.End();
}
private void drawRect()
{
//四角形(テクスチャつき)の頂点
VertexPositionTexture[] vertices = {
new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2()),
new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0)),
new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1)),
new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0)),
new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1)),
new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1))
};
GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>(
PrimitiveType.TriangleList,
vertices,
0,
2
);
}
static void Main()
{
using (MyGame game = new MyGame())
{
game.Run();
}
}
}
texture PreviousProduct;
sampler TextureSampler = sampler_state
{
Texture = (PreviousProduct);
};
float Width;
float Height;
int PassIndex;
struct VertexPositionTexture
{
float4 Position : POSITION;
float2 TextureCoordinate : TEXCOORD;
};
VertexPositionTexture VertexShaderFunction(VertexPositionTexture input)
{
return input;
}
float4 getColor(float2 texCoord)
{
if(texCoord.x < 0 || texCoord.y < 0) return 0;
else return tex2D(TextureSampler, texCoord + float2(0.5/Width, 0.5/Height));
}
float4 SumX(float2 textureCoordinate : TEXCOORD):COLOR
{
return getColor(textureCoordinate + float2((-1/ Width) * exp2(PassIndex), 0))
+ getColor(textureCoordinate);
}
float4 SumY(float2 textureCoordinate : TEXCOORD):COLOR
{
return getColor(textureCoordinate + float2(0, (-1/ Height) * exp2(PassIndex)))
+ getColor(textureCoordinate);
}
technique Technique1
{
pass SumXPass
{
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_2_0 SumX();
}
pass SumYPass
{
VertexShader = compile vs_1_1 VertexShaderFunction();
PixelShader = compile ps_2_0 SumY();
}
}
private void createSummedAreaTable()
{
tableCreationEffect.Parameters["Width"].SetValue(renderTarget.Width);
tableCreationEffect.Parameters["Height"].SetValue(renderTarget.Height);
tableCreationEffect.Begin();
//横方向に足す
tableCreationEffect.CurrentTechnique.Passes["SumXPass"].Begin();
for (int i = 0; i < System.Math.Log(renderTarget.Width, 2); i++)
{
GraphicsDevice.SetRenderTarget(0, null);
tableCreationEffect.Parameters["PreviousProduct"].SetValue(renderTarget.GetTexture());
GraphicsDevice.SetRenderTarget(0, renderTarget);
tableCreationEffect.Parameters["PassIndex"].SetValue(i);
tableCreationEffect.CommitChanges();
drawRect();
}
tableCreationEffect.CurrentTechnique.Passes["SumXPass"].End();
//縦方向に足す
tableCreationEffect.CurrentTechnique.Passes["SumYPass"].Begin();
for (int i = 0; i < System.Math.Log(renderTarget.Height, 2); i++)
{
GraphicsDevice.SetRenderTarget(0, null);
tableCreationEffect.Parameters["PreviousProduct"].SetValue(renderTarget.GetTexture());
GraphicsDevice.SetRenderTarget(0, renderTarget);
tableCreationEffect.Parameters["PassIndex"].SetValue(i);
tableCreationEffect.CommitChanges();
drawRect();
}
tableCreationEffect.CurrentTechnique.Passes["SumYPass"].End();
tableCreationEffect.End();
}