2015-05-12 66 views
1

我想寫一個簡單的片段着色器,它應該混合2個或更多紋理。我已經編寫了關於Qt 5.4的測試項目,但由於某些原因,它無法運行任何必須非零聯合的紋理。 它忽略 中的任何值setUniformValue(「tex *」,*); (str。83-90) 和任何sampler2d總是隻操作綁定到0的紋理。GLSL像素着色器只操作0紋理

怎麼了?

Source of test project on Qt 5.4 available at bitbucket

#include <QApplication> 
#include <QCoreApplication> 
#include <QOffscreenSurface> 
#include <QOpenGLContext> 
#include <QOpenGLFunctions> 
#include <QOpenGLFramebufferObject> 
#include <QOpenGLShader> 
#include <QOpenGLTexture> 
#include <QLabel> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    QSurfaceFormat format; 
    format.setMinorVersion(2); 
    format.setMajorVersion(4); 
    format.setProfile(QSurfaceFormat::CompatibilityProfile); 
// format.setProfile(QSurfaceFormat::CoreProfile); 

    QOpenGLContext context; 
    context.setFormat(format); 
    if(!context.create()){   
     qFatal("Cannot create the requested OpenGL context!"); 
    } 

    QOffscreenSurface surface; 
    surface.setFormat(format); 
    surface.create(); 
    context.makeCurrent(&surface); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0); 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    const float c_01SquareVertices[8] ={0.0f, 0.0f, 
             1.0f, 0.0f, 
             1.0f, 1.0f, 
             0.0f, 1.0f}; 
    glVertexPointer(2, GL_FLOAT, 0, c_01SquareVertices); 
    glTexCoordPointer(2, GL_FLOAT, 0, c_01SquareVertices); 
    glDisable(GL_DEPTH_TEST); 
    glDisable(GL_TEXTURE_2D); 
    int maxTextureUnits; 
    glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); 
    qDebug()<<"GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS" << maxTextureUnits; 

    QImage texImg = QImage(":/tex/tex"); 
    QOpenGLTexture tex(texImg.mirrored()); 
    QImage texImg1 = QImage(":/tex/tex1"); 
    QOpenGLTexture tex1(texImg1.mirrored()); 
    QImage texImg2 = QImage(":/tex/tex2"); 
    QOpenGLTexture tex2(texImg2.mirrored()); 

    QString fsc = 
      "uniform sampler2D tex;" 
      "uniform sampler2D tex1;" 
      "uniform sampler2D tex2;" 
      "varying vec4 gl_TexCoord[];" 
      "void main(void)" 
      "{" 
      " gl_FragColor = texture2D(tex2, gl_TexCoord[0].yx * 2.0);" 
//   " gl_FragColor = texture2D(tex1, gl_TexCoord[0].xy) + texture2D(tex2, gl_TexCoord[0].xy);" 
      "}"; 

    QOpenGLShader fsh(QOpenGLShader::Fragment, &context); 
    fsh.compileSourceCode(fsc); 

    QOpenGLShaderProgram pr(&context); 

    pr.addShader(&fsh); 
    pr.link(); 

    QOpenGLFramebufferObjectFormat fboFormat; 
// fboFormat.setInternalTextureFormat(GL_ALPHA32F); 
    QOpenGLFramebufferObject fbo(1000, 1000, fboFormat); 
    fbo.bind(); 
     glViewport(0,0,fbo.width(),fbo.height()); 
     glClear(GL_COLOR_BUFFER_BIT); 

     tex.bind(0); 
     pr.setUniformValue("tex", GLuint(1)); 

     tex1.bind(2); 
     pr.setUniformValue("tex1", GLuint(2)); 

     tex2.bind(3); 
     pr.setUniformValue("tex2", GLuint(3)); 

     pr.bind(); 

     glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
    fbo.release(); 

    QLabel w; 
    w.resize(fbo.size()); 
    w.setPixmap(QPixmap::fromImage(fbo.toImage())); 
    w.show(); 

    return a.exec(); 
} 
+2

嘗試將'pr.bind()'移動到第一個'pr.setUniformValue'之前(在'glClear'後面) –

+0

Thanx alot man!它的作品) – ibnz

+0

@ColonelThirtyTwo你應該將你的評論移到答案 – Spektre

回答

1

在C API的OpenGL,以便使用或修改對象,必須首先將其綁定*。

顯然,在調用glUniform之前,pr.setUniformValue未綁定pr來更改統一值。雖然有點不方便和不直觀,但這是可以理解的;反覆冗餘地綁定相同的着色器會產生性能開銷。

因此,只需將pr.bind()移動到上面,您可以撥打pr.setUniformValue


*的EXT_direct_state_access擴展,可以修改對象,而不結合它們,但需要不同的API,並且不保證4.5(最新)之前出現的OpenGL版本。