在我的纹理是错误使用纹理着色器我用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