2016-09-05 60 views
3

我正在開發一個項目,我需要在Qt 5.7中使用OpenGL 2.1創建紋理矩形。我一直在使用Qt的QOpenGLWidget寫這個小例子:在Mac OSX上使用Qt 5.7在OpenGL 2.1中創建紋理矩形el capitan

#include <QDebug> 
#include <string.h> 
#include "openglwidget.h" 

OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent) 
{ 

} 

void OpenGLWidget::initializeGL() { 
    initializeOpenGLFunctions(); 
    glClearColor(0, 0, 0, 1); 

    /** Vertex Shader **/ 
    const char* vertexShader = "\ 
      attribute vec2 pos;\ 
      attribute vec2 texCoord;\ 
      varying vec2 TexCoord;\ 
      void main() {\ 
       gl_Position.xy = pos.xy;\ 
       gl_Position.zw = vec2(0, 1);\ 
       TexCoord = texCoord;\ 
      }\ 
           "; 
    GLint vertexSourceLength = strlen(vertexShader); 
    GLuint vertexShaderObject = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShaderObject, 1, &vertexShader, &vertexSourceLength); 
    glCompileShader(vertexShaderObject); 
    GLint result; 
    glGetShaderiv(vertexShaderObject, GL_COMPILE_STATUS, &result); 
    if (result != GL_TRUE) { 
     qDebug() << "Vertex Shader not compiled"; 
    } 

    /** Fragment Shader **/ 
    const char* fragmentShader = "\ 
      uniform sampler2D texture;\ 
      varying vec2 TexCoord;\ 
      void main() {\ 
       vec4 texColor = texture2D(texture, TexCoord);\ 
       gl_FragColor = texColor;\ 
      }\ 
           "; 
    GLint fragmentSourceLength = strlen(vertexShader); 
    GLuint fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShaderObject, 1, &fragmentShader, &fragmentSourceLength); 
    glCompileShader(fragmentShaderObject); 
    glGetShaderiv(fragmentShaderObject, GL_COMPILE_STATUS, &result); 
    if (result != GL_TRUE) { 
     qDebug() << "Fragment Shader not compiled"; 
    } 

    /** Program **/ 
    GLuint program = glCreateProgram(); 
    glAttachShader(program, vertexShaderObject); 
    glAttachShader(program, fragmentShaderObject); 
    glLinkProgram(program); 
    glGetProgramiv(program, GL_LINK_STATUS, &result); 
    if (result != GL_TRUE) { 
     qDebug() << "Program not linked."; 
    } 
    glUseProgram(program); 

    /** Upload Buffer Data **/ 
    GLuint VBO; 
    glGenBuffers(1, &VBO); 
    glBindBuffer(GL_ARRAY_BUFFER, VBO); 
    GLfloat vertexData[] = { 
     //Position  //TexCoord 
     -0.5, -0.5,  0.0, 0.0, 
     0.5, -0.5,  1.0, 0.0, 
     0.5, 0.5,  1.0, 1.0, 
     -0.5, 0.5,  0.0, 1.0 
    }; 
    glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(GLfloat),vertexData, GL_STATIC_DRAW); 

    /** Set Position Pointers **/ 

    GLint pos = glGetAttribLocation(program, "pos"); 
    if (pos == -1) { 
     qDebug() << "Position attribute not found."; 
    } 
    glVertexAttribPointer(pos, 2, GL_FLOAT, GL_TRUE, 4 * sizeof(GLfloat), 0); 
    glEnableVertexAttribArray(pos); 

    /** Set TexCoord Pointers **/ 

    GLint texCoord = glGetAttribLocation(program, "texCoord"); 
    if (texCoord == -1) { 
     qDebug() << "texCoord attribute not found."; 
    } 
    glVertexAttribPointer(texCoord, 2, GL_FLOAT, GL_TRUE, 4 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(texCoord); 

    /** Set Texture **/ 
    int width = 4; 
    int height = 4; 
    GLubyte pixels[] = { 
     255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
     255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
     255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
     255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255 
    }; 
    glActiveTexture(GL_TEXTURE0); 
    GLuint texture; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 
    glGenerateMipmap(GL_TEXTURE_2D); 
    GLint textureLoc = glGetUniformLocation(program, "texture"); 
    if (textureLoc == -1) { 
     qDebug() << "texture uniform not found."; 
    } 
    glUniform1i(textureLoc, 0); 

    GLuint err = GL_NO_ERROR; 
    while ((err = glGetError()) != GL_NO_ERROR) { 
     qDebug() << "Error: " << (void *) err; 
    } 
} 

