1

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 OpenGL3.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();
    }
4

1 に答える 1

7
m_shader->compileandlink();
m_shader->setUniform("texture0", 0);

アクティブなプログラムオブジェクトがある場合にのみユニフォームを設定できるため、これは機能しません。glUseProgram(m_program)つまり、均一な値を設定しようとする前に必要です。そのため、関数のprogramパラメーターはありません。glUniform

わかりません:リンクされたプログラムの名前が必要なint loc = getUniformLocation(name)ので。コメント:は実際には正しいです。glGetUniformLocation(m_program, name)

于 2013-04-07T14:25:22.400 に答える