Tengo una ventana estándar de 800x600 en mi proyecto XNA. Mi objetivo es colorear cada píxel individual en función de una matriz rectangular que contenga valores booleanos. Actualmente estoy usando una textura 1x1 y dibujo cada sprite en mi matriz.¿Cómo puedo usar un Shader en XNA para colorear píxeles individuales?
Soy muy nuevo en XNA y vengo de un fondo GDI, así que estoy haciendo lo que habría hecho en GDI, pero no escala muy bien. Me han dicho en otra pregunta que use un Shader, pero después de mucha investigación, todavía no he podido averiguar cómo lograr este objetivo.
Mi aplicación recorre las coordenadas X e Y de mi matriz rectangular, realiza cálculos basados en cada valor y reasigna/mueve la matriz. Al final, tengo que actualizar mi "Lienzo" con los nuevos valores. Una muestra más pequeña de mi matriz se vería así:
0,0,0,0,0,0,0
0,0,0,0,0,0,0
0,0,0,0,0,0,0
1,1,1,1,1,1,1
1,1,1,1,1,1,1
¿Cómo puedo usar un sombreador para colorear cada píxel?
Una versión muy simplificada de los cálculos sería:
for (int y = _horizon; y >= 0; y--) // _horizon is my ending point
{
for (int x = _width; x >= 0; x--) // _width is obviously my x length.
{
if (grains[x, y] > 0)
{
if (grains[x, y + 1] == 0)
{
grains[x, y + 1] = grains[x, y];
grains[x, y] = 0;
}
}
}
}
..each vez que el método de actualización se llama, los cálculos se realizan y en el ejemplo del ciclo anterior, una actualización pueden verse como:
inicial:
0,0,0,1,0,0,0
0,0,0,0,0,0,0
0,0,0,0,0,0,0
1,1,1,0,1,1,1
1,1,1,1,1,1,1
primero:
0,0,0,0,0,0,0
0,0,0,1,0,0,0
0,0,0,0,0,0,0
1,1,1,0,1,1,1
1,1,1,1,1,1,1
Segundo:
0,0,0,0,0,0,0
0,0,0,0,0,0,0
0,0,0,1,0,0,0
1,1,1,0,1,1,1
1,1,1,1,1,1,1
final:
0,0,0,0,0,0,0
0,0,0,0,0,0,0
0,0,0,0,0,0,0
1,1,1,1,1,1,1
1,1,1,1,1,1,1
Actualización:
Después de aplicar el código Render2DTarget y colocando mis píxeles, termino con un borde no deseado en mis píxeles, siempre a la izquierda. ¿Cómo puedo eliminar esto?
alt text http://www.refuctored.com/borders.png
alt text http://www.refuctored.com/fallingdirt.png
La parte del código para la aplicación de las texturas es:
RenderTarget2D target;
Texture2D texture;
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
texture = Content.Load<Texture2D>("grain");
_width = this.Window.ClientBounds.Width - 1;
_height = this.Window.ClientBounds.Height - 1;
target = new RenderTarget2D(this.GraphicsDevice,_width, _height, 1, SurfaceFormat.Color,RenderTargetUsage.PreserveContents);
}
protected override void Draw(GameTime gameTime)
{
this.GraphicsDevice.SetRenderTarget(0, target);
this.GraphicsDevice.SetRenderTarget(0, null);
this.GraphicsDevice.Clear(Color.SkyBlue);
this.spriteBatch.Begin(SpriteBlendMode.None,SpriteSortMode.Deferred,SaveStateMode.None);
SetPixels(texture);
this.spriteBatch.End();
}
private void SetPixels(Texture2D texture)
{
for (int y = _grains.Height -1; y > 0; y--)
{
for (int x = _grains.Width-1; x > 0; x--)
{
if (_grains.GetGrain(x, y) >0)
{
this.spriteBatch.Draw(texture, new Vector2(x,y),null, _grains.GetGrainColor(x, y));
}
}
}
}
¿Te importaría compartir los cálculos que realizas en tu matriz rectangular? Si puede hacer esos cálculos dentro del sombreador, puede que no sea demasiado difícil de descifrar. Tengo problemas para averiguar cómo pasar una matriz de tamaño 800x600 al sombreador porque las matrices están limitadas a 65536 índices (índice de 16 bits), al parecer; por lo tanto, si pudiera realizar los cálculos dentro del sombreador sin tener que pasar la matriz grande en cada momento, sería más fácil averiguarlo. – Venesectrix
He actualizado la pregunta con más información de apoyo para su consulta. –
En realidad, lo siento, ahora que lo pienso, ese enfoque no es una buena idea por varias razones. Requiere que una textura represente el estado inicial de su matriz, el sombreador de píxeles no puede modificar la textura, solo puede devolver valores diferentes, por lo que cada vez que se llamó sería como comenzar desde el estado inicial, y lo hace todo los cálculos en la función draw() en lugar de la función update(), que probablemente no es una buena idea. – Venesectrix