void OpenGLWidget::resizeGL(int w, int h) { 

} 

void OpenGLWidget::paintGL() { 
    glClear(GL_COLOR_BUFFER_BIT); 
    glDrawArrays(GL_QUADS, 0, 4); 
    GLuint err = GL_NO_ERROR; 
    while ((err = glGetError()) != GL_NO_ERROR) { 
     qDebug() << "Error: " << (void *) err; 
    } 
} 

我期待這個代碼來生成一個紅色矩形,相反,我得到一個黑色的屏幕。我已經在StackOverflow上查看了幾乎所有與glTexImage2D相關的問題,而且我似乎無法找到答案。我開始認爲這是一個Qt/Mac特定的問題,但不幸的是,我沒有資源在另一個操作系統上嘗試它,所以我不確定。這可能是一些顯而易見的事情,我錯過了。

我知道一個事實,即位置向量和texCoords正在發送正確,因爲如果我改變片段着色器到這一點:

uniform sampler2D texture; 
varying vec2 TexCoord; 
void main() { 
    vec4 texColor = texture2D(texture, TexCoord); 
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); 
    gl_FragColor.xy *= TexCoord; 
} 

我得到

this

這是什麼我期望與片段着色器。 glGetShaderiv,glGetProgramiv或glGetError沒有錯誤出現。有任何想法嗎?

UPDATE用OpenGL 3.3試過了,仍然沒有工作。我嘗試了上面我嘗試過的相同測試,得到了texCoords的工作,併發送了頂點(這是因爲GL_QUADS已棄用,並且使用片段着色器中的texture()而不是texture2D,因爲已棄用紋理) 。所以它不是我使用的OpenGL版本的問題。

UPDATE所以經過再三考慮,它沒有太大的意義,這將是一個操作系統的問題,因爲我知道Qt使用蘋果的NeXTStep的API引擎蓋下,並禁止這一點,我想一個例子從Apple的網站(用Objective-C和Cocoa編寫)構建一個帶紋理的OpenGL對象。這工作。我查看了源代碼,並嘗試使用相同的opengl調用他們的紋理(雖然他們大多是相同的),但它似乎仍然沒有工作。所以它或者是Qt的問題,或者是我在代碼中遺漏/誤解的東西真的很愚蠢。

回答

0

我找到了答案,我的問題!事實證明,你必須在glDrawArrays之前調用glBindTexture才能工作。在initializeGL和paintGL之間發生了一些事情,Qt解綁定紋理並綁定不同的紋理。對於那些有興趣的人,我通過使用glGetTexImage進行調試發現了這一點,這對於調試非常有用(即使顯然很慢)。

1

的問題是你用你的紋理數據的數據類型:

GLuint pixels[] = { 
    255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
    255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
    255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255, 
    255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255,  255, 0, 0, 255 
}; 

由於您使用GLuint的類型,並匹配GL_UNSIGNED_INT參數glTexImage2D(),這些值會解釋爲32位無符號值。 255是一個非常小的32位值,這就解釋了爲什麼你會變黑。

換言之,glTexImage2D()將基於類型將您傳遞的值解釋爲標準化的定點值。要獲得[0.0,1.0]範圍內的實際標準化值,它將在32位值的情況下將您傳遞的值除以2^32-1。所以你的情況下得到的值將是255 /(2^32-1)= 0.00000005937。這是接近0到黑色。

爲了解決這個問題,最簡單的方法是,你使用的字節的類型:

GLubyte pixels[] = { 
... 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 
+0

謝謝,這實際上是我發佈的示例的一個問題,在原始項目中,它是GL_UNSIGNED_BYTE,而不是GL_UNSIGNED_INT。我將用正確的類型編輯我的問題。它仍然無法工作:( –

+1

)當你告訴OpenGL你的數據是'GL_UNSIGNED_BYTE'(每個通道1個字節)時,你還必須提供這些數據,目前你仍然有4字節的GLuint,你必須改變那對'GLubyte'。 – BDL

+0

@BDL是的抱歉..這個例子和原始項目的另一個區別是,原始代碼的數據類型都是GLubyte,都不是。 –

相關問題