Sprites de contorno

9

Atualmente, estou trabalhando em um jogo 2D, e minha tarefa atual é descrever o objeto selecionado.

Basicamente, uso um shader de desfoque para fazê-lo em tempo de execução total. Primeiro, desenho meu sprite usando um sombreador de desfoque gaussiano vertical, depois o desenho com um sombreador de desfoque gaussiano horizontal e depois desenho meu sprite normalmente.

Aqui está o meu shader shader: 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 são as compensações que permitem testar os pixels de arredondamento. SampleWeights são pesos calculados com a função gaussiana ( http://en.wikipedia.org/wiki/Gaussian_blur )

Aqui está o resultado:

insira a descrição da imagem aqui

Não é tão ruim, bastante suave, mas não é visível o suficiente no jogo ... Mas eu gostaria de poder controlar a espessura (para aumentá-la) e adicionar um primeiro contorno opaco antes de desbotá-la em alfa (para mais visível). E eu sinto que o borrão gaussiano talvez não seja tão bom quanto eu pensava na minha tarefa :)

Outra idéia é gerá-lo automaticamente a partir do .png (usando um script do photoshop para torná-lo automático). Eu só preciso preencher os pixels do contorno com uma cor personalizada, armazenando o valor alfa no componente Vermelho, por exemplo, e definir todos os outros componentes como 0. Então, só preciso aplicar um sombreador que substitua os pixels transparentes pela cor desejada

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;
    }
}

O problema é que estou usando a compressão DXT5 para o meu sprite, então não tenho certeza de que a cor do shader será exatamente a mesma que escrevi. É por isso que eu nem tentei ... Alguma idéia?

Qualquer conselho seria bem vindo :)

s0ubap
fonte
Você deve poder controlar a espessura e a queda alfa no seu shader. Gostaria de publicá-lo para referência?
Seth Battin
Eu usei o shader Gaussian Blur a partir desta amostra: ligação deixe-me editar o meu post para mostrar-lhe o shader em detalhes
s0ubap
Não tenho certeza se o desfoque gaussiano é o caminho certo para você. Tente um pouco de desfoque radial.
user1306322

Respostas:

6

O que você provavelmente está procurando é uma forma de detecção de borda antes, depois ou mesmo antes e depois do desfoque gaussiano. Talvez uma versão do Sobel Edge Detection possa funcionar. Eu sei que seu jogo é 2D, mas se a página da wiki for muito grossa, aqui está um tutorial sobre como fazê-lo funcionar no UDK que pode ser traduzido melhor.

Sua detecção de borda só precisa encontrar as bordas do canal alfa se você precisar de um aumento de velocidade.

Alex Shepard
fonte
Interessante! Eu tentei. O resultado foi bom, exceto quando eu zoom in / out ... Pixels aparecem e desaparecem, resultando em artefatos indesejados ...
s0ubap
11
Que tipo de artefato você está vendo? Você pode fornecer uma imagem?
Alex Shepard
2

O que funcionou para mim com o esboço de texto foi:

  • Escolha a cor do contorno
  • Desenhe o texto em (x-1, y-1) com a cor do contorno
  • Desenhe o texto em (x + 1, y-1) com a cor do contorno
  • Desenhe o texto em (x-1, y + 1) com a cor do contorno
  • Desenhe o texto em (x + 1, y + 1) com a cor do contorno
  • Desenhe o texto em (x, y)

Você pode fazer a mesma coisa - tudo o que você precisa fazer é desenhar o sprite com os pixels opacos coloridos com a cor do contorno. (Mantenha os valores de transparência para que as bordas arredondadas ainda pareçam redondas).

Isso funciona, parece melhor do que desenhar uma versão em escala e tem algumas outras propriedades interessantes (como poder controlar o alfa do contorno para obter ousadia e manter quaisquer "furos" na imagem do sprite) - a única desvantagem é que você pode ' realmente não controla muito bem a largura do contorno.

ashes999
fonte
1

Eu sou meio que novato em tudo isso, mas aqui está a minha ideia:

Você pode usar o canal alfa da sua textura para criar outra textura. Qualquer valor alfa abaixo de um valor limite será definido como totalmente transparente. Qualquer um dos itens acima será totalmente opaco. Usando essa nova textura, você pode definir os valores de RGB para qualquer cor que desejar. Escale essa nova "textura" para ser um pouco maior que a textura do seu personagem. Isso daria uma boa cor sólida ao redor do personagem. Em seguida, use essa cor com seu sombreador gaussiano para dar um brilho agradável ao redor da textura criada. Suponho que isso possa ser feito sem criar outra textura e ser todo o sombreamento baseado na textura do personagem.

Isso faz algum sentido?

aglassman
fonte
Este método tem uma falha importante ao lidar com formas não côncavas. Por exemplo, quando aplicado a uma rosquinha, somente a borda externa obterá um contorno. Sem mencionar outras distorções na espessura do contorno.
Kromster 6/03/2013