我正在尝试实现一个最小可行的示例,用于使用 QOpenGLWidget 运行 OpenGL2.1 兼容管道。在此示例中,我尝试创建一个与 View 空间中的 xy 平面平行的平面(使用正交投影矩阵)。我还想在片段着色器中使用顶点着色器的颜色输出变量。
当我运行代码时,调用 glDrawElements 时出现段错误。我不是 OpenGL 专家,总是很难正确设置它,所以也许有人可以告诉我我在这里缺少什么。
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(OpenGLExample)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets OpenGLWidgets)
set(CMAKE_AUTOMOC ON)
add_executable(MainApp main.cpp)
target_link_libraries(MainApp PRIVATE Qt6::Widgets Qt6::OpenGLWidgets)
main.cpp
#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QVector3D>
#include <QOpenGLContext>
namespace {
const QString vertexShader = ( "#version 120\n"
"attribute vec3 pos;\n"
"varying vec3 color;\n"
"uniform mat4 mvp_mat;\n"
"void main(){\n"
" gl_Position = mvp_mat * vec4(pos, 1);\n"
" color = (vec3(pos.x, pos.y, 0) + 1) / 2;\n"
"}" );
const QString fragmentShader = ( "#version 120\n"
"varying vec3 color;\n"
"void main() {\n"
" gl_FragColor = vec4(color, 1);\n"
"}" );
}
class OpenGLTestWidget: public QOpenGLWidget {
Q_OBJECT
public:
OpenGLTestWidget(QWidget* parent = nullptr)
: QOpenGLWidget(parent)
, vertexData({QVector3D(-0.5f, -0.5f, -0.5f),
QVector3D(0.5f, -0.5f, -0.5f),
QVector3D(0.5f, 0.5f, -0.5f),
QVector3D(-0.5f, 0.5f, -0.5f)})
{
modelMatrix.setToIdentity();
viewMatrix.setToIdentity();
projectionMatrix.setToIdentity();
projectionMatrix.ortho(-1.0, 1.0, -1.0, 1.0, 0, 1);
}
virtual ~OpenGLTestWidget() {
cleanup();
}
protected:
void initializeGL() override {
vao.create(); // added in edit
vao.bind(); // added in edit
vbo.create();
vbo.bind();
vbo.allocate(vertexData.data(), sizeof(QVector3D) * vertexData.size());
program = new QOpenGLShaderProgram(this);
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader);
program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader);
program->link();
program->bind();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLTestWidget::cleanup);
}
void paintGL() override {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const QMatrix4x4 mpvMatrix = projectionMatrix * viewMatrix * modelMatrix;
program->setUniformValue("mpv_mat", mpvMatrix);
const int vertexLocation = program->attributeLocation("pos");
program->enableAttributeArray(vertexLocation);
program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(QVector3D));
// glDrawElements(GL_TRIANGLE_FAN, vertexData.size(), GL_UNSIGNED_SHORT, nullptr); // <-- ERROR
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.size()); // <-- no segfault but nothing renders
}
private:
QOpenGLVertexArrayObject vao; // added in edit
QOpenGLBuffer vbo;
QOpenGLShaderProgram* program;
std::array<QVector3D, 4> vertexData;
QMatrix4x4 modelMatrix;
QMatrix4x4 viewMatrix;
QMatrix4x4 projectionMatrix;
void cleanup(){
makeCurrent();
delete program;
vbo.destroy();
vao.destroy(); // added in edit
doneCurrent();
disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLTestWidget::cleanup);
}
};
#include "main.moc"
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
OpenGLTestWidget test;
test.show();
return a.exec();
}
最佳答案
顶点数组对象丢失。添加成员变量
QOpenGLVertexArrayObject vao;
并调用
vao.create(); vao.bind();
绑定(bind)VBO之前。
模型- View -投影矩阵的统一名称不匹配。
program->setUniformValue("mpv_mat", mpvMatrix);
需要
program->setUniformValue("mvp_mat", mpvMatrix);
绘制调用
glDrawElements
用于索引渲染。相反,使用glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.size());
主动提供的建议:您可能想要设置 QOpenGLDebugLogger 。在这种情况下,这并不重要,但它对于追踪此类错误很有用。
关于c++ - 运行 QOpenGLWidget 实现时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74171154/