No OpenGL, é uma má idéia “combinar” o modo imediato e o modo retido por causa das GUIs?

8

Suponha que eu tenha uma cena 3D sendo desenhada glDrawArrays(...)e que queira tornar algo simples, como uma sobreposição 2D. Seria uma má idéia usar o modo imediato para isso, em vez de configurar um renderizador 2D com o modo retido?

Exemplo:

void Draw()
{
    // Draw the 3D scene:
    // *does stuff*
    glDrawArrays(...);
    // *some other stuff*

    // Setup a quad with immediate mode (for something like a vignette overlay)
    glBegin(GL_QUADS);
    glTexCoord2f(...); glVertex2f(...);
    glEnd();
}
KK Slider
fonte
Minecraft faz isso. Funciona bem, exceto para limitar sua versão do OpenGL (para <3.1 ou um perfil de compatibilidade) e para tornar sua GUI menos rápida.
user253751
Nota O Minecraft também possui seu próprio conjunto de funções que simulam o modo imediato usando matrizes de vértices - não é difícil escrever. Ainda não tenho certeza se eles os estão usando para a GUI.
user253751

Respostas:

7

É uma péssima idéia, na medida em que não faz sentido. Não há nada para "configurar" que você ainda não tenha feito, exceto uma matriz de projeção orto (que você terá que fazer em qualquer caso).

A portabilidade provavelmente não é um problema, embora deva ser. IHVs parecem ser muito relutantes em perder o suporte para modo imediato para o futuro previsível (parece "bom trabalho" mesmo em perfis de núcleo), portanto, embora modo imediato deveria ter morrido há muito tempo, ele provavelmente vai ficar para sempre. O desempenho é outra história. Deseja realmente que algo que represente 0,1% da complexidade da cena consuma 15 a 20% do tempo da CPU - as chamadas GL são relativamente leves, em comparação com, por exemplo, o DX, mas não são gratuitas - e 15 a 20% tempo de quadro real devido ao bloqueio do pipeline? Você pode pagar isso com seu orçamento de tempo? A maioria dos jogos não pode.

E então, claro, as peculiaridades. Oh, as peculiaridades. A beleza aparente do modo imediato é que é (aparentemente) fácil e direto fazer algo como desenhar dois quadríceps rapidamente. Na realidade, o modo imediato pode ser uma dor na parte traseira, é tão cheio de armadilhas não óbvias.
Por outro lado, é tão fácil (e mais direto, se você me perguntar!) Escrever apenas uma pequena função 5-LOC DrawQuadque, quando chamada, adiciona coordenadas e índices de vértices a um buffer de memória e incrementa um contador. Com surpresa, você pode desenhar glDrawArrays/Elementse reutilizar (a cópia da GPU, não apenas a cópia da terra do usuário!) O próximo quadro, como está, desde que nada seja alterado.
O modo imediato deve, de nenhuma outra maneira, alocar um buffer e fazer uma transferência PCIe sempre. Ou, algo equivalente em latência (GPU lendo a memória principal no barramento, qualquer que seja). O motorista não pode saber (ou assumir) que os dados permaneceram exatamente os mesmos do quadro anterior.

A obtenção de dados na GPU é uma operação de alta velocidade, mas também de alta latência . Não é só a transferência de ônibus per se um complicado protocolo, alta latência (várias camadas de protocolo, empacotamento, agradecimentos, etc.), mas também nem todas as GPUs são mesmo capazes de transferir e desenhar ao mesmo tempo, ou se eles podem fazê-lo , eles podem não ser capazes de alternar o tempo todo ou iniciar novas operações livremente enquanto fazem algo diferente. Leia como: Você não deve transferir em vão .

Damon
fonte
"Não há nada para" configurar "que você ainda não tenha feito" Renderização em lote?
precisa saber é o seguinte
2
Embora os IHVs estejam relutantes em abandonar o modo imediato, também existem drivers de vídeo no Linux que não suportam uma versão superior do OpenGL, a menos que você solicite o Perfil principal. Isso significa, em particular, gráficos Intel HD ( inteldriver), mas também chips NVidia e AMD ao usar drivers de código aberto ( nouveaue amdgpurespectivamente). Da mesma forma, no MacOS você também não possui um Perfil de Compatibilidade com o OpenGL> 2.1.
Ruslan
@HolyBlackCat: Não sei o que você quer dizer? O OP declara ter um pipeline 3D funcional baseado em glDrawArrays. Portanto, há tudo o que é necessário para fazer outra chamada glDrawElements(ou matriz, o que for) para desenhar todos os quadríceps da GUI (depois de gravar os vértices em um buffer). As funções são carregadas, você tem uma estrutura para alocar buffers, etc. Nada de especial para fazer em lotes da GUI, realmente. Apenas vincule (ou não, se você tiver TUs suficientes para deixá-lo vinculado) a textura da GUI, defina a matriz orto e faça uma chamada de desenho adicional. Como você deseja melhorar o lote?
Damon
(É claro que concordo que o modo imediato é ruim.) Desculpe se não estava claro. Refiro-me ao processo de preenchimento do referido buffer de vértice. Isso é fácil, mas é um pouco mais trabalhoso do que usar o modo imediato.
precisa saber é o seguinte
12

Pessoalmente, só vejo isso como ruim por duas razões:

  1. É muito desatualizado e obsoleto. E,
  2. É muito mais lento que as formas modernas de desenhar com o OpenGL.

Mas, se estiver funcionando, e o desempenho não for um problema, e se não for um problema para você usar funções obsoletas do OpenGL em seu programa, acredito que você poderia fazê-lo. Será mais lento o número de Toneladas e Toneladas de GUIs, mas se não forem tantas, novamente, faça isso.

Entenda isso, no entanto. Que, no final das contas, o OpenGL está fazendo a mesma coisa; desenho para a tela. O modo imediato é muito mais lento se você tiver muitas coisas sendo processadas. Portanto, você deve escolher o que é mais útil para a tarefa que tem em mente. Espero que isto te ajude!

dev9999
fonte
1

Outra desvantagem é que isso torna seu código menos portátil. Certas variantes do OpenGL não suportam o modo imediato, por exemplo, o OpenGL ES. (e, à medida que dispositivos baseados em Android de maior calibre, como tablets, ganham mais força, isso pode se tornar importante)

Nome em Exibição
fonte
0

Usar o modo imediato é completamente desnecessário para trabalhos relacionados à GUI.

Para criar um item simples da GUI, digamos, um botão:

  1. Você precisa de uma malha de tira quad / triângulo,
  2. Uma textura para a malha
  3. Uma transformação de projeção ortográfica

Dessa forma, você pode simplesmente escrever um sombreador de passagem simples que ignore as considerações de iluminação e apenas escalar o item da GUI para uma escala de pixels ou alguma porcentagem da janela e, em seguida, executar um algoritmo de pintores para renderização.

Dessa forma, você pode fazer um sistema de interface do usuário completo com todos os benefícios de desempenho do modo retido.

Ian Young
fonte