質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

OpenGL ESで長方形を描画すると「GL_INVALID_OPERATION: Operation illegal in current state」が発生します

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,185

fumiasi

score 12

前提・実現したいこと

Unityで外部プラグインを作成してOpenGL ESで長方形(FillRect)を描画しようとしたところ、
「GL_INVALID_OPERATION: Operation illegal in current state」が発生し、
何も描画されない状態になってしまいます。

どこか根本的に間違っている部分や設定漏れがあるのではと考えておりますが、
数日間、原因を調査しても解決しなかったので、皆様のお力をお借りできればと思います。
お手数ですが、何卒宜しくお願い致します。 

ソースコード

// 頂点シェーダー
#define VERTEX_C_SRC(ver, attr, varying)                            \
    ver                                                                \
    attr " highp vec4 a_vertex;\n"                                    \
    attr " lowp vec4 a_color;\n"                            \
    "\n"                                                            \
    "uniform highp mat4 u_ModelViewProj;\n"                            \
    "\n"                                                            \
    varying " lowp vec4 v_color;\n"                                    \
    "\n"                                                            \
    "void main()\n"                                                    \
    "{\n"                                                            \
    "    gl_Position = u_ModelViewProj * a_vertex;\n"                \
    "    v_color = a_color;\n"                                        \
    "}\n"                                                            \

static const char* c_VProgTextGLES2        = VERTEX_C_SRC("\n", "attribute", "varying");
static const char* c_VProgTextGLES3        = VERTEX_C_SRC("#version 300 es\n", "in", "out");
static const char* c_VProgTextGLCore    = VERTEX_C_SRC("#version 150\n", "in", "out");



// フラグメントシェーダー
#define FRAGMENT_C_SRC(ver, varying, outDecl, outVar)                \
    ver                                                                \
    outDecl                                                            \
    varying " lowp vec4 v_color;\n"                                    \
    "\n"                                                            \
    "void main()\n"                                                    \
    "{\n"                                                            \
    "    " outVar " = v_color;\n"                                    \
    "}\n"                                                            \

static const char* c_FShaderTextGLES2    = FRAGMENT_C_SRC("\n", "varying", "\n", "gl_FragColor");
static const char* c_FShaderTextGLES3    = FRAGMENT_C_SRC("#version 300 es\n", "in", "out lowp vec4 fragColor;\n", "fragColor");
static const char* c_FShaderTextGLCore    = FRAGMENT_C_SRC("#version 150\n", "in", "out lowp vec4 fragColor;\n", "fragColor");
class Shader
{
public:
    GLuint        m_Program;
    GLuint        m_VertShader;
    GLuint        m_FragShader;
    GLint*        m_piGLAttrib;
    GLint        m_iGLAttribNum;
    GLint*        m_piGLUniform;
    GLint        m_iGLUniformNum;
    UnityGfxRenderer m_APIType;

    Shader( const char* vert, const char* frag, const int* attribIndex, const char** attribName, int attribNum, const int* uniformIndex, const char** uniformName, int uniformNum, UnityGfxRenderer APIType)
    {
        m_Program = 0;
        m_VertShader = 0;
        m_FragShader = 0;
        m_iGLAttribNum = 0;
        m_piGLAttrib = NULL;
        m_iGLAttribNum = 0;
        m_piGLUniform = NULL;
        m_APIType = APIType;

        createShader( vert, frag, attribIndex, attribName, attribNum, uniformIndex, uniformName, uniformNum);
    }

