gpt4 book ai didi

qt - 如何在 Qt 5 中使用带有实例化的 VAO

转载 作者:行者123 更新时间:2023-12-03 14:45:43 27 4
gpt4 key购买 nike

我试图围绕如何正确使用 VAO 进行实例渲染(特别是在 Qt 5.2 中,使用 OpenGL 3.3)。我的理解是,VAO 保存了 VBO 的状态和相关属性,这样您就不必担心在绘图时绑定(bind)和启用所有内容,您只需绑定(bind) VAO。但是通过实例化,您通常会有多个 VBO。你如何绕过需要绑定(bind)它们?还是我只需要为每个顶点数据和每个实例数据都使用一个 VBO?

我一直在看一些教程,例如:http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html

在我看来,他所做的是对每个顶点数据使用 VAO,而不是对每个实例数据使用 VAO。我试过用我的基于 Qt 的代码做同样的事情,但它对我不起作用(可能是因为我不完全理解它是如何工作的......当绘制发生时他的实例数据是否仍然需要绑定(bind)? ?)

一些虚拟代码......这有点傻,我只是在绘制两个三角形的单个实例,并将透视矩阵作为每个实例的属性。

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, 0.5);

QVector<QVector3D> colours;
colours << QVector3D(1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, 1);
colours << QVector3D(1, 1, 1) << QVector3D(1, 1, 1) << QVector3D(1, 1, 1);

_vao.create();
_vao.bind();

_vbo.create();
_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
_vbo.bind();

size_t positionSize = triangles.size() * sizeof(QVector3D);
size_t colourSize = colours.size() * sizeof(QVector3D);
_vbo.allocate(positionSize + colourSize);
_vbo.bind();
_vbo.write(0, triangles.constData(), positionSize);
_vbo.write(positionSize, colours.constData(), colourSize);
_colourOffset = positionSize;

_program->setAttributeBuffer(_positionAttr, GL_FLOAT, 0, 3, 0);
_program->setAttributeBuffer(_colourAttr, GL_FLOAT, _colourOffset, 3, 0);

_program->enableAttributeArray(_positionAttr);
_program->enableAttributeArray(_colourAttr);

_vao.release();

_matbo.create();
_matbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
_matbo.bind();

_matbo.allocate(4 * sizeof(QVector4D));
_program->setAttributeBuffer(_matrixAttr, GL_FLOAT, 0, 4, 4 * sizeof(QVector4D));
_program->enableAttributeArray(_matrixAttr);

_func330->glVertexAttribDivisor(_matrixAttr, 1);
_matbo.release();

_program->release();
resizeGL(width(), height());
}

void GLWindow::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}

void GLWindow::paintGL()
{
if (! _context) // not yet initialized
return;

_context->makeCurrent(this);
QColor background(Qt::black);

glClearColor(background.redF(), background.greenF(), background.blueF(), 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -2);

_program->bind();

_matbo.bind();
_matbo.write(0, matrix.constData(), 4 * sizeof(QVector4D));

_vao.bind();

glEnable(GL_DEPTH_TEST);
_func330->glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);

_vao.release();

_program->release();

_context->swapBuffers(this);
_context->doneCurrent();

}

void GLWindow::setupShaders()
{

QString vShaderSrc("#version 330\n"
"layout(location = 0) in vec4 position;\n"
"layout(location = 1) in vec4 colour;\n"
"layout(location = 2) in mat4 matrix;\n"
"smooth out vec4 col;\n"
"void main() {\n"
" col = colour;\n"
" gl_Position = matrix * position;\n"
"}\n");

QString fShaderSrc("#version 330\n"
"smooth in vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n");


_program = new QOpenGLShaderProgram(this);
_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vShaderSrc);
_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fShaderSrc);
_program->link();


}

void GLWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);

if (isExposed())
{
if (! _context)
{
_context = new QOpenGLContext(this);
QSurfaceFormat format(requestedFormat());
format.setVersion(3,3);
format.setDepthBufferSize(24);

_context->setFormat(format);
_context->create();

_context->makeCurrent(this);
initializeOpenGLFunctions();

_func330 = _context->versionFunctions<QOpenGLFunctions_3_3_Core>();
if (_func330)
_func330->initializeOpenGLFunctions();
else
{
qWarning() << "Could not obtain required OpenGL context version";
exit(1);
}

initGL();
}

paintGL();
}
}

glwindow.h:
#ifndef GL_WINDOW_H
#define GL_WINDOW_H

#include <QExposeEvent>
#include <QSurfaceFormat>
#include <QWindow>

#include <QOpenGLBuffer>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>


class GLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
GLWindow(QWindow * = 0);
virtual ~GLWindow();

void initGL();
void paintGL();
void resizeGL(int, int);

protected:
virtual void exposeEvent(QExposeEvent *);


private:

void setupShaders();

QOpenGLBuffer _vbo;
QOpenGLBuffer _matbo;
QOpenGLContext *_context;
QOpenGLShaderProgram *_program;
QOpenGLVertexArrayObject _vao;
QOpenGLFunctions_3_3_Core *_func330;

GLuint _positionAttr;
GLuint _colourAttr;
GLuint _matrixAttr;

size_t _colourOffset;

} ;

#endif

glbuffertest.cpp:
#include <QGuiApplication>
#include <QSurfaceFormat>

#include "glwindow.h"



int main(int argc, char **argv)
{

QGuiApplication app(argc, argv);

GLWindow window;
window.resize(400, 400);
window.show();

return app.exec();

}

glbuffertest.pro:
######################################################################
# Automatically generated by qmake (3.0) Fri May 16 09:49:41 2014
######################################################################

TEMPLATE = app
TARGET = glbuffertest
INCLUDEPATH += .

CONFIG += qt debug

# Input
SOURCES += glbuffertest.cpp glwindow.cpp
HEADERS += glwindow.h

更新:
我试过摆脱我的 _matbo缓冲区,而是将矩阵数据放入与位置和颜色属性相同的 VBO 中,但这对我不起作用。我的 initGL函数现在看起来像:
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, 0.5);

QVector<QVector3D> colours;
colours << QVector3D(1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, 1);
colours << QVector3D(1, 1, 1) << QVector3D(1, 1, 1) << QVector3D(1, 1, 1);

_vao.create();
_vao.bind();

_vbo.create();
_vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
_vbo.bind();

size_t positionSize = triangles.size() * sizeof(QVector3D);
size_t colourSize = colours.size() * sizeof(QVector3D);
size_t matrixSize = 4 * sizeof(QVector4D);
_vbo.allocate(positionSize + colourSize + matrixSize);
_vbo.bind();
_vbo.write(0, triangles.constData(), positionSize);
_vbo.write(positionSize, colours.constData(), colourSize);


_colourOffset = positionSize;
_matrixOffset = positionSize + colourSize;

_program->setAttributeBuffer(_positionAttr, GL_FLOAT, 0, 3, 0);
_program->setAttributeBuffer(_colourAttr, GL_FLOAT, _colourOffset, 3, 0);
_program->setAttributeBuffer(_matrixAttr, GL_FLOAT, _matrixOffset, 4, 4 * sizeof(QVector4D));

_program->enableAttributeArray(_positionAttr);
_program->enableAttributeArray(_colourAttr);
_program->enableAttributeArray(_matrixAttr);
_func330->glVertexAttribDivisor(_matrixAttr, 1);

_vao.release();

_program->release();
resizeGL(width(), height());
}

paintGL :
void GLWindow::paintGL()
{
if (! _context) // not yet initialized
return;

_context->makeCurrent(this);
QColor background(Qt::black);

glClearColor(background.redF(), background.greenF(), background.blueF(), 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -2);


_program->bind();

_vao.bind();
_vbo.write(_matrixOffset, matrix.constData(), 4 * sizeof(QVector4D));

/* I tried replacing the three preceding lines with the following, without success: */

/*
_vao.bind();
_vbo.bind();
_vbo.write(_matrixOffset, matrix.constData(), 4 * sizeof(QVector4D));


_program->bind();
_program->enableAttributeArray(_matrixAttr);
_func330->glVertexAttribDivisor(_matrixAttr, 1); */

glEnable(GL_DEPTH_TEST);
_func330->glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 1);

_vao.release();

_program->release();

_context->swapBuffers(this);
_context->doneCurrent();

}

因此,似乎我的实例化问题不仅仅是在错误的时间绑定(bind)了错误的缓冲区。我还有什么做错的?

最佳答案

我认为您必须为位置创建一个 VBO,为颜色创建一个 VBO(或使用跨步的交错数据)。 VAO 允许您使用多个 VBO,每个属性一个。

vao.create();
vao.bind();
// prepare your shader program
// ...
// prepare your VBOs : one VBO for pos, one VBO for colors, one for normals,...
// example for position
vertexPositionBuffer.create();
vertexPositionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
vertexPositionBuffer.bind();
// if your store the points using QVector<QVector3D>
vertexPositionBuffer.allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
vertexPositionBuffer.release();
// do the same for colors or other attributes
// ...
// after all buffers are created
shaderProgram.bind();
// Bind the position buffer
vertexPositionBuffer.bind();
shaderProgram.enableAttributeArray("vertexPosition");
shaderProgram.setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 3);
vertexPositionBuffer.release();
// do the same for all other buffers
// ...
shaderProgram.release();
// release vao
vao.release();

and in your paintGL function:

// update your matrices
// bind your shader program
// set you uniform variables
// then
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
vao.release();
// release your shader program

关于qt - 如何在 Qt 5 中使用带有实例化的 VAO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23732001/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com