我今天刚开始从本教程开始学习OpenGL:http://openglbook.com/the-book/
我到了第2章,在那里画了一个三角形,我理解除了VAO之外的一切(这个首字母缩略词好吗?).本教程有以下代码:
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
Run Code Online (Sandbox Code Playgroud)
虽然我知道代码是必要的,但我不知道它的作用.虽然我从不使用VaoId(除了销毁它),但如果没有它,代码就无法运行.我假设这是因为它需要被绑定,但我不知道为什么.这个确切的代码是否只需要成为每个OpenGL程序的一部分?该教程将VAO解释为:
顶点数组对象(或VAO)是描述顶点属性如何存储在顶点缓冲区对象(或VBO)中的对象.这意味着VAO不是存储顶点数据的实际对象,而是顶点数据的描述符.顶点属性可以通过glVertexAttribPointer函数及其两个姐妹函数glVertexAttribIPointer和glVertexAttribLPointer来描述,我们将在下面探讨其中的第一个.
我不明白VAO如何描述顶点属性.我没有以任何方式描述它们.它是否从glVertexAttribPointer获取信息?我想这一定是它.VAO只是glVertexAttribPointer信息的目的地吗?
另外,我遵循的教程是否可以接受?有什么我应该注意的或更好的教程可以遵循?
我面临一个问题,我相信是VAO依赖的,但我不确定..
我不确定VAO的正确用法,我在GL初始化期间做的事情很简单
glGenVertexArrays(1,&vao)
Run Code Online (Sandbox Code Playgroud)
接下来是
glBindVertexArray(vao)
Run Code Online (Sandbox Code Playgroud)
后来,在我的绘图管道中,我只调用glBindBuffer(),glVertexAttribPointer(),glEnableVertexAttribArray()等等,而不关心初始绑定的VAO
这是正确的做法吗?
我试图理解这两个,如何使用它们以及它们是如何相关的.假设我想创建一个简单的地形和一个纹理立方体.对于这两个对象,我有三角形顶点的数组,对于立方体,我有一个包含纹理数据的数组.我的问题是:如何使用VAO和VBO来创建和渲染这两个?
有许多教程和书籍,但我仍然不知道如何理解和使用这些概念.
我正在编写一个OpenGL3 +应用程序,并且对VAO的使用感到困惑.现在我只有一个VAO,一个围绕原点的标准化四边形集.这个单一的VAO包含3个VBO; 一个用于位置,一个用于表面法线,一个GL_ELEMENT_ARRAY_BUFFER用于索引(因此我只能存储4个顶点,而不是6个).
我已经设置了一些辅助方法来将对象绘制到场景中,例如drawCube()获取位置和旋转值并遵循该过程;
uniform mat4 model顶点着色器变量.glDrawElements()将四边形绘制到此面部的位置.我刚刚开始添加每个立方体颜色的任务,并意识到我不能将我的颜色VBO添加到单个VAO中,因为它会随着每个立方体而改变,这感觉不对.
我刚读过这个问题; OpenGL VAO最佳实践,告诉我我的方法是错误的,并且我应该使用更多的VAO来保存每次设置整个场景的工作.
应该使用多少个VAO?显然,如果场景中的每个静态表面都有VAO,那么我的1的方法并不是最优的吗?移动的是什么?
我正在为每个顶点写一个统一变量,这是正确的吗?我读到uniform着色器变量不应该改变中间帧,如果我能够为我的uniform变量写入不同的值,那么制服与in顶点着色器中的简单变量有何不同?
我有以下代码,只需在屏幕上绘制一个绿色三角形.它使用顶点数组对象和索引缓冲区绘制,并具有我可以制作的最简单的着色器.
起初我没有使用索引缓冲区,只是简单地进行绘制调用,glDrawArrays但是当我将其更改为使用时glDrawElements,屏幕上没有任何内容(它完全是黑色).
from OpenGL.GL import shaders
from OpenGL.arrays import vbo
from OpenGL.GL import *
from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, \
glBindVertexArray
import pygame
import numpy as np
def run():
pygame.init()
screen = pygame.display.set_mode((800,600), pygame.OPENGL)
#Create the Vertex Array Object
vertexArrayObject = GLuint(0)
glGenVertexArrays(1, vertexArrayObject)
glBindVertexArray(vertexArrayObject)
#Create the VBO
vertices = np.array([[0,1,0],[-1,-1,0],[1,-1,0]], dtype='f')
vertexPositions = vbo.VBO(vertices)
#Create the index buffer object
indices = np.array([0,1,2], dtype='uint16')
indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)
indexPositions.bind()
vertexPositions.bind()
glEnableVertexAttribArray(0) # from 'location = 0' in …Run Code Online (Sandbox Code Playgroud) 我试图围绕如何适当地使用VAO进行实例化渲染(特别是在Qt 5.2中,使用OpenGL 3.3).我的理解是VAO保存了VBO和相关属性的状态,这样您就不必担心在绘图时绑定和启用所有内容,只需绑定VAO即可.但是通过实例化,您经常会有多个VBO.你如何解决所有需要绑定它们的问题?或者我只需要为每个顶点数据和每个实例数据使用一个VBO?
我一直在看几个教程,例如:http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html
在我看来,他所做的就是使用VAO作为他的每个顶点数据而不是他的每个实例数据.我尝试用基于Qt的代码做同样的事情,它对我不起作用(可能是因为我不完全理解它是如何工作的......当绘图发生时,他的实例数据是否仍然需要绑定?)
一些虚拟代码...这有点傻,我只是绘制一个两个三角形的实例,透视矩阵作为每个实例属性.
glwindow.cpp:
#include "glwindow.h"
#include <QColor>
#include <QMatrix4x4>
#include <QVector>
#include <QVector3D>
#include <QVector4D>
#include <QDebug>
GLWindow::GLWindow(QWindow *parent)
: QWindow(parent)
, _vbo(QOpenGLBuffer::VertexBuffer)
, _matbo(QOpenGLBuffer::VertexBuffer)
, _context(0)
{
setSurfaceType(QWindow::OpenGLSurface);
}
GLWindow::~GLWindow()
{}
void GLWindow::initGL()
{
setupShaders();
_program->bind();
_positionAttr = _program->attributeLocation("position");
_colourAttr = _program->attributeLocation("colour");
_matrixAttr = _program->attributeLocation("matrix");
QVector<QVector3D> triangles;
triangles << QVector3D(-0.5, 0.5, 1) << QVector3D(-0.5, -0.5, 1) << QVector3D(0.5, -0.5, 1);
triangles << QVector3D(0.5, 0.5, 0.5) << QVector3D(-0.5, -0.5, 0.5) << QVector3D(0.5, -0.5, …Run Code Online (Sandbox Code Playgroud) 问题1
删除VAO后,在某个VAO下创建的顶点缓冲区对象是否已删除?
一个例子:
glGenBuffers(1, &bufferObject);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(someVertices), someVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(positionAttrib);
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, NULL);
Run Code Online (Sandbox Code Playgroud)
以后打电话时glDeleteVertexArrays(1, &VAO);,会bufferObject被删除吗?
我问的原因是我在网上看到了一些没有删除那些缓冲区对象的例子.
问题2
我可以为缓冲区对象分配的最大内存量是多少?它当然必须是系统依赖的,但我似乎无法找到它的估计.当视频RAM不够大时会发生什么?我怎么会知道?
假设我使用新的(从OpenGL 4.3开始)glBindVertexBuffer机制设置了两个VAO:
glGenVertexArrays(1, &vaoIndex0);
glGenVertexArrays(1, &vaoIndex1);
Run Code Online (Sandbox Code Playgroud)
...
glBindVertexArray(vaoIndex0)
glBindVertexBuffer(bindingIndex0, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex0)
...
glBindVertexArray(0)
Run Code Online (Sandbox Code Playgroud)
...
glBindVertexArray(vaoIndex1)
glBindVertexBuffer(bindingIndex1, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex1)
...
glBindVertexArray(0)
Run Code Online (Sandbox Code Playgroud)
并且假设两者是独立的,除非它们存在于相同的OpenGL上下文中; 它们绑定不同的缓冲区,用于绘制不同的东西.
bindingIndex0需要与bindingIndex1不同吗?两个指数的平等(或不平等)是否有任何意义?
...
编辑:
在收到答案后,我开始明白,对于一个真正知道"顶点缓冲区绑定点"是什么的人,特别是它的范围是什么,我的问题似乎是在问一些与我的意图不同的东西.也许一个更好的措辞就是" 为了防止冲突,是否需要尽力避免重复使用OpenGL顶点缓冲区绑定点索引,甚至跨多个VAO?" 但无论如何,似乎现在已经回答了这两个问题:不,你不能重复使用"绑定点",并且不需要以这种方式避免索引冲突.
我需要帮助来看看他们之间的权衡.
glDrawElements()需要将索引数据"实时"作为参数.glDrawArrays().有没有办法结合优势?我们也可以缓冲索引数据吗?
如何在顶点着色器中看到它?它可以使用索引并在顶点位置数组中查找吗?
我在LWJGL / OpenGL 3中验证我的着色器程序时遇到问题。
我阅读了文档,但似乎找不到调用glValidateProgram时需要VAO的原因。
int program = glCreateProgram();
int vertexShader = glCreateShader(...);
int fragmentShader = glCreateShader(...);
// ... vertex and fragment shader loading, compiling, errorchecking ...
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
glDetachShader(program, shader);
glDetachShader(program, shader);
glValidateProgram(program);
if (glGetProgrami(program, GL_VALIDATE_STATUS) != GL_TRUE)
System.exit(-1);
Run Code Online (Sandbox Code Playgroud)
这将退出程序,而不会出现任何错误消息。
GL_LINK_STATUS可以,并且GL.getErrors()也没有要报告的内容。
但是,在glValidateProgram周围创建VAO时,效果很好。
我还可以忽略glGetProgrami返回GL_FALSE并仅运行着色器程序这一事实。
我围绕glValidateProgram()创建VAO的意思是:
int vao = glGenVertexArrays();
glBindVertexArray(vao);
glValidateProgram(program);
if (glGetProgrami(program, GL_VALIDATE_STATUS) != GL_TRUE)
System.exit(-1);
glDeleteVertexArrays(vao);
Run Code Online (Sandbox Code Playgroud)
当我这样做时,GL_VALIDATE_STATUS为true,我可以画画了。
使用的着色器是简单的直通着色器。
顶点着色器返回位置,片段着色器返回颜色。
那么,为什么我必须绑定VAO,即使我可以在验证后立即将其删除?