Quanta precisão (half, float, double, etc) é suficiente para uma classe Color?

8

Ao ler algumas coisas sobre como os aplicativos em tempo real lidam com cores no OpneGL, notei que alguns exemplos implementavam Color como uma coleção de 4 floats, enquanto outros usavam 4 doubles. Eu já vi alguns exemplos de compactação de vértices no campo de desenvolvimento de jogos que defendiam salvar cores como 4 short.

Tudo isso me deixou ansioso por aprender mais sobre isso: qual é a precisão limite que o OpenGl (ou hardwares) manipula para cores? Mais importante, porém, quais são os limites de precisão acima dos quais as diferenças de cores se tornam impossíveis de observar?

Tenho a impressão de que aprender com mais cuidado sobre isso me ajudaria a pensar e decidir melhor como implementar uma classe Color para diferentes aplicativos e cenários (por exemplo, fazer escolhas de troca entre memória, velocidade e variedade de cores).

Obrigado por suas idéias sobre isso.

AndrewSteer
fonte

Respostas:

6

As cores mostradas no visor ou salvas em formatos de arquivo de imagem padrão usam 8 bits por componente. Portanto, para armazenar essas cores, basta usar quatro bytes ( unsigned char). Essas cores geralmente estão usando o espaço de cores sRGB , que inclui uma transformação "gama" não linear que redistribui a precisão para torná-la um pouco mais perceptualmente uniforme, portanto fica bem perto do limite de quão finamente os seres humanos já podem perceber as diferenças de cores. (No entanto, a gama sRGB é apenas um subconjunto de todas as cores fisicamente perceptíveis. Gamuts mais amplas precisam de mais bits.)

No entanto, se você estiver gerando ou processando cores no software gráfico (e não apenas carregando / armazenando-as), há vários motivos pelos quais você pode querer usar mais precisão.

  • A realização de operações em cores, como ajuste de brilho e contraste, mistura alfa, correção de gama, etc., todos tendem a perder precisão. Convém armazenar cores como 16 bits ou mais internamente, para obter mais espaço de precisão. Caso contrário, o arredondamento repetido para 8 bits após cada operação pode causar uma perda progressiva de qualidade.
  • Da mesma forma, ao trabalhar com cores lineares (não as cores codificadas por sRGB gama) para iluminar a matemática, é necessária uma precisão extra para garantir que você tenha precisão suficiente ao converter novamente para sRGB.
  • Pode ser mais rápido e mais conveniente trabalhar com cores de ponto flutuante em vez de cores inteiras. Isso é especialmente verdadeiro nas GPUs, nas quais as instruções matemáticas inteiras têm apenas uma fração da taxa de transferência das instruções de flutuação. Mas mesmo em CPUs é certamente mais fácil e provavelmente mais rápido converter cores para flutuar, executar várias operações e depois converter novamente em número inteiro, em vez de tentar fazer tudo com matemática de ponto fixo inteiro.
  • Se você executar a renderização HDR, precisará de mais de 8 bits de precisão para lidar com a maior gama de cores e intensidade. Os novos monitores HDR que estão começando a aparecer aceitam imagens com 10 ou 12 bits por componente.

O uso doublede cores é um exagero maciço, mas o uso floatpara representação interna de cores é comum por todos os motivos acima. Ao trabalhar com GPUs, half(flutuação de 16 bits) também é comum, pois eles suportam esse formato em hardware.

Nathan Reed
fonte
Excelente resposta, obrigado! Eu simplesmente não entendi a última parte: usar um halfnão teria os mesmos problemas que você mencionou antes, devido à falta de precisão? Eu pensei que isso seria particularmente importante na GPU, devido aos muitos cálculos de cores que são freqüentemente feitos em shaders
#
11
O @AndrewSteer A halftem 16 bits, incluindo 11 bits efetivos de precisão de mantissa, portanto, embora não seja tão preciso quanto possível float, ainda é suficiente para a maioria das operações de cores. (Talvez não completamente ; suficiente se você estiver saída para um display de alta gama HDR eu não tenho certeza.)
Nathan Reed