Como criar um sombreador de pixel "retro" para sprites 2D transformados que mantém a fidelidade do pixel?

10

A imagem abaixo mostra dois sprites renderizados com amostragem de pontos no topo de um plano de fundo:

insira a descrição da imagem aqui

  • O crânio esquerdo não possui rotação / redimensionamento, portanto, cada pixel combina perfeitamente com o fundo.
  • O crânio direito é girado / escalado e isso resulta em pixels maiores que não estão mais alinhados ao eixo .

Como eu desenvolvi um sombreador de pixel que renderizaria o sprite transformado à direita com pixels alinhados ao eixo do mesmo tamanho que o resto da cena?

Isso pode estar relacionado à forma como o dimensionamento do sprite foi implementado em jogos antigos, como Monkey Island, porque esse é o efeito que estou tentando obter, mas com a rotação adicionada.


Editar

De acordo com as sugestões do kaoD, tentei resolver o problema como um pós-processo. A abordagem mais fácil foi renderizar primeiro para um destino de renderização separado (redução de tamanho para corresponder ao tamanho de pixel desejado) e, em seguida, aumentar a escala ao renderizar uma segunda vez. Ele atendeu aos meus requisitos acima.

Primeiro eu tentei fazê-lo Linear -> Pointe o resultado foi o seguinte:

insira a descrição da imagem aqui

Não há distorção, mas o resultado parece desfocado e perde a maioria das cores dos destaques. Na minha opinião, quebra o visual retrô que eu precisava.

A segunda vez que tentei Point -> Pointe o resultado foi este:

insira a descrição da imagem aqui

Apesar da distorção, acho que isso pode ser bom o suficiente para minhas necessidades, embora pareça melhor como uma imagem parada do que em movimento.

Para demonstrar, aqui está um vídeo do efeito, embora o YouTube tenha filtrado os pixels:

http://youtu.be/hqokk58KFmI

No entanto, deixarei a pergunta em aberto por mais alguns dias, caso alguém encontre uma solução de amostragem melhor que mantenha a aparência nítida enquanto diminui a quantidade de distorção ao se mover.

David Gouveia
fonte
Isso deveria ser uma caveira ...?
DeadMG
@DeadMG Um crânio de boi, eu acho?
David Gouveia
Efeito agradável, parece melhor do que eu pensava (tentei na paleta e resolução EXTREMELY baixa resolução, EGA de 40x30). BTW, duvido que exista uma solução de amostragem melhor que mantenha o efeito como você pretende. NN é muito bonito o que dá aquele olhar nítido, qualquer outra amostragem vai borrar a imagem final (apenas supondo qualquer maneira.)
kaoD
@kaoD Mas lembre-se de que estou aplicando dois passes. A segunda passagem que amplia a imagem ainda será a vizinha mais próxima para preservar a sensação retrô. Mas acho que pode haver algum benefício em tentar diferentes técnicas de amostragem para a primeira passagem. Atualmente, estou olhando para o Scale2x!
David Gouveia
@kaoD Nah, eu desisto. Alterar os parâmetros do shader entre cada chamada de sprite SpriteBatchrequer que eu use o modo Imediato, para que não valha a pena. Eu vou com isso :)
David Gouveia

Respostas:

3

Você deve aplicar seu shader APÓS seu sprite ter sido girado.

Se a cena inteira ainda não foi sombreada e seus sprites estão realmente pixelizados, o que você precisa é de algum tipo de filtro pós-FX para toda a cena. A média das regiões de pixels funcionará bem. Não é exatamente o que você pretende (vai parecer meio distorcido quando se move / gira), mas pode fazer o truque.

A única maneira de manter o visual retrô fiel ao que você quer é realmente desenhar suas rotações de sprite. Não tem nada a ver com a implementação do dimensionamento: a resolução era realmente ruim, falando nisso, você tentou com resoluções extremamente baixas? Também pode ser útil e parecerá mais natural, pois, na verdade, foi o que causou o efeito que você está procurando. E é barato! Muito barato! De fato, será mais barato do que o que você já possui (menos execuções de shader de fragmento).

O efeito é arruinado na imagem de amostra porque sua resolução é alta em comparação com os sprites, permitindo que você veja os pixels reais em cena.

kaoD
fonte
Sim, ainda não estou usando shaders. São apenas sprites regulares com texturas de resolução muito baixa, renderizados com o padrão do XNA SpriteBatchcom a amostragem de pontos ativada. Mas um pós-FX pode realmente funcionar. Para iniciantes, tentarei renderizar com amostragem linear em um destino de renderização e, em seguida, renderize todo o destino de renderização no backbuffer com amostragem de pontos.
David Gouveia
@DavidGouveia não perca a oportunidade de avaliar sua resolução. Se você realmente deseja obter o efeito original, é a sua melhor chance. Se você precisar de alta resolução (se uma parte do seu GFX for alta resolução ou quiser corresponder às resoluções nativas), ainda poderá renderizar em um buffer de baixa resolução fora da tela e pintá-lo em seu buffer de quadros de alta resolução como um tamanho completo. quad-screen com a filtragem desativada. Lembre-se de que você precisa combinar as proporções para evitar pixels retangulares, é claro.
kaoD
Verifique minha edição :) Acho que resolveu a maior parte do problema, embora ainda esteja curioso para saber se existe uma solução de amostragem melhor que o vizinho mais próximo para esse problema. Vou deixar a pergunta correr por mais algum tempo.
David Gouveia