Quando leio o doc no webGL ou OpenGL, podemos observar alguns padrões de como os nomes de funções e objetos são usados. Mas não consigo entender a diferença entre objeto de buffer e uma matriz.
Existem "objetos de buffer de vértice", "objetos de matriz de vértice" e até algum tipo de "matriz de buffer" ou "buffer de matriz".
No contexto do OpenGL, quando algo é "array" e quando deve ser chamado de "buffer"?
char* buffer = socketRead();
(pseudocódigo). O log, por outro lado, dura todo o ciclo de vida do aplicativo. Então, você cria uma matriz em algum lugar e começa a ler o soquete, sempre que obtém dados que gravam essa parte na matriz, fornecendo uma lista clara de todos os dados recebidos.Respostas:
A nomeação de Vertex Array Object é um tanto infeliz. Existem três coisas diferentes que aparecem (costumavam aparecer) em / com / em torno de seu aplicativo e que são (foram, historicamente) nomeadas de maneira diferente, com "matriz" ou "buffer" no nome (bem, também há objetos framebuffer, mas eu vou ignorar isso).
A intenção disso era tornar o acesso mais eficiente, já que o OpenGL podia copiar tudo de uma só vez, em um momento bem definido, quando você prometia que os dados eram consistentes e enviá-los pelo AGP ou qualquer outro bloco. Isso não existe mais.
O OpenGL pode mover esses dados mais ou menos livremente, e você só pode / pode copiar de / para o buffer através da API correspondente ou acessar os dados enquanto estão sendo mapeados. Isso é o que você chama de objeto de buffer ( objeto de buffer de vértice, se ele contiver vértices, mas realmente não precisa, também pode ser dados de imagem ou uniformes, apenas os vértices foram os primeiros a serem suportados, uma vez).
A intenção disso é garantir que o OpenGL possa (em princípio) fazer o que quiser, pode até empurrar o buffer sobre o PCIe especulativamente antes mesmo de desenhar. Isso funciona porque você não possui os dados (o OpenGL possui!) E só pode acessá-los através da API especificada; portanto, é sabido sempre que os dados são válidos. O driver pode até optar por jogar fora a memória buffer na placa gráfica quando precisar de memória para algo diferente e depois restaurá-la de sua cópia secreta quando necessário.
Agora, a intenção do objeto de matriz de vértices é reduzir o número de chamadas de API e o número de verificações de consistência que o OpenGL deve fazer internamente e, é claro, usar o hardware como ele funciona. Se você vincular 5 buffers, cada um deverá passar por algumas verificações possivelmente caras, e cada um deles será candidato a falhas de cache no driver, além de que cada um deles precisará se comunicar com a placa gráfica para alterar um descritor, etc. Para vincular um VAO, o driver pode (geralmente) simplesmente alternar o descritor definido na placa de vídeo e pronto.
fonte
(puxado de khronos )
Cada buffer tende a constituir um atributo de uma matriz de vértices (objeto). Um VAO pode conter muitos atributos de vértice (por exemplo, posição, cor, UV). Cada um pode ser mantido em seu próprio buffer, em que buffer indica uma série não formatada de bytes contíguos e onde você precisa especificar explicitamente o tamanho (tipo) por elemento de buffer para as chamadas OpenGL do lado da CPU e para o sombreamento do lado da GPU.
Essa é uma maneira. As outras maneiras pelas quais isso pode funcionar são:
O diagrama abaixo ilustra esses dois últimos casos.
Conclusão: se a frase "matriz de vértices" for usada não qualificada no OpenGL, você poderá assumir que significa VAO, que, em um contexto OpenGL (especificamente), é uma coisa muito diferente de um buffer.
EDIT re seu comentário:
GL_ARRAY_BUFFER
indica uma intenção de usar esse objeto de buffer para dados de atributo de vértice, conforme descrito acima. Isso ocorre porque os buffers não são usados apenas para atributos de vértice. No entanto, como é o caso de uso mais comum e você está perguntando sobre os VAOs, não vou entrar nos outros; aqui, no entanto, há uma lista dos outros tipos de buffers que podem ser configurados.fonte
struct
tipo primitivo ou . Os dados podem ser intercalados ou completamente uniformes, por buffer. Você pode indexá-los, assim como em uma matriz C tradicional na CPU. Matriz objetos (usar esta terminologia correta ou acabar confundindo-se!) ... (continua abaixo)Essa terminologia está enraizada na história do OpenGL. O que é importante lembrar é que, para a maioria das versões GL relevantes aqui, o OpenGL foi desenvolvido de forma incremental e adicionando novas funcionalidades a uma API já existente, em vez de alterá-la.
A primeira versão do OpenGL não possuía nenhum desses tipos de objetos. O desenho foi conseguido através da emissão de várias chamadas glBegin / glEnd, e um problema com esse modelo era que ele era muito ineficiente em termos de sobrecarga de chamada de função.
O OpenGL 1.1 deu os primeiros passos para resolver isso, introduzindo matrizes de vértices. Em vez de especificar diretamente os dados dos vértices, você agora pode obtê-los de matrizes C / C ++ - daí o nome. Portanto, uma matriz de vértices é exatamente isso - uma matriz de vértices e o estado GL necessário para especificá-los.
A próxima grande evolução veio com o GL 1.5 e permitiu armazenar dados da matriz de vértices na memória da GPU, em vez da memória do sistema ("lado do cliente"). Um ponto fraco da especificação da matriz de vértices GL 1.1 era que o conjunto completo de dados de vértices precisava ser transferido para a GPU toda vez que você queria usá-los; se já estivesse na GPU, essa transferência poderia ser evitada e possíveis ganhos de desempenho.
Portanto, um novo tipo de objeto GL foi criado para permitir o armazenamento desses dados na GPU. Assim como um objeto de textura é usado para armazenar dados de textura, um objeto de buffer de vértice armazena dados de vértice. Este é realmente apenas um caso especial de um tipo de objeto de buffer mais geral que pode armazenar dados não específicos.
A API para usar objetos de buffer de vértice era suportada por piggy na API de matrizes de vértice já existente, e é por isso que você vê coisas estranhas como converter deslocamentos de bytes em ponteiros nela. Portanto, agora temos uma API de matrizes de vértices que apenas armazena estado, com os dados sendo originados de objetos de buffer em vez de matrizes na memória.
Isso nos leva quase ao fim de nossa história. A API resultante era bastante detalhada quando se tratava de especificar o estado da matriz de vértices; portanto, outro caminho de otimização era criar um novo tipo de objeto que coletasse todo esse estado, permitisse várias alterações de estado da matriz de vértices em uma única chamada de API e permitisse GPUs potencialmente realizar otimizações devido à capacidade de saber qual estado seria usado com antecedência.
Digite o objeto da matriz de vértices, que coleta tudo isso junto.
Então, para resumir, uma matriz de vértices começou a vida como uma coleção de estado e dados (armazenados em uma matriz) para serem desenhados. Um buffer de vértice substitui o armazenamento da matriz na memória por um tipo de objeto GL, deixando a matriz de vértice apenas no estado. Um objeto de matriz de vértice é apenas um objeto de contêiner para esse estado, permitindo que ele seja alterado mais facilmente e com menos chamadas de API.
fonte
Eu não trabalho com o OpenGL há algum tempo, então só posso estar meio certo. De um modo geral: os buffers armazenam uma matriz de memória não formatada. Uma matriz é um termo geral de memória contígua.
Um buffer precisa estar vinculado ao contexto, enquanto uma matriz é apenas uma matriz de dados. Se bem me lembro, os dados no buffer devem ser copiados para a placa gráfica (daí a ligação).
Espero que isso ajude um pouco
fonte