OpenGL代码适用于GLFW,但不适用于Qt OpenGL
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL代码适用于GLFW,但不适用于Qt OpenGL相关的知识,希望对你有一定的参考价值。
我正在尝试将OpenGL代码从GLFW传输到Qt,以便将其与更大的项目集成。但无论我尝试过什么,我都无法进行纹理显示,而我得到的只是黑屏。
在Qt中,程序编译时没有错误,我在尝试插入纹理之前设法绘制了一个多色三角形。
我已经尝试将Qt OpenGL对象用于着色器,着色器程序,纹理,并根据他们的示例重写代码,但仍然没有。
下面是一个简单的Qt实现,它试图显示一个纹理,导致黑屏。精确的GLFW等效工作正常:
CustomViewGL::CustomViewGL(QWidget *parent): QOpenGLWidget(parent)
{
QSurfaceFormat format;
format.setMajorVersion(3);
format.setMinorVersion(3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
}
void CustomViewGL::initializeGL()
{
glewExperimental=true;
if (glewInit() != GLEW_OK)
{
qDebug() << "Failed to initialize GLEW";
}
std::string vertexShaderSource =
" #version 330 core
"
" "
" layout (location = 0) in vec3 aPos; "
" layout (location = 1) in vec2 aTexCoord; "
" "
" out vec2 TexCoord; "
" "
" void main() "
" { "
" "
" TexCoord = aTexCoord; "
" gl_Position = vec4(aPos, 1.0); "
" "
" } ";
std::string fragmentShaderSource =
" #version 330 core
"
" "
" in vec2 TexCoord; "
" out vec4 FragColor; "
" uniform sampler2D tex; "
" void main() "
" { "
" "
" FragColor = texture(tex, TexCoord); "
" "
" } ";
// Variables
unsigned int shaderVertex, shaderFragment, shaderProgram;
....
....
// Compile Shaders //
...
...
glUseProgram(shaderProgram);
// Vetrices
float rectangle[] = {
// positions // texture coords
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
QImage texture = QImage("wall.jpg").convertToFormat(QImage::Format_RGB888);
// Variables
unsigned int VAO, VBO, EBO, tex;
// VAO, VBO, Attributes Configuration
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle), rectangle, 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, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Texture
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width(), texture.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, texture.bits());
glGenerateMipmap(GL_TEXTURE_2D);
}
void CustomViewGL::paintGL()
{
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*) 0);
}
关于QOpenGLWidget,正如我在关于这个问题的评论中写的那样,我不喜欢的第一个行为就是没有缓冲交换功能。 Qt任意决定何时绘制东西,如question中所述,这是我绝对不想要的东西。其次,虽然我会绑定纹理并设置纹理数据,但它不会出现在屏幕上,除非a)每次在paintGL函数中绑定它或b)在绑定和设置TEXTURE0数据后调用glActiveTexture(GL_TEXTURE1),这是在最不奇怪的。
所以我决定切换到QGLWidget,the official Qt documentation recommends to avoid。 QGLWidget提供了禁用自动交换缓冲区的自由,具有交换缓冲区功能,并且正在使用问题中提到的代码(它本身是来自基于GLFW的实现的直接副本)。
为了禁用自动缓冲交换,选择OpenGL版本,设置反锯齿并设置共享上下文,下面的代码用作构造函数:
CustomViewGL::CustomViewGL(QWidget *parent, const QGLWidget *shareWidget):
QGLWidget(parent, shareWidget) // QGLWidget accepts as a second
{ // constructor argument another QGLWidget
QGLFormat format; // thus context sharing between this and
// the shareWidget is created
format.setVersion(3,3); // Set OpenGL version, here 3.3
format.setProfile(QGLFormat::CoreProfile); // Core Profile
format.setSamples(16); // Anti Alliasing
setFormat(format);
setAutoBufferSwap(false); // Prevents Qt from drawing whenever it wants
}
构造函数的头文件声明是:
CustomViewGL(QWidget *parent = 0, const QGLWidget *shareWidget = 0);
然后实现protected function initializeGL()并输入初始化代码,您就可以开始了。
以上是关于OpenGL代码适用于GLFW,但不适用于Qt OpenGL的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL 代码适用于 Windows 但不适用于 Mac
Opengl Array Texture,适用于原始数据,但不适用于图像数据
OpenGL - 在 NDC 中计算位置适用于着色器,但不适用于“常规”程序