    boolean createShader( const char* vert, const char* frag, const int* attribIndex, const char** attribName, int attribNum, const int* uniformIndex, const char** uniformName, int uniformNum)
    {
        // プログラムオブジェクトの作成
        m_Program = glCreateProgram();
        if( m_Program == 0 ){
            goto _ERROR;
        }

        if( FALSE == compileShader( &m_VertShader, GL_VERTEX_SHADER, vert) ){
            goto _ERROR;
        }
        if( FALSE == compileShader( &m_FragShader, GL_FRAGMENT_SHADER, frag) ){
            goto _ERROR;
        }

        // シェーダオブジェクトのシェーダプログラムへの登録
        glAttachShader( m_Program, m_VertShader );
        glAttachShader( m_Program, m_FragShader );

    #if SUPPORT_OPENGL_CORE
        if (m_APIType == kUnityGfxRendererOpenGLCore)
            glBindFragDataLocation(m_Program, 0, "fragColor");
    #endif // if SUPPORT_OPENGL_CORE

        // シェーダプログラムのリンク
        glLinkProgram( m_Program );

        // プログラムの検証
        glValidateProgram( m_Program );

        // リンクフェーズで決定されたuniform locationをすべて取得
        if( FALSE == getAttribLocations( attribIndex, attribName, attribNum ) ){
            goto _ERROR;
        }    
        // リンクフェーズで決定されたattrib locationをすべて取得
        if( FALSE == getUniformLocations( uniformIndex, uniformName, uniformNum ) ){
            goto _ERROR;
        }

        // シェーダオブジェクトの削除
        releaseShader();

        return TRUE;

    _ERROR:
        release();
        return FALSE;
    }


    boolean compileShader(GLuint* shader, GLenum type, const char* source)
    {
        GLint iGLStatus;

        if( source == NULL ){
            return FALSE;
        }

        *shader = glCreateShader( type );
        if( *shader == 0 ){
            goto _ERROR;
        }

        // シェーダのソースプログラムのシェーダオブジェクトへの読み込み
        glShaderSource(*shader, 1, (const GLchar**)&source, NULL);

        // シェーダのソースプログラムのコンパイル
        glCompileShader( *shader );

        glGetShaderiv( *shader, GL_COMPILE_STATUS, &iGLStatus );
        if( iGLStatus == 0 ){
            goto _ERROR;
        }

        return TRUE;

    _ERROR:
        if( *shader ){
            glDeleteShader( *shader );
            *shader = 0;
        }
        return FALSE;    
    }

    void releaseShader()
    {
        if( m_VertShader )
        {
            glDeleteShader( m_VertShader );
            m_VertShader = 0;
        }
        if( m_FragShader )
        {
            glDeleteShader( m_FragShader );
            m_FragShader = 0;
        }
    }

    void useShader()
    {
        glUseProgram( m_Program );
    }

    boolean getAttribLocations( const int* index, const GLchar** name, int32 num )
    {
        glGetProgramiv( m_Program, GL_ACTIVE_ATTRIBUTES, &m_iGLAttribNum );

        m_piGLAttrib = new GLint[ num ];
        for( int i = 0 ; i < num ; i++ )
        {
            if( m_piGLAttrib == NULL )    continue;
            m_piGLAttrib[ index[ i ] ] = glGetAttribLocation( m_Program, name[ i ] );
        }

        return TRUE;
    }

