Pergunta

Existe algo incomum sobre como o componente alfa é tratado em um shader de pixels? Eu tenho um aplicativo WPF para o qual meu artista está me dando imagens em escala de cinza para usar como fundo, e o aplicativo coloriza essas imagens de acordo com o estado atual. Então, escrevi um shader de pixel (usando a infraestrutura da biblioteca de efeitos do shader do WPF Pixel) para usar como efeito em um elemento de imagem. O shader toma uma cor como um parâmetro, que converte para o HSL para que possa manipular o brilho. Então, para cada pixel cinza, ele calcula uma cor cujo brilho é interpolado entre o parâmetro de cor e o branco proporcionalmente ao brilho do pixel de origem.

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 src = tex2D(implicitInputSampler, uv);

    // ...Do messy computation involving src brightness and color parameter...

    float4 dst;
    dst.r = ...
    dst.g = ...
    dst.b = ...
    dst.a = src.a;
    return dst;
}

Isso funciona bem nos pixels em que alfa = 1. Mas onde alfa = 0, os pixels resultantes saem brancos, em vez de exibir o plano de fundo da janela. Então eu fiz uma pequena mudança:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 src = tex2D(implicitInputSampler, uv);
    if (src.a == 0) 
        return src;
    ...

E agora as partes transparentes são realmente transparentes. Por quê? Por que não dst.a = src.a A declaração na primeira versão faz isso? Infelizmente, mesmo essa é apenas uma correção parcial, porque me parece que os pixels com 0 <alfa <1 estão saindo branco.

Alguém sabe o que não estou entendendo sobre Alpha?

Foi útil?

Solução

Depois de mais algumas pesquisas na web, descobri a peça que estava perdendo.

De acordo com Um artigo sobre MSDN: "O WPF usa alfa pré-multiplicado em todos os lugares internamente por vários motivos de desempenho, então é também a maneira como interpretamos os valores de cores no shader de pixel personalizado".

Portanto, a correção acaba sendo lançar uma multiplicação por Alpha:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    ...
    dst.rgb *= src.a;
    return dst;
}

E agora minha saída parece como eu espero.

Outras dicas

0 <alfa <1 está saindo branco

Que faixas você está esperando aqui?

Todos os valores estarão no intervalo de 0,0 e 1,0 ... os shaders de pixels não funcionam em intervalos de cores discretos 256, eles são o ponto flutuante em que 1.0 é a intensidade máxima.

Se seus cálculos acabarem definindo valores R/G/B para> 1.0, você vai ficar branco ...

http://www.facewound.com/tutorials/shader1/

Cara, estou trabalhando em um jogo XNA e tive que usar um shader de pixels em escala de cinza e tive o mesmo problema que você está enfrentando. Eu não estou familiarizado com o ambiente XNA ou não, mas resolvi o problema alterando o SpriteBatch desenho SpriteBlendMode a partir de SpriteBlendMode.none para SpriteBlendMode.alphablend, Espero que isso possa ajudá -lo a saber o motivo.

Saudações,

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top