2015-05-12 64 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版本。