Eu perguntei isso no StackOverflow , mas pode fazer mais sentido aqui:
Alguém implementou renderização / sombreamento diferido no OpenGL ES 2.0? Ele não suporta MRTs; portanto, com apenas um buffer de cores, não é algo que possa ser implementado da maneira "usual".
Especificamente, estou explorando no iPad, iPhone4 (iPhone 3GS) e Android. No aplicativo GLESView no iPad / iPhone4 / iPhone3gs, a extensão GL_OES_RGB8_RGBA8 está presente e eu ainda não olhei muito profundamente, mas com 8bits / canal, essa ideia é interessante: http://www.gamedev.net/topic/ 562138-opengl-es-20-e-adiado-sombreado /
Alguma outra ideia? Vale a pena fazer, em termos de desempenho?
android
ios
opengl-es2
Jim Buck
fonte
fonte
Respostas:
Sim, é possível. No entanto, não vale particularmente a pena.
Primeiro, a menos que você tenha acesso à extensão NV_draw_buffers (como o nome indica, ela é apenas da NVIDIA. Portanto, a menos que você esteja executando o Tegra, você não o possui), os objetos framebuffer no ES 2.0 podem renderizar apenas uma imagem de uma vez. Portanto, para gerar seus buffers G, você precisará renderizar sua cena várias vezes, tirando assim uma das vantagens da renderização adiada.
Segundo, a largura de banda nas plataformas móveis não é a mesma que você obteria nas GPUs de nível médio. E a largura de banda é fundamental para que a renderização diferida (para muitas luzes) valha a pena. Sem essa largura de banda, as passagens de luz realmente vão doer, em termos de desempenho.
Terceiro, o hardware PowerVR realmente não foi projetado para esse tipo de coisa. Otimiza a renderização com seu hardware de renderização baseado em blocos. Uma renderização tão adiada além disso seria menos útil do que em uma arquitetura tradicional de conversão de varredura.
fonte
O principal problema é a taxa de preenchimento. Em GPUs para dispositivos móveis, a taxa de preenchimento é baixa, e você não pode fazer sombreamento adiado em tempo real com resolução nativa.
No iPhone 4 e iPad 1, a taxa de preenchimento é ridícula. O único dispositivo IOS com boa taxa de preenchimento é o iPad 2, mas duvido que seja suficiente ... No Android, apenas os dispositivos Tegra têm o GL_NV_draw_buffers para usar o MRT, mas a taxa de preenchimento também é muito baixa. O Mali 400 parece ter a melhor taxa de preenchimento. Se você quiser chorar, tente preencher um retângulo de cores em resolução de tela cheia 4 vezes ... Muitos dispositivos não conseguem fazer 60 fps.
Nas GPUs de desktop, você tem 10 vezes (ou mais) a taxa de preenchimento como gpus móvel. Não esqueça que as GPUs móveis usam a mesma memória que a CPU e você não tem memória dedicada.
Existem alguns exemplos no WebGL (mesma API), portanto isso não é uma limitação da API.
fonte
Você realmente precisa considerar qual é o mínimo absoluto necessário para um renderizador diferido. Se você voltar para a iluminação diferida, reduz a quantidade de dados que precisam ser armazenados no GBuffer, e é realmente muito mais barato do que renderizar metade da cena 3 vezes ou mais para suportar uma quantidade baixa de luzes.
Eu usaria o seguinte formato GBuffer:
A iluminação diferida é semelhante à renderização diferida, exceto que você renderiza a cena duas vezes:
Sobre como armazenar os resultados da iluminação. Apreciei o armazenamento de cores difusas e luminância especular, para que o buffer de acumulação precise apenas ser uma textura de cor padrão de 32 bits. Você pode estimar a cor especular calculando o croma de cor difusa e combinando-o com a luminância especular.
A parte mais importante, porém, será usar o buffer de estêncil de profundidade ao máximo, para garantir que você não processe nenhum código de iluminação onde ele não é necessário. Eu chegaria ao ponto de adicionar algumas declarações de descarte aos sombreadores de fragmentos em termos que reduziriam a visibilidade da luz abaixo do intervalo de exibição do dispositivo (1e-3 é geralmente um corte seguro).
fonte
discard
é muito, muito ruim para pipelines baseados em blocos que muitas / a maioria das GPUs móveis usa.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:
Aproximei o atributo de posição xy fazendo:
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:
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).
fonte
Sim, é absolutamente possível. A taxa de preenchimento não é um problema porque os chips gráficos móveis são projetados para lidar com telas de resolução muito alta. De fato, a renderização adiada ajuda nisso, porque seu cálculo de iluminação é independente da complexidade da cena; portanto, o excesso não causa lentidão. Aqui está minha implementação em um iPad de quarta geração: http://www.youtube.com/watch?v=K4X1oF6b4V8
Se você deseja quatro vezes o desempenho, apenas metade da resolução da textura para a qual você renderiza. Realmente não consigo ver nada diferente com gráficos 3D em uma tela de retina.
Os chips gráficos para dispositivos móveis são extremamente bons na renderização diferida devido à maneira como lidam com a renderização na textura. Diferentemente das placas gráficas de PC, que normalmente sofrem um grande impacto no desempenho quando você começa a renderizar em uma textura em vez de em um contexto de janela, os gráficos móveis são projetados para fazer isso sem impacto no desempenho. Assim, você obtém a escalabilidade de um renderizador diferido, sem a penalidade de desempenho inicial que você experimenta em uma placa gráfica de desktop.
No momento da minha implementação, o OpenGLES estava ausente na renderização para vários destinos, então tive que desenhar a cor da tela e o normal em passagens separadas. Isso pode ser corrigido nas versões mais recentes do OpenGLES, mas não sabemos se as soluções ainda estão disponíveis no hardware móvel do consumidor.
fonte