[英]OpenGL Code works on GLFW but not on 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\n "
" "
" 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); "
" "
" }\0 ";
std::string fragmentShaderSource =
" #version 330 core\n "
" "
" in vec2 TexCoord; "
" out vec4 FragColor; "
" uniform sampler2D tex; "
" void main() "
" { "
" "
" FragColor = texture(tex, TexCoord); "
" "
" }\0 ";
// 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可以隨意決定何時繪制內容,這是我絕對不希望的。 其次,盡管我將綁定紋理並設置紋理數據,但除非a)每次在paintGL函數中進行綁定或b)在綁定並設置TEXTURE0數據后調用glActiveTexture(GL_TEXTURE1),否則它將不會出現在屏幕上,最不奇怪。
因此,我決定切換到QGLWidget,這是Qt官方文檔建議避免的 。 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);
然后實現受保護的函數initializeGL()並輸入初始化代碼,您就可以開始了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.