在我的紋理是錯誤使用紋理着色器我用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();
}
不幸的是你的代碼並沒有顯示出一些重要的東西:第一:glAssert是怎麼樣的? OpenGL錯誤堆棧,你必須在循環中調用glGetError,直到它返回GL_NO_ERROR。如果你不這樣做,你會得到報告陳舊的錯誤狀態。此外,還不清楚CShader的哪些上下文實例正在運行。將OpenGL映射到類和實例是非常困難的,幾乎不可能正確。 – datenwolf 2013-04-06 16:24:19
那麼,在C++包裝器中綁定OpenGL確實工作得很好,而且非常方便。但事實上,我們必須格外小心保持堆棧清潔,同時不要爲功能增加太多額外的操作。但總的來說,我認爲這是一個非常好的設計方法,尤其是當多着色器和FBO發揮作用時。 你能向我們展示如何以及何時綁定着色器。你會驚訝於這麼簡單的東西會帶來多少麻煩;) – geenux 2013-04-07 00:38:40
在設置統一值之前程序是否在使用? – 2013-04-07 10:18:28