Usando a correção gama

A correção gama, ou gama, é o nome de uma operação não linear que os sistemas usam para codificar e decodificar valores de pixel em imagens.

O que é gama e para que serve?

No final do pipeline gráfico, exatamente onde a imagem sai do computador para fazer seu percurso ao longo do cabo do monitor, há uma pequena peça de hardware que pode transformar valores de pixel em tempo real. Esse hardware normalmente usa uma tabela de pesquisa para transformar os pixels. Esse hardware usa os valores vermelho, verde e azul que vêm da superfície a serem exibidos para pesquisar valores corrigidos por gama na tabela e, em seguida, envia os valores corrigidos para o monitor em vez dos valores reais da superfície. Portanto, essa tabela de pesquisa é uma oportunidade de substituir qualquer cor por qualquer outra cor. Embora a tabela tenha esse nível de potência, o uso típico é ajustar as imagens sutilmente para compensar as diferenças na resposta do monitor. A resposta do monitor é a função que relaciona o valor numérico dos componentes vermelho, verde e azul de um pixel com o brilho exibido desse pixel.

Era para isso que esta tabela se destinava, mas os desenvolvedores de jogos encontraram usos criativos para ela, como piscar a tela inteira em vermelho para efeito psicológico. Em aplicativos de jogos modernos, como parte do pós-processamento de cada quadro, normalmente fornecemos outras maneiras de fazer essas coisas. Na verdade, recomendamos que você deixe a tabela gama em paz porque ela pode estar em uso para calibrar a resposta do monitor, e as alterações por atacado na rampa gama destruirão essa calibragem cuidadosa.

A ciência da determinação da correção gama é complexa, e não é apresentada aqui, além de iluminar de onde veio o nome "gama". A resposta de um monitor crt (ou seja, um vidro à moda antiga) é uma função complexa, mas a física desses monitores significa que eles exibem uma resposta que pode ser representada grosseiramente por essa função de poder:

brilho( entrada ) =gama de entrada

O valor gama normalmente é próximo de um valor de 2,0. Monitores LCD e todas as outras tecnologias mais recentes são projetados especificamente para exibir uma resposta semelhante para que todos os nossos softwares e imagens não precisem ser recalculados para essas novas tecnologias. O padrão sRGB declara que esse valor gama é exatamente 2,2 e esse valor se tornou um padrão amplamente implementado.

O olho humano também tem uma função de resposta que inverte aproximadamente a função de energia CRT. Isso significa que o brilho percebido de um pixel sobe aproximadamente linearmente com os valores RGB nesse pixel.

Como um valor gama de 2.2 tornou-se um padrão de fato, normalmente não precisamos nos preocupar muito com a curva gama codificada nesta tabela e podemos deixá-la como um mapeamento linear, um para um. A correspondência de cores adequada, naturalmente, requer um cuidado requintado com essa função, mas essa discussão está além do escopo deste tópico. O Windows inclui uma ferramenta que permite que os usuários calibram suas telas para gama 2.2, e essa ferramenta usa o hardware da tabela de pesquisa para derivar um ajuste sutil cuidadosamente escolhido para seus computadores. Os usuários podem executar essa ferramenta pesquisando "calibrar cor". Também há perfis de cores bem definidos para monitores específicos que automatizam esse processo. A ferramenta "calibrar cor" pode detectar esses monitores mais recentes e informar aos usuários que a calibragem já está em vigor.

Essa noção de codificar uma lei de poder em valores de cor também é útil em outros lugares do pipeline gráfico, especialmente em texturas. Para texturas, você quer mais precisão em cores mais escuras devido à resposta logarítmica dos olhos humanos que acabamos de falar. O tratamento cuidadoso de gama nesta parte do pipeline é importante. Para obter mais informações, consulte Convertendo dados para o espaço de cor.

O restante deste tópico se concentra apenas na correção gama nesta última parte do pipeline, entre os dados do buffer de quadro e o monitor. Se você quiser escrever um assistente de calibragem ou criar efeitos especiais em um aplicativo de tela inteira em que uma etapa pós-processamento não é prática, aqui estão as informações necessárias.

Plano de fundo do gama no Windows

Os computadores Windows normalmente têm uma tabela gama que é uma tabela de pesquisa que usa um trigêmeo de bytes e gera um trigêmeo de bytes. Esses trigêmeos são 768 (256 x 3) bytes de RAM. Isso é bom quando o formato de exibição contém um trigêmeo de valores BYTE RGB, mas não é expressivo o suficiente para descrever as transformações que você pode querer quando o formato de exibição tem um intervalo maior que [0,1], como valores de ponto flutuante. As APIs no Windows que controlam gama seguiram uma evolução à medida que os formatos de exibição se tornaram mais complexos.