    boolean getUniformLocations( const int* index, const GLchar** name, int32 num )
    {
        glGetProgramiv( m_Program, GL_ACTIVE_UNIFORMS, &m_iGLUniformNum );

        m_piGLUniform = new GLint[ num ];
        for( int i = 0 ; i < num ; i++ )
        {
            if( m_piGLUniform == NULL )    continue;
            m_piGLUniform[ index[ i ] ] = glGetUniformLocation( m_Program, name[ i ] );
        }

        return TRUE;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

glVertexAttribPointerにクライアント側のメモリアドレスを渡しているようですが(DrawPolyの引数vertex)、OpenGLのバージョンによっては認められない方法かと思います。
頂点情報をOpenGLサーバ側にVBOの形で送り込み、それをバインドした上でglVertexAttribPointerを使って頂点属性を指定してみてはどうでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/14 16:18

    情報ありがとうございます。

    頂いた内容を基に
    glGenBuffers(1, &m_VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertex, &pVerCoord[ 0 ], GL_STREAM_DRAW);
    をFillRect内で行って

    Render_DrawPoly()内で
    glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
    glEnableClientState(GL_VERTEX_ARRAY);
    を行ってから
    glVertexAttribPointer(pShader->m_piGLAttrib[COMMON_ATTRIB_VERTEX], 3, GL_FLOAT, GL_FALSE, 0, 0);
    を行うようにしたところ、無事に表示されるようになりました。

    数日間、悩んでいた内容だったので非常に助かりました。
    ありがとうございました。

    キャンセル

0

すみません
上記に収まらなかったので問題部分のソースをこちら側に追加させて頂きます。

float    m_Proj[ 16 ];
float    m_View[ 16 ];
OGLShader    *m_ShaderTbl;

// m_APITypeにはUnity側で実行されているOpenGLの環境が格納されています。
// kUnityGfxRendererOpenGLES20 / kUnityGfxRendererOpenGLES30 / kUnityGfxRendererOpenGLCore
// の何れかの値になります。
UnityGfxRenderer m_APIType;

// Unity側からdllの初期化/解放時に呼ばれる
void ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)
{
    // 初期化
    if (type == kUnityGfxDeviceEventInitialize)
    {
        CreateResources();
    }
    // 解放
    else if (type == kUnityGfxDeviceEventShutdown)
    {
        //@TODO: release resources
    }
}

const GLchar* commonAttribName[] =
{
    "a_vertex",
    "a_normal",
    "a_color",
};

enum
{
    COMMON_ATTRIB_VERTEX,
    COMMON_ATTRIB_NORMAL,
    COMMON_ATTRIB_COLOR,
    COMMON_ATTRIB_MAX,    
};

const int commonAttribIndex[] =
{
    COMMON_ATTRIB_VERTEX,
    COMMON_ATTRIB_NORMAL,
    COMMON_ATTRIB_COLOR,
};

const GLchar* commonUniformName[] =
{
    "u_ModelViewProj",
    "u_work0",
    "u_work1",
    "u_work2",
};

enum
{
    COMMON_UNIFORM_MODELVIEWPROJ,
    COMMON_UNIFORM_WORK0,
    COMMON_UNIFORM_WORK1,
    COMMON_UNIFORM_WORK2,

    COMMON_UNIFORM_MAX
};

const int commonUniformIndex[] =
{
    COMMON_UNIFORM_MODELVIEWPROJ,
    COMMON_UNIFORM_WORK0,
    COMMON_UNIFORM_WORK1,
    COMMON_UNIFORM_WORK2,
};

void CreateResources()
{
    m_Proj[0] = 1.0f;    m_Proj[4] = 0.0f;    m_Proj[8] = 0.0f;    m_Proj[12] = 0.0f;
    m_Proj[1] = 0.0f;    m_Proj[5] = 1.0f;    m_Proj[9] = 0.0f;    m_Proj[13] = 0.0f;
    m_Proj[2] = 0.0f;    m_Proj[6] = 0.0f;    m_Proj[10] = 1.0f;    m_Proj[14] = 0.0f;
    m_Proj[3] = 0.0f;    m_Proj[7] = 0.0f;    m_Proj[11] = 0.0f;    m_Proj[15] = 1.0f;

    m_View[0] = 1.0f;    m_View[4] = 0.0f;    m_View[8] = 0.0f;    m_View[12] = 0.0f;
    m_View[1] = 0.0f;    m_View[5] = 1.0f;    m_View[9] = 0.0f;    m_View[13] = 0.0f;
    m_View[2] = 0.0f;    m_View[6] = 0.0f;    m_View[10] = 1.0f;    m_View[14] = 0.0f;
    m_View[3] = 0.0f;    m_View[7] = 0.0f;    m_View[11] = 0.0f;    m_View[15] = 1.0f;

    if (m_APIType == kUnityGfxRendererOpenGLCore)
    {
        glewExperimental = GL_TRUE;
        glewInit();
        glGetError(); // glewInitで生成されたエラーを初期化する
    }

    // シェーダー生成
    if (m_APIType == kUnityGfxRendererOpenGLES20)
    {
        m_ShaderTbl = new Shader(c_VProgTextGLES2, c_FShaderTextGLES2, commonAttribIndex, commonAttribName, COMMON_ATTRIB_MAX, commonUniformIndex, commonUniformName, COMMON_UNIFORM_MAX, m_APIType);
    }
    else if (m_APIType == kUnityGfxRendererOpenGLES30)
    {
        m_ShaderTbl = new Shader(c_VProgTextGLES3, c_FShaderTextGLES3, commonAttribIndex, commonAttribName, COMMON_ATTRIB_MAX, commonUniformIndex, commonUniformName, COMMON_UNIFORM_MAX, m_APIType);
    }
#if SUPPORT_OPENGL_CORE
    else if (m_APIType == kUnityGfxRendererOpenGLCore)
    {
        m_ShaderTbl = new Shader(c_VProgTextGLCore, c_FShaderTextGLCore, commonAttribIndex, commonAttribName, COMMON_ATTRIB_MAX, commonUniformIndex, commonUniformName, COMMON_UNIFORM_MAX, m_APIType);
    }
#endif // if SUPPORT_OPENGL_CORE
}

void    FillRect(int x, int y, int width, int height)
{
    float    pVerCoord[12];

    // 頂点の設定
    pVerCoord[0] = pVerCoord[3] = (float)x;
    pVerCoord[1] = pVerCoord[7] = (float)y;
    pVerCoord[4] = pVerCoord[10] = (float)(y + height);
    pVerCoord[6] = pVerCoord[9] = (float)(x + width);
    pVerCoord[2] = pVerCoord[5] = pVerCoord[8] = pVerCoord[11] = m_Prio;
    m_Prio += 0.0001f; // DEPTH_ADD

    int alpha = ( (m_Color >> 24) & 0xFF )
    if (alpha < 0xFF)
    {
        // 半透明
        glBlendEquation(GL_FUNC_ADD_OES);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    DrawPoly(pVerCoord, m_Color, GL_TRIANGLE_STRIP, 4);
}

void    DrawPoly(float *vertex, int color, GLenum type, int count)
{
    // シェーダーの取得
    OGLShader *pShader = m_ShaderTbl;
    if (pShader == NULL) return;

    // modelViewProj = m_View * m_Proj
    float    modelViewProj[ 16 ];
    modelViewProj[0] = m_View[0] * m_Proj[0] + m_View[1] * m_Proj[4] + m_View[2] * m_Proj[8] + m_View[3] * m_Proj[12];
    modelViewProj[1] = m_View[0] * m_Proj[1] + m_View[1] * m_Proj[5] + m_View[2] * m_Proj[9] + m_View[3] * m_Proj[13];
    modelViewProj[2] = m_View[0] * m_Proj[2] + m_View[1] * m_Proj[6] + m_View[2] * m_Proj[10] + m_View[3] * m_Proj[14];
    modelViewProj[3] = m_View[0] * m_Proj[3] + m_View[1] * m_Proj[7] + m_View[2] * m_Proj[11] + m_View[3] * m_Proj[15];
    modelViewProj[4] = m_View[4] * m_Proj[0] + m_View[5] * m_Proj[4] + m_View[6] * m_Proj[8] + m_View[7] * m_Proj[12];
    modelViewProj[5] = m_View[4] * m_Proj[1] + m_View[5] * m_Proj[5] + m_View[6] * m_Proj[9] + m_View[7] * m_Proj[13];
    modelViewProj[6] = m_View[4] * m_Proj[2] + m_View[5] * m_Proj[6] + m_View[6] * m_Proj[10] + m_View[7] * m_Proj[14];
    modelViewProj[7] = m_View[4] * m_Proj[3] + m_View[5] * m_Proj[7] + m_View[6] * m_Proj[11] + m_View[7] * m_Proj[15];
    modelViewProj[8] = m_View[8] * m_Proj[0] + m_View[9] * m_Proj[4] + m_View[10] * m_Proj[8] + m_View[11] * m_Proj[12];
    modelViewProj[9] = m_View[8] * m_Proj[1] + m_View[9] * m_Proj[5] + m_View[10] * m_Proj[9] + m_View[11] * m_Proj[13];
    modelViewProj[10] = m_View[8] * m_Proj[2] + m_View[9] * m_Proj[6] + m_View[10] * m_Proj[10] + m_View[11] * m_Proj[14];
    modelViewProj[11] = m_View[8] * m_Proj[3] + m_View[9] * m_Proj[7] + m_View[10] * m_Proj[11] + m_View[11] * m_Proj[15];
    modelViewProj[12] = m_View[12] * m_Proj[0] + m_View[13] * m_Proj[4] + m_View[14] * m_Proj[8] + m_View[15] * m_Proj[12];
    modelViewProj[13] = m_View[12] * m_Proj[1] + m_View[13] * m_Proj[5] + m_View[14] * m_Proj[9] + m_View[15] * m_Proj[13];
    modelViewProj[14] = m_View[12] * m_Proj[2] + m_View[13] * m_Proj[6] + m_View[14] * m_Proj[10] + m_View[15] * m_Proj[14];
    modelViewProj[15] = m_View[12] * m_Proj[3] + m_View[13] * m_Proj[7] + m_View[14] * m_Proj[11] + m_View[15] * m_Proj[15];

    // 有効化
    pShader->useShader();

    // マトリックスの設定
    glUniformMatrix4fv( pShader->m_piGLUniform[COMMON_UNIFORM_MODELVIEWPROJ], 1, GL_FALSE, modelViewProj.m );

    // Core profile needs VAOs, setup one
#if SUPPORT_OPENGL_CORE
    GLuint m_VertexArray;
    if (m_APIType == kUnityGfxRendererOpenGLCore)
    {
        glGenVertexArrays(1, &m_VertexArray);
        glBindVertexArray(m_VertexArray);
    }
#endif // if SUPPORT_OPENGL_CORE

    // 頂点の設定
    glEnableVertexAttribArray( pShader->m_piGLAttrib[COMMON_ATTRIB_VERTEX] );
    glVertexAttribPointer( pShader->m_piGLAttrib[COMMON_ATTRIB_VERTEX], 3, GL_FLOAT, GL_FALSE, 0, vertex );

    // 頂点カラー設定
    glDisableVertexAttribArray( pShader->m_piGLAttrib[COMMON_ATTRIB_COLOR] );
    glVertexAttrib4f( pShader->m_piGLAttrib[COMMON_ATTRIB_COLOR], ( ( (color >> 16) & 0xFF ) * 0.0039f ), ( ( (color >>  8) & 0xFF ) * 0.0039f ), ( ( (color >>  0) & 0xFF ) * 0.0039f ), ( ( (color >> 24) & 0xFF ) * 0.0039f ) );

    // Cleanup VAO
#if SUPPORT_OPENGL_CORE
    if (m_APIType == kUnityGfxRendererOpenGLCore)
    {
        glBindVertexArray(m_VertexArray);
    }
#endif
    // 描画
    glDrawArrays( type, 0, count );
}

問題点

上記の処理で

FillRect(0, 0, 1920, 1080);


を呼び出した際に、DrawPoly()関数の

// 頂点の設定
glEnableVertexAttribArray( pShader->m_piGLAttrib[COMMON_ATTRIB_VERTEX] );
glVertexAttribPointer( pShader->m_piGLAttrib[COMMON_ATTRIB_VERTEX], 3, GL_FLOAT, GL_FALSE, 0, vertex );


下側のglVertexAttribPointer()を呼び出したタイミングで
「GL_INVALID_OPERATION: Operation illegal in current state」が発生します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る