在我使用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);
Run Code Online (Sandbox Code Playgroud)
然后通过统一变量通知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.
}
Run Code Online (Sandbox Code Playgroud)
这超出了我的期望,它在最后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__);
Run Code Online (Sandbox Code Playgroud)
顺便说一下,在我使用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;
}
Run Code Online (Sandbox Code Playgroud)
我在着色器中删除了许多代码以简化问题.
对不起,我没有详细描述.实际上,我的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);
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
m_shader->compileandlink();
m_shader->setUniform("texture0", 0);
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为只有在有活动的程序对象时才能设置制服.即,glUseProgram(m_program)在尝试设置统一值之前需要.这就是为什么函数没有program参数的原因glUniform.
我不明白:int loc = getUniformLocation(name),因为它确实需要链接程序的名称.评论:glGetUniformLocation(m_program, name)实际上是正确的.
| 归档时间: |
|
| 查看次数: |
4458 次 |
| 最近记录: |