Considere iluminação adiada. Em resumo, a iluminação diferida é uma técnica que usa uma versão reduzida do sombreamento diferido para calcular um mapa de luz do espaço na tela. Em uma segunda passagem, a geometria é renderizada novamente usando o mapa de luz do espaço na tela como informações de iluminação.
Essa técnica é usada para reduzir o tamanho do G-Buffer, pois menos atributos são necessários. Também oferece a vantagem de que o G-Buffer e o mapa de luz do espaço na tela podem ter uma resolução mais baixa que a tela.
Eu havia implementado um renderizador estrito baseado em GLES 2.0 (embora experimental) e consegui reduzir o G-Buffer até uma textura RGBA (sim, usei um texture2D em vez de um renderbuffer). Ele continha o mapa normal do espaço na tela + o buffer de profundidade no canal alfa (que foi compactado usando um logaritmo, tanto quanto me lembro).
Os atributos de posição (denominados mundo aqui) podem ser calculados durante o passo de iluminação usando o fato de que, em uma projeção prospectiva , .xy é dividido por .z , de modo que:
x yfr u s t u m= x yw o r l d/ zw o r l d
Aproximei o atributo de posição xy fazendo:
x yw o r l d= x yfr u s t u m∗ zw o r l d
Nota: tive que fazer mais ajustes, dependendo das configurações da matriz de projeção.
Também digno de nota é que eu era capaz de omitir o componente .z dos vetores normais, pois eu podia reconstruir .z do .xy, pois o vetor normal é normalizado para que:
x2+ y2+ z2----------√= 1x2+ y2+ z2= 1z2= 1 - ( x2+ y2)z= 1 - ( x2+ y2)-----------√
Usando essa técnica, fui capaz de liberar outro canal no meu RGBA G-Buffer e usei isso para armazenar o mapa especular do espaço da tela (ou brilho, se desejar).