As primeiras APIs do Windows a oferecer controle gama são SetDeviceGammaRamp e GetDeviceGammaRamp do Windows Graphics Device Interface (GDI). Essas APIs funcionam com três matrizes de 256 entradas de WORDs, com cada word codificando zero até um, representado pelos valores 0 e 65535 do WORD. A precisão extra de um WORD normalmente não está disponível em tabelas de pesquisa de hardware reais, mas essas APIs foram destinadas a serem flexíveis. Essas APIs, ao contrário das outras descritas posteriormente nesta seção, permitem apenas um pequeno desvio de uma função de identidade. Na verdade, qualquer entrada na rampa deve estar dentro de 32768 do valor de identidade. Essa restrição significa que nenhum aplicativo pode transformar a tela completamente preta ou em alguma outra cor ilegível.

A próxima API é SetGammaRamp do Microsoft Direct3D 9, que segue o mesmo padrão e formato de dados que SetDeviceGammaRamp. O valor padrão da rampa gama do Direct3D 9 não é particularmente útil; é uma rampa de WORDs inicializada para 0-255, não 0-65535, embora a API seja definida em termos de 0-65535.

A API mais recente é IDXGIOutput::SetGammaControl. Essa API tem um esquema mais flexível para expressar o controle gama, pois se encaixa no maior conjunto de formatos de exibição do DXGI, incluindo dez bits inteiros por canal, formatos float de 16 bits e o formato de intervalo estendido XR_BIAS.

Todas essas APIs operam no mesmo hardware e alteram os mesmos valores. As APIs Direct3D 9 e DXGI são "somente gravação". Não é possível ler o valor do hardware, modificá-lo e defini-lo. Você só pode definir a rampa. Além disso, você só pode definir gama quando o aplicativo estiver em tela inteira. Essa restrição é outra maneira de garantir que a área de trabalho seja sempre legível. Ou seja, o aplicativo pode perturbar sua própria tela, mas o Windows restaurará a rampa gama anterior quando o aplicativo perder tela inteira (por exemplo, por meio de alt-tab ou ctrl-alt-del).

Evolução do hardware de exibição

Alguns monitores mais recentes podem exibir uma ampla variedade de intensidades. Mas, quando o formato de exibição pode representar apenas valores entre zero e um, a exibição deve mapear zero para seu valor mais escuro e um para seu valor mais brilhante. Esse valor mais brilhante pode ser muito brilhante para visualização confortável de páginas da Web com texto preto em um fundo branco, mas é maravilhoso para efeitos especiais muito brilhantes, como ver a luz solar brilhando de um lago ou um raio bifurcando o céu. Então, precisamos de uma maneira de expressar esses intervalos mais amplos. O DXGI 1.1 e posterior contém valores de formato de exibição que permitem que 1.0 represente um valor branco confortável e reserva valores de formato de exibição mais amplos para efeitos especiais super brilhantes. O DXGI 1.1 dá suporte a dois formatos de exibição que podem expressar esses valores mais amplos: DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM e ponto flutuante de 16 bits. Para obter uma discussão completa sobre esses formatos, consulte Detalhes do formato estendido. Em seguida, veremos por que a API gama IDXGIOutput::SetGammaControl da DXGI precisa de valores de pixel maiores que 1,0.

Recursos de controle gama no DXGI

O DXGI permite que o driver de exibição expresse seus controles gama como uma função linear passo a passo. Essa função linear passo a passo é definida pelos pontos de controle dessa função, pelo intervalo de valores em que a função pode converter e por uma operação opcional adicional de escala e deslocamento que pode ser aplicada após a conversão. Um aplicativo pode chamar o método IDXGIOutput::GetGammaControlCapabilities para recuperar todos esses recursos de controle na estrutura DXGI_GAMMA_CONTROL_CAPABILITIES .

Este grafo mostra uma função linear com apenas quatro pontos de controle.

função linear de correção gama

O DXGI define pontos de controle por sua localização ao longo do eixo de cores da superfície. No grafo anterior, os locais dos pontos de controle são 0, 0,5, 0,75 e 1,0. Esses pontos de controle indicam que o hardware pode converter valores no intervalo de 0 a 1,0. O DXGI lista esses pontos de controle no membro da matriz ControlPointPositions de DXGI_GAMMA_CONTROL_CAPABILITIES e sempre os declara em ordem crescente. O DXGI preenche apenas os primeiros elementos da matriz ControlPointPositions e indica o número de elementos com o membro NumGammaControlPoints de DXGI_GAMMA_CONTROL_CAPABILITIES. Se NumGammaControlPoints for menor que 1025, DXGI deixará o restante dos elementos ControlPointPositions indefinidos.

O hardware representado por esse grafo pode converter valores em um intervalo de 0 a 1,25. Portanto, o DXGI define os membros MinConvertedValue e MaxConvertedValue como 0,0f e 1,25f, respectivamente.

O DXGI define o membro ScaleAndOffsetSupported do DXGI_GAMMA_CONTROL_CAPABILITIES para indicar se o hardware dá suporte à funcionalidade de escala e deslocamento. Se o hardware der suporte a escala e deslocamento, ele manterá uma tabela de pesquisa um-para-um simples, mas ajustará a saída da tabela para ampliar a saída para um intervalo maior que [0,1]. O hardware primeiro dimensiona os valores que saem da tabela de pesquisa e, em seguida, os desloca.

Observação

Monitores diferentes conectados ao mesmo computador podem ter diferentes funcionalidades de controle gama. Além disso, os recursos de controle gama podem de fato mudar dependendo do modo de exibição da saída. Consequentemente, recomendamos que você sempre chame IDXGIOutput::GetGammaControlCapabilities para consultar recursos de controle gama depois que seu aplicativo entrar no modo de tela inteira.

 

Você pode usar esses valores de funcionalidade de controle gama para derivar valores de controle que você pode definir usando a API IDXGIOutput::SetGammaControl .

Configurando o controle gama com DXGI

Para definir controles gama, você passa um ponteiro para uma estrutura DXGI_GAMMA_CONTROL ao chamar a API IDXGIOutput::SetGammaControl .

Defina os membros Escala e Deslocamento de DXGI_GAMMA_CONTROL para especificar os valores de escala e deslocamento que você deseja que o hardware aplique aos valores obtidos da tabela de pesquisa. Você pode definir com segurança Escala como 1 e Deslocamento como zero (ou seja, uma escala por um não tem efeito e um deslocamento de zero não tem efeito) se você não quiser usar a funcionalidade de escala e deslocamento ou se o hardware não tiver essa funcionalidade.

Você define o membro da matriz GammaCurve de DXGI_GAMMA_CONTROL como uma lista de estruturas DXGI_RGB para os pontos na curva gama. Cada elemento DXGI_RGB especifica os valores float que representam os componentes vermelho, verde e azul para esse ponto. A curva gama não usa valores alfa. Use o número obtido de NumGammaControlPoints de DXGI_GAMMA_CONTROL_CAPABILITIES para preencher esse número de elementos na matriz GammaCurve . Cada elemento que você coloca na matriz GammaCurve é a altura de cada ponto de controle.

Observe no grafo anterior que agora você tem controle sobre o posicionamento vertical de cada ponto de controle e tem controle separado para vermelho, verde e azul. Por exemplo, você pode definir todos os valores verde e azul como zero e definir os valores vermelhos como uma escada crescente de zero para um. Nesse cenário, a imagem exibida mostra apenas suas partes vermelhas, com o azul e o verde aparecendo como preto. Você também pode definir uma escada decrescente para todas as cores, o que resulta em uma exibição invertida. Qualquer valor colocado na matriz GammaCurve deve estar incluído nos valores obtidos dos membros MinConvertedValue e MaxConvertedValue de DXGI_GAMMA_CONTROL_CAPABILITIES.

Praticidades de controle gama

Os controles gama do DXGI só se aplicam desde que o aplicativo esteja em tela inteira. O Windows restaura o estado anterior da exibição quando o aplicativo sai ou retorna ao modo em janelas. Mas o Windows não restaurará o estado gama do aplicativo se o aplicativo entrar novamente no modo de tela inteira. Seu aplicativo deve restaurar explicitamente seu estado gama quando ele entra novamente no modo de tela inteira.

Nem todos os adaptadores dão suporte ao controle gama. Se um adaptador não der suporte ao controle gama, ele ignorará as chamadas para definir uma rampa gama.

Os aplicativos executados na área de trabalho remota não podem controlar o gama.

O cursor do mouse, se ele for implementado no hardware (como a maioria está), normalmente não responde à configuração gama.

Guia de programação para DXGI