在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着色器(如setUniform所做),这里的名称是“texture0”,对应于我的frag着色器:
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在此方法中返回后,它的GL_INVALID_OPERATION结果为“glGetError”。
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 :(得分:7)
m_shader->compileandlink();
m_shader->setUniform("texture0", 0);
这不起作用,因为you can only set uniforms when there's an active program object。即,在尝试设置统一值之前,您需要glUseProgram(m_program)
。这就是program
函数没有glUniform
参数的原因。
我不明白:int loc = getUniformLocation(name)
,因为 需要链接程序的名称。评论:glGetUniformLocation(m_program, name)
实际上是正确的。