2013-04-06 20 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