Uma textura detalhada leva mais tempo para renderizar?

22

Digamos que eu queira renderizar um quadrado; sua textura é "square.png".

É mais fácil para o computador renderizá-lo se a textura tiver apenas uma cor lisa?

E se for muito barulhento textura com cores completamente aleatórias aqui e ali?

Ou, e se essa textura for barulhenta, no sentido de que cada pixel é diferente de um para outro, mas apenas um pouquinho?

user3491043
fonte

Respostas:

39

Como a maioria das coisas no desenvolvimento de jogos, e especialmente nos gráficos de jogos, a resposta é "depende"

Tamanho da textura

A resolução da sua textura pode afetar a velocidade de renderização. Quanto mais pixels ele contém, mais dados brutos existem para carregar na GPU e menos textura é possível caber no cache de cada vez, para que o shader atinja mais pausas enquanto aguarda a parte certa da textura ser puxado para o cache.

O uso do mipmapping pode reduzir o impacto disso. Com os mipmaps, armazenamos uma cadeia de versões reduzidas da textura, que a princípio parece ainda mais memória para esquivar. Mas nos permite ler as versões menores quando a textura é exibida em um tamanho pequeno na tela (como um objeto distante em perspectiva), para que nossas amostras façam melhor uso do cache de texturas, em vez de saltarem por toda parte. Isso também reduz o alias.

Detalhe de textura

O conteúdo de suas texturas não afeta a eficiência da renderização na maioria das vezes.

Uma cor é apenas um monte de números no que diz respeito à GPU, por isso não se importa muito com o que esses números são, apenas os canaliza através da matemática da mesma maneira. Não faz nada extravagante como lembrar "Ah, eu já vi um pixel nesse verde antes, vou reutilizar a mesma saída que calculei na última vez que vi essa entrada", para saber se sua textura é de uma só cor ou brilhos aleatórios, sua GPU está fazendo o mesmo trabalho.

Ao contrário de formatos como PNG e JPG, que compactam com mais eficiência em áreas previsíveis da imagem e consomem mais bits em regiões complexas, os formatos de textura de GPU como BTC, ETC, PVRTC ou mesmo RGBA bruto usam um número fixo de bits por bloco de píxeis. Portanto, tornar sua textura mais ou menos detalhada, mantendo o mesmo formato de compactação, não altera o tamanho dos dados nem afeta a transferência de dados e a eficiência relacionada ao cache.

Porém, se você usar um tipo específico de detalhe que a compactação anterior não preserva bem, poderá ser forçado a alterar toda a imagem para usar um formato diferente, o que poderá alterar novamente o tamanho dos dados.

Ramificação e Indirecionamento de Shader

Aqui está o maior asterisco da situação: você pode estar usando essa entrada de cor da textura para tomar decisões, como um if()ramo. Aqui, os detalhes são importantes para a velocidade.

As unidades de sombreamento da GPU trabalham em blocos de pixels em lotes, executando as mesmas instruções em paralelo em vários fluxos de dados. Portanto, quando alguns pixels no bloco ocupam um ramo do ifoutro e outros pixels, o lote inteiro precisa passar pelos dois ramos (mascarando os resultados que não se aplicam a um conjunto de pixels ou outro)

Se sua entrada for alterada de maneira suave / previsível, é provável que você tenha muitos blocos que precisam apenas de um único ramo, e esses casos de ambos os ramos serão limitados a faixas estreitas ao redor da borda de transição. Mas se sua entrada for aleatória, esperamos que a maioria dos blocos pegue os dois ramos e diminua a renderização.

Isso também pode acontecer se você estiver usando uma textura para controlar pesquisas em uma segunda textura, como um mapa de distorção ou índice. Se a primeira textura saltar aleatoriamente, coletaremos amostras de pontos aleatórios e dispersos da segunda textura, fazendo uso menos consistente de nosso cache de textura e aguardando mais tempo para obter os dados de que precisamos, em média.


Portanto, no geral: não, o conteúdo da textura não tem muito impacto na velocidade de renderização, exceto nos casos em que ocorre. ;)

DMGregory
fonte
Texturas de baixa resolução (acho que o Minecraft) teriam mais probabilidade de carregar texels para pixels adjacentes no cache quando um texel específico é carregado no cache, certo?
user253751
6
@immibis Minecraft tem pequenas texturas. O padrão é apenas 16x16, que se encaixa tão facilmente no cache de textura de cada núcleo que nem é engraçado: D E sim, a maioria das amostras de textura será do mesmo texel, a menos que você esteja muito longe do bloco. Isso é especialmente verdadeiro se você levar em consideração a subdivisão da tela - se você estiver razoavelmente próximo, todo o lote de um determinado núcleo poderá ser mapeado para o mesmo texel: GPU mais simples do DA provavelmente funcionaria melhor para texturas de baixa definição - suspeito muito esforço é desperdiçado em otimizações que não ajudam em nada o Minecraft.
Luaan 14/03/19
1
Observação: o "usa o mesmo número de bytes por pixel" é realmente a chave para alguns dos hacks rápidos que o código gráfico usa. Se você tentasse usar PNG internamente, ou mesmo algo como UTF-8 com um tamanho de pixel variável, para chegar ao ndécimo pixel, seria necessário passar por cada pixel antes dele. Com uma largura constante de bytes de pixel, é apenas start_of_buffer + width * n, o que é muito mais rápido, especialmente para grandes n.
Fund Monica's Lawsuit
@Luaan, quero dizer que, mesmo quando você estiver longe do bloco, quando ele buscar um texel (o que ocorrer primeiro), ele deverá puxar alguns adjacentes para o cache também.
precisa saber é o seguinte
4
É o caso de que falo acima com o mipmapping. Para evitar que nossas amostras pulem toda a textura, deixando grandes lacunas com pouca ou nenhuma reutilização de cache, armazenamos uma versão de 512x512 e uma de 256x256 e .... até 1x1 às vezes. Portanto, ao desenhar a textura 1024x1024 em 16x16, a maioria dos jogos realmente lê do mip 16x16 e tem desempenho semelhante ao do Minecraft 16x16 em termos de eficiência de cache. Isso também reduz artefatos de aliasing brilhantes da redução da amostra.
DMGregory
1

Juntamente com a excelente resposta do DMGregory acima, talvez haja um caso em que a complexidade de uma "textura" possa afetar o desempenho da renderização e é aí que os resultados de uma renderização anterior são usados ​​como fonte em uma subsequente, por exemplo, mapas de sombras / reflexões / mapas de ambiente.

Alguns hardwares modernos podem aplicar compactação sem perdas a esses buffers: por exemplo, o PowerVR possui PVRIC , AMD, Delta Color Compression e ARM possui algo semelhante. O objetivo dessas técnicas de compactação é reduzir a largura de banda geral que, por sua vez, pode melhorar o desempenho da renderização.

Quanto mais simples os dados, seja profundidade ou cor (número inteiro ou ponto flutuante), melhor esses esquemas funcionarão. Obviamente, eu não sugeriria simplificar deliberadamente sua saída de renderização apenas para que funcionem melhor, mas evitar o uso de dados ruidosos pode ajudar em algumas circunstâncias.

Além disso, fazer uma amostragem esparsa de buffers de quadro / profundidade que usam esses esquemas, em uma tentativa vã de diminuir a largura de banda, não ajudará porque é muito provável que sejam baseados em blocos.

Além disso, você pode encontrar estas duas perguntas e respostas de interesse da SE Computer Graphics:

Simon F
fonte