Esquema de sprites

9

Actualmente estoy trabajando en un juego 2D, y mi tarea actual es delinear el objeto seleccionado.

Básicamente utilizo un sombreador de desenfoque para hacerlo en tiempo de ejecución completo. Primero dibujo mi sprite usando un sombreador de desenfoque gaussiano vertical, luego lo dibujo con un sombreador de desenfoque gaussiano horizontal, y luego dibujo mi sprite normalmente.

Aquí está mi sombreador de desenfoque: sampler TextureSampler: register (s0);

#define SAMPLE_COUNT 15

float2 SampleOffsets[SAMPLE_COUNT];
float SampleWeights[SAMPLE_COUNT];


float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 c = 0;

    // Combine a number of weighted image filter taps.
    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];
    }

    return c;
}

SampleOffets son los desplazamientos que me permiten probar píxeles de redondeo SampleWeights son pesos calculados con función gaussiana ( http://en.wikipedia.org/wiki/Gaussian_blur )

Aquí está el resultado:

ingrese la descripción de la imagen aquí

No es tan malo, bastante suave, pero no lo suficientemente visible en el juego ... Pero me gustaría poder controlar el grosor (para hacerlo más grande) y agregar un primer contorno opaco antes de desvanecerlo en alfa (para hacer es más visible) Y siento que el desenfoque gaussiano tal vez no sea tan bueno como pensé para mi tarea :)

Otra idea es generarlo automáticamente desde el .png (usando un script de Photoshop para hacerlo automático). Solo necesito llenar los píxeles del contorno con un color personalizado, almacenando el valor alfa en el componente Rojo, por ejemplo, y establecer todos los demás componentes en 0. Luego, solo tengo que aplicar un sombreador que reemplace los píxeles transparentes al color que quiero.

float4 PixelShaderFunction2(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(TextureSampler, texCoord);
    float4 newColor = 0;
    if (color.a == 0 && color.r != 0)
    {
        color.a = color.r;
        // Blue outline
        color.b = 1;
    }
}

El problema es que estoy usando la compresión DXT5 para mi sprite, así que no puedo estar seguro de que el color que obtendré en mi sombreador será exactamente el mismo que escribí. Es por eso que ni siquiera lo intenté ... ¿Alguna idea?

Cualquier consejo sería bienvenido :)

s0ubap
fuente
Debería poder controlar el grosor y la caída alfa en su sombreador. ¿Quieres publicarlo como referencia?
Seth Battin
Utilicé el sombreador de desenfoque gaussiano de esta muestra: el enlace me permite editar mi publicación para mostrarle el sombreador en detalles
s0ubap
No estoy seguro de que el desenfoque gaussiano sea el adecuado para ti. Intente un poco de desenfoque radial en su lugar.
user1306322

Respuestas:

6

Lo que probablemente esté buscando es una forma de detección de bordes antes, después o incluso antes y después de su desenfoque gaussiano. Tal vez una versión de Sobel Edge Detection podría funcionar. Sé que tu juego es 2D, pero si la página wiki es demasiado tosca, aquí hay un tutorial sobre cómo hacerlo funcionar en el UDK que podría traducirse mejor.

Su detección de bordes solo tiene que encontrar los bordes del canal alfa si necesita un aumento de velocidad.

Alex Shepard
fuente
¡Interesante! Lo intenté. El resultado fue bueno, excepto cuando
acerco
1
¿Qué tipo de artefacto estás viendo? ¿Puedes proporcionar una imagen?
Alex Shepard
2

Lo que funcionó para mí con la descripción del texto fue:

  • Elige el color del contorno
  • Dibuje el texto en (x-1, y-1) con color de contorno
  • Dibuje el texto en (x + 1, y-1) con el color del contorno
  • Dibuje el texto en (x-1, y + 1) con el color del contorno
  • Dibuje el texto en (x + 1, y + 1) con el color del contorno
  • Dibuja el texto en (x, y)

Puede hacer lo mismo: todo lo que necesita hacer es dibujar el sprite con los píxeles opacos coloreados con su color de contorno. (Mantenga los valores de transparencia para que los bordes redondos sigan pareciendo redondos).

Esto funciona, se ve mejor que dibujar una versión a escala y tiene algunas otras propiedades interesantes (como poder controlar el contorno alfa para la negrita y retener los "agujeros" en la imagen de su sprite): el único inconveniente es que puede ' No controlas demasiado bien el ancho del contorno.

cenizas999
fuente
1

Soy algo nuevo en todo esto, pero aquí está mi idea:

Podrías usar el canal alfa de tu textura para hacer otra textura. Cualquier valor alfa por debajo de un valor umbral se establecerá en totalmente transparente. Cualquier anterior será completamente opaco. Con esta nueva textura, puede establecer los valores de RGB para que sean del color que desee. Escala esta nueva "textura" para que sea un poco más grande que la textura de tu personaje. Esto te daría un bonito color sólido alrededor del personaje. Luego, use ese color con su sombreador gaussiano para darle un brillo agradable alrededor de su textura creada. Supongo que esto podría hacerse sin crear otra textura, y ser todo sombreador basado en la textura del personaje.

¿Tiene esto algún sentido?

aglassman
fuente
Este método tiene un defecto importante cuando se trata de formas no cóncavas. Por ejemplo, cuando se aplica a una rosquilla, solo el borde exterior obtendrá un contorno. Sin mencionar otras distorsiones de grosor del contorno.
Kromster