在我使用 GLSL 程序的纹理中,只有一个纹理绑定到纹理单元 0。如下所示:
.......................
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);
然后通过一个统一变量通知frag shader(就像setUniform一样),这里的名字是“texture0”,对应于我的frag shader:
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__);
顺便说一句,在我使用 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 方法,正如我之前所说,在 glGetUniformiv 在此方法中返回后,它具有“glGetError”的 GL_INVALID_OPERATION 结果。
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();
}