GLSLプログラムを使用したテクスチャリングでは、次のように、テクスチャユニット0にテクスチャバインドを1つだけ使用します。
.......................
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
.what was wrong,doesn't my display card is supported for this operation?,サポートされていません.my version is OpenGL
3.x. 数時間の闘争の後、最後のコメントを試してみましたglAssert()
が、私の gldrawelements 呼び出しで別のアサーションが失敗しました。gldrawelements
明らかに、失敗した原因は失敗したと絶対に思いますglUniform1i
。誰かが私に提案を与えることができますか?
編集:
datenwolf の提案から、ここに glAssert のコードがあります。これは非常に単純で、glGetError を 1 回呼び出すだけです。
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();
}