2013-04-06 74 views
1

在我的纹理是错误使用纹理着色器我用GLSL程序,只是一个纹理绑定到纹理单元0.such如下:什么通过glUniform1i

....................... 
     glActiveTexture(GL_TEXTURE0); 
     GLuint tid; 
     glGenTextures(1, &tid); 
     glBindTexture(GL_TEXTURE_2D, tid); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width, img.height, 0, 
        img.format, GL_UNSIGNED_BYTE, img.data); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

,然后通过统一的变量通知到断枝着色器(如setUniform一样),这里的名字是“texture0”相当于我的断枝着色器:

void CShader::setUniform(const char *name, int val) 
    { 
     int loc = getUniformLocation(name); 
     glAssert(); //note!,my own assertion wrapping around glGetError. 
       if(loc >= 0) 
     { 
      glUniform1i(loc, val); 

     } else { 
      printf("Uniform: %s not found.\n",name); 
     } 
       glAssert(); //note!,my own assertion wrapping around glGetError. 

    } 

这是出乎我的意料,它声称在最后glAssert()线失败,并给我GL_INVALID_OPERATION。什么是错的,没有按我的显卡是支持的堕落为此操作?,它不能,我的OpenGL版本是3.x.经过几个小时的努力之后,尝试了一下最后的glAssert(),但另一个断言在我的gldrawelements调用中失败了。显然,我绝对认为导致gldrawelements失败的原因是glUniform1i失败。有人可以给我建议。

编辑:

从datenwolf建议,这里有给glAssert代码,这是非常简单的,只需要调用glGetError一次。

void _glAssert(const char * info, int line){ 
char const* sz_GL_INVALID_ENUM="GL_INVALID_ENUM"; 
char const* sz_GL_INVALID_VALUE="GL_INVALID_VALUE"; 
char const* sz_GL_INVALID_OPERATION="GL_INVALID_OPERATION"; 
char const* sz_GL_OUT_OF_MEMORY ="GL_OUT_OF_MEMORY"; 
GLenum result; 
    if((result=glGetError()) != GL_NO_ERROR) 
    { 
     const char * sz_result=NULL; 
     switch(result) 
     { 
     case GL_INVALID_ENUM: 
      sz_result = sz_GL_INVALID_ENUM; 
     break; 
     case GL_INVALID_VALUE: 
      sz_result = sz_GL_INVALID_VALUE; 
     break; 
     case GL_INVALID_OPERATION: 
      sz_result = sz_GL_INVALID_OPERATION; 
     break; 
     case GL_OUT_OF_MEMORY: 
      sz_result = sz_GL_OUT_OF_MEMORY; 
     break; 
     } 

     _assert(sz_result,info,line); 
    } 
} 

#define glAssert() \ 
    _glAssert(__FILE__, __LINE__); 

BTW,我使用glUniform1i电话之前,

attribute vec3 VertexPosition; 
varying vec3 Color; 
void main() 
{ 
Color = vec3(0.5,0,0); 
gl_TexCoord[0] = gl_MultiTexCoord0; 
gl_Position = gl_ModelViewProjectionMatrix * vec4(VertexPosition, 1.0); 
} 


uniform sampler2D texture0; 

varying vec3 Color; 
void main() { 

vec4 texColor = texture2D(texture0, gl_TexCoord[0].st); 
gl_FragColor= vec4(Color, 1.0)*texColor; 
} 

我已经在着色器剥离出来很多代码来简化问题,一切工作正常与我的着色器。

对不起,我没有详细描述这一点。实际上,我的opengl封装非常简单,没有复杂的东西,没有多线程。

这是用于将纹理和着色器脚本单独加载到GPU,内存中的构造方法,然后调用“compileandlink”方法编译着色器脚本,并立即调用setUniform。

IEntity(const char * szvs,const char * szfs): m_shader(new CShader(szvs,szfs)){ 
     ........................... 
} 

CCube::CCube():IEntity("v_simple.glsl","f_simple.glsl") { 
    ................... 

     IMAGE img; 
     img.Load("texture.bmp"); 
     img.ExpandPalette(); 

     glActiveTexture(GL_TEXTURE0); 
     GLuint tid; 
     glGenTextures(1, &tid); 
     glBindTexture(GL_TEXTURE_2D, tid); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width, img.height, 0, 
        img.format, GL_UNSIGNED_BYTE, img.data); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

     m_shader->compileandlink(); 
     m_shader->setUniform("texture0", 0); 
} 

CShader :: compileandlink方法

bool CShader::compileandlink(){ 
      if(m_vsscript == NULL || m_fsscript == NULL) 
       return false; 

      if(strlen(m_vsscript) <= 0 || strlen(m_fsscript) <= 0) 
       return false; 

      glShaderSource(m_vs, 1, (const GLchar **) &m_vsscript, NULL); 
      glCompileShader(m_vs); 

      glShaderSource(m_fs, 1, (const GLchar **) &m_fsscript, NULL); 
      glCompileShader(m_fs); 

      glAttachShader(m_program, m_vs); 
      glAttachShader(m_program, m_fs); 
      //glBindFragDataLocation(m_program, 0, "FragColor"); 
      glLinkProgram(m_program); 
      glAssert(); 


      GLint status; 
      glGetProgramiv(m_program, GL_LINK_STATUS, &status); 
      if(GL_FALSE == status) { 
      fprintf(stderr, "Failed to link shader program!\n"); 
      GLint logLen; 
      glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, 
      &logLen); 

      if(logLen > 0) 
       { 
       char * log = (char *)malloc(logLen); 
       GLsizei written; 
       glGetProgramInfoLog(m_program, logLen, 
        &written, log); 
       printf("Program log: \n%s", log); 
       free(log); 
       } 
      } 


      return true; 

    } 

CShader :: setUniform方法,正如我前面说的,它具有 “glGetError” 的GL_INVALID_OPERATION结果后glGetUniformiv这种方法中返回。

void CShader::setUniform(const char *name, int val) 
    { 
     int loc = getUniformLocation(name); 
     glAssert(); 
     if(loc >= 0) 
     { 
      GLint outval=-1; 

      glUniform1i(loc, val); 
      /*int tmploc =glGetUniformLocation(m_program, name); 
      glGetUniformiv(m_program, 
          tmploc, 
          &outval); 
      printf("Value is %d\n", outval);*/ 

     } else { 
      printf("Uniform: %s not found.\n",name); 
     } 
     glAssert(); 
    } 
+0

不幸的是你的代码并没有显示出一些重要的东西:第一:glAssert是怎么样的? OpenGL错误堆栈,你必须在循环中调用glGetError,直到它返回GL_NO_ERROR。如果你不这样做,你会得到报告陈旧的错误状态。此外,还不清楚CShader的哪些上下文实例正在运行。将OpenGL映射到类和实例是非常困难的,几乎不可能正确。 – datenwolf 2013-04-06 16:24:19

+0

那么,在C++包装器中绑定OpenGL确实工作得很好,而且非常方便。但事实上,我们必须格外小心保持堆栈清洁,同时不要为功能增加太多额外的操作。但总的来说,我认为这是一个非常好的设计方法,尤其是当多着色器和FBO发挥作用时。 你能向我们展示如何以及何时绑定着色器。你会惊讶于这么简单的东西会带来多少麻烦;) – geenux 2013-04-07 00:38:40

+0

在设置统一值之前程序是否在使用? – 2013-04-07 10:18:28

回答

7
m_shader->compileandlink(); 
m_shader->setUniform("texture0", 0); 

这是行不通的,因为you can only set uniforms when there's an active program object。即在尝试设置统一值之前需要glUseProgram(m_program)。这就是为什么glUniform函数没有program参数。

我不明白:int loc = getUniformLocation(name),因为它确实需要一个链接程序的名称。评论:glGetUniformLocation(m_program, name)其实是正确的。

+0

哦,我很愚蠢,我忘了绑定当前的程序对象,在添加“compileandlink”方法后,everthing工作正常。真的很感谢你提醒我。 @Brett Hale – 2013-04-07 14:37:28