[英]Qt program with OpenGL + GLSL integration crashes immediately in run-time
我是 OpenGL 和 GLSL 的新手。 我正在嘗試使用 Qt Creator 中的這些庫編寫第一個程序,該程序將在QOpenGLWindow
window 中繪制一個普通的矩形。 編譯成功實現,但是程序在嘗試運行時立即崩潰,並出現以下錯誤 output:
Running /home/andrey/build-opengl_glsl-Desktop-Debug/opengl_glsl ...
The program has suddenly terminated.
The process was terminated forcibly.
/home/andrey/build-opengl_glsl-Desktop-Debug/opengl_glsl has crashed.
我使用 Ubuntu 20.04、QtCreator 4.11 和 OpenGL ES 2.0(因為此版本由QOpenGLFunctions
類使用)。
編碼:
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QOpenGLWindow>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
class GLWindow : public QOpenGLWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
GLWindow(QWindow *parent = nullptr, QString vertex_shader_p = "", QString
fragment_shader_p = "");
protected:
virtual void initializeGL() override;
virtual void paintGL() override;
virtual void resizeGL(GLint w, GLint h) override;
QOpenGLContext *m_context;
QString vertex_shader_path;
QString fragment_shader_path;
GLint shaderProgramID;
};
#endif // MAINWINDOW_H
主窗口.cpp
#include "mainwindow.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
GLWindow::GLWindow(QWindow *parent, QString vertex_shader_p, QString
fragment_shader_p)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent),
vertex_shader_path(vertex_shader_p),
fragment_shader_path(fragment_shader_p)
{
setSurfaceType(OpenGLSurface);
create();
m_context = new QOpenGLContext;
m_context->create();
initializeGL();
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f, // Lower left vertex
0.5f, -0.5f, 0.0f, // Lower right vertex
0.5f, 0.5f, 0.0f, // Upper right vertex
-0.5f, 0.5f, 0.0f // Upper left vertex
};
GLuint indices[] = {
0, 1, 3, // Lower triangle
3, 2, 1 // Upper triangle
};
GLuint vbo, ebo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
QString vertex_shader_code;
QString fragment_shader_code;
string vsc_to_stdstr = vertex_shader_code.toStdString();
string fsc_to_stdstr = fragment_shader_code.toStdString();
ifstream inf;
inf.exceptions(ifstream::failbit | ifstream::badbit);
try
{
stringstream shadercodestream;
inf.open(vertex_shader_path.toStdString());
shadercodestream << inf.rdbuf();
inf.close();
vsc_to_stdstr = shadercodestream.str();
shadercodestream.str("");
inf.open(fragment_shader_path.toStdString());
shadercodestream << inf.rdbuf();
inf.close();
fsc_to_stdstr = shadercodestream.str();
shadercodestream.str("");
}
catch (ifstream::failure& e)
{
std::cout << e.what() << std::endl;
}
const GLchar* vsc_to_cstr = vsc_to_stdstr.c_str();
const GLchar* fsc_to_cstr = fsc_to_stdstr.c_str();
GLint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vsc_to_cstr, nullptr);
glCompileShader(vertexShaderID);
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
GLint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fsc_to_cstr, nullptr);
glCompileShader(fragmentShaderID);
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
shaderProgramID = glCreateProgram();
glAttachShader(shaderProgramID, vertexShaderID);
glAttachShader(shaderProgramID, fragmentShaderID);
glLinkProgram(shaderProgramID);
glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgramID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
paintGL();
}
void GLWindow::initializeGL()
{
m_context->makeCurrent(this);
initializeOpenGLFunctions();
}
void GLWindow::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgramID);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
void GLWindow::resizeGL(GLint w, GLint h)
{
glViewport(0, 0, w, h);
}
主文件
#include "mainwindow.h"
#include <iostream>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GLWindow w(nullptr,
"/home/andrey/programs/cpp/opengl/opengl_glsl/vertex_shader.glsl",
"/home/andrey/programs/cpp/opengl/opengl_glsl/fragment_shader.glsl");
w.show();
return a.exec();
}
vertex_shader.glsl
#version 450 core
layout (location = 0) in vec3 vpos;
out vec3 new_pos;
void main()
{
gl_Position = vec4(vpos.x, vpos.y, vpos.z, 1.0);
new_pos = vpos;
}
片段着色器.glsl
#version 450 core
in vec3 new_pos;
out vec4 color;
vec3 nmlzed_pos;
void main()
{
nmlzed_pos = normalize(new_pos);
color = vec4(nmlzed_pos.xyz, 1.0);
}
.pro
QT += opengl core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs
deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
HEADERS += \
mainwindow.h \
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
我還嘗試使用 GDB 在調試模式下運行程序,看起來這在GLWindow::initializeGL()
方法中的initializeOpenGLFucntions()
調用上崩潰了。
根據評論...
基本解決方法是將所有初始化代碼移至initializeGL
並讓Qt
OpenGL
框架對initializeGL
、 paintGL
等進行必要的調用。
您的構造函數和initializeGL
成員應類似於...
GLWindow::GLWindow(QWindow *parent, QString vertex_shader_p,
QString fragment_shader_p)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent)
, vertex_shader_path(vertex_shader_p)
, fragment_shader_path(fragment_shader_p)
{
}
void GLWindow::initializeGL()
{
initializeOpenGLFunctions();
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f, // Lower left vertex
0.5f, -0.5f, 0.0f, // Lower right vertex
0.5f, 0.5f, 0.0f, // Upper right vertex
-0.5f, 0.5f, 0.0f // Upper left vertex
};
GLuint indices[] = {
0, 1, 3, // Lower triangle
3, 2, 1 // Upper triangle
};
GLuint vbo, ebo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
QString vertex_shader_code;
QString fragment_shader_code;
string vsc_to_stdstr = vertex_shader_code.toStdString();
string fsc_to_stdstr = fragment_shader_code.toStdString();
ifstream inf;
inf.exceptions(ifstream::failbit | ifstream::badbit);
try
{
stringstream shadercodestream;
inf.open(vertex_shader_path.toStdString());
shadercodestream << inf.rdbuf();
inf.close();
vsc_to_stdstr = shadercodestream.str();
shadercodestream.str("");
inf.open(fragment_shader_path.toStdString());
shadercodestream << inf.rdbuf();
inf.close();
fsc_to_stdstr = shadercodestream.str();
shadercodestream.str("");
}
catch (ifstream::failure& e)
{
std::cout << e.what() << std::endl;
}
const GLchar* vsc_to_cstr = vsc_to_stdstr.c_str();
const GLchar* fsc_to_cstr = fsc_to_stdstr.c_str();
GLint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vsc_to_cstr, nullptr);
glCompileShader(vertexShaderID);
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
GLint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fsc_to_cstr, nullptr);
glCompileShader(fragmentShaderID);
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
shaderProgramID = glCreateProgram();
glAttachShader(shaderProgramID, vertexShaderID);
glAttachShader(shaderProgramID, fragmentShaderID);
glLinkProgram(shaderProgramID);
glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgramID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
}
使用上面的代碼進行快速測試會導致...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.