Estou escrevendo um aplicativo que processa uma ilha aleatória plantada com árvores. As árvores são atualmente dois quadriláteros, cruzados e desenhados com texturas. Planejo ter malhas mais complexas que formem diferentes tipos de plantas, como palmeiras, carvalhos, gramíneas etc.
O problema que enfrento é que, como as texturas são transparentes, preciso desenhá-las de trás para frente. O plano-b é usar o descarte no frag shader, mas a ordem z fornece melhores resultados:
uniform float uTreeAlpha;
uniform sampler2D uTexture;
varying vec2 vTexCoordOut;
void main (void)
{
vec4 colour = texture2D(uTexture, vTexCoordOut);
if (colour.a < 0.1) {
discard;
}
gl_FragColor = vec4(colour.rgb, colour.a * uTreeAlpha);
}
O segundo problema é que a ordem muda dependendo da câmera e da aparência. Não conheço uma maneira eficiente de desenhá-las no OpenGL em uma única chamada.
Atualmente, meu código de renderização se parece com este pseudocódigo:
if cameraChangedFromLastTime() then
sortTreesBackToFront();
end
for i = 0 to trees.size() -1
drawTree()
end
Onde todo drawTree () define alguns uniformes, define a textura e chama glDrawArrays (). Eu tenho algumas otimizações para pular a configuração de uma textura ou atualizar as cordas de textura, se a última árvore e a corrente forem iguais, e definir alguns uniformes comuns fora do loop e pular árvores que estão muito distantes, mas basicamente se eu tiver 3000 árvores I ir 3000 vezes ao redor do loop.
Desenhar cada árvore individualmente é o assassino de desempenho. Se eu pudesse desenhá-los em uma única chamada ou em lotes (preservando a ordem Z), provavelmente o faria em 1/10 do tempo.
Então, como eu faria isso. Lembre-se de que minhas árvores são espaços reservados e, eventualmente, eu teria:
- Malhas diferentes para árvores diferentes
- Diferentes escalas e ângulos para as árvores para dar um pouco mais de variedade
- Texturas diferentes para árvores diferentes, potencialmente várias texturas aplicadas a uma malha (por exemplo, deixa uma textura, tromba outra)
- As árvores são todas misturadas, portanto, não há maneira simples de desenhar um tipo e depois outro
- Alguma forma de animação cíclica simples (galhos balançando ao vento)
- Todas as texturas residiriam em um único atlas
Então, qual é a melhor abordagem aqui? É possível renderizar em uma única passagem? Se eu usasse glDrawElements, reconstruindo os índices, mas não os vértices, conseguiria isso?
fonte
Respostas:
O que você quer é instanciamento de hardware . Nota: Fiz isso no XNA (DirectX), mas não sei muito sobre o OpenGL. Estou certo de que existe um recurso comparável. Basicamente, o que isso significa é vincular os vértices do seu modelo de árvore a outro fluxo de vértices que carrega coordenadas mundiais para cada instância.
fonte
A transparência só precisa ser solicitada se usar mistura não aditiva. Para uma tonelada de outdoors distantes, a mistura é desnecessária (você realmente não pode vê-lo). Renderize pelo menos os outros com transparência de recorte (alfa de apenas 1 ou 0) e não será necessário classificá-los.
Você pode usar uma espécie de folha de sprite para renderizar diferentes tipos de árvores, com animações criadas. Desenhe malhas para árvores mais próximas, que você pode animar com mais fidelidade com base nos ventos ou o que quiser.
fonte