9

ビデオフレーム (Mac の場合) をカスタム フレームバッファ オブジェクトにレンダリングするクラスを作成しました。入力として YUV テクスチャがあり、入力として 3 つの長方形テクスチャ (Y、U、および V プレーンごとに 1 つ、データは GL_TEXTURE_RECTANGLE_ARB、GL_LUMINANCE、および GL_UNSIGNED_BYTE を使用して glTexSubImage2D によってアップロードされる) を受け取るフラグメント シェーダを正常に作成しました。レンダリングする前に、アクティブなテクスチャを 3 つの異なるテクスチャ ユニット (0、1、2) に設定し、それぞれにテクスチャをバインドします。パフォーマンス上の理由から、GL_APPLE_client_storage と GL_APPLE_texture_range を使用しました。次に、glUseProgram(myProg)、glBegin(GL_QUADS) ... glEnd() を使用してレンダリングしました。

それはうまく機能し、期待どおりの結果が得られました (ちらつき効果は別として、これは、2 つの異なるスレッドで 2 つの異なる GL コンテキストを使用したという事実に関係していると思います。 [それは後で別の質問のトピックです])。とにかく、頂点シェーダーも追加してコードをさらに改善することにしました。これにより、glBegin/glEnd をスキップできるようになりました。これは時代遅れであり、とにかく避けるべきです。

次のステップとして、2 つのバッファ オブジェクトを作成しました。1 つは頂点用、もう 1 つはテクスチャ座標用です。

      const GLsizeiptr posSize = 4 * 4 * sizeof(GLfloat);
      const GLfloat posData[] =
      {
            -1.0f, -1.0f, -1.0f, 1.0f,
             1.0f, -1.0f, -1.0f, 1.0f,
             1.0f,  1.0f, -1.0f, 1.0f,
            -1.0f,  1.0f, -1.0f, 1.0f
        };

        const GLsizeiptr texCoordSize = 4 * 2 * sizeof(GLfloat);
        const GLfloat texCoordData[] =
        {
            0.0, 0.0,
            1.0, 0.0,
            1.0, 1.0,
            0.0, 1.0
        };

    glGenBuffers(1, &m_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, posSize, posData, GL_STATIC_DRAW);

    glGenBuffers(1, &m_texCoordBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, texCoordSize, texCoordData, GL_STATIC_DRAW);

次に、シェーダーをロードした後、頂点シェーダーの属性の場所を取得しようとします。

        m_attributeTexCoord = glGetAttribLocation( m_shaderProgram, "texCoord");
        m_attributePos = glGetAttribLocation( m_shaderProgram, "position");

これにより、texCoord が 0 になり、位置が 1 になり、問題ないようです。

属性を取得した後、私も呼び出します

        glEnableVertexAttribArray(m_attributePos);
        glEnableVertexAttribArray(m_attributeTexCoord);

(私はそれを一度だけ行っていますか、それともすべての glVertexAttribPointer と glDrawArrays の前に行う必要がありますか?テクスチャ ユニットごとに行う必要がありますか?またはシェーダーが glProgram でアクティブ化されている間に行う必要がありますか?それとも、どこでも行うことができますか?)

その後、glBegin/glEnd を置き換えるようにレンダリング コードを変更しました。

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_Y);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_U);

        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texID_V);

        glUseProgram(myShaderProgID);

        // new method with shaders and buffers
        glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
        glVertexAttribPointer(m_attributePos, 4, GL_FLOAT, GL_FALSE, 0, NULL);
        glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
        glVertexAttribPointer(m_attributeTexCoord, 2, GL_FLOAT, GL_FALSE, 0, NULL);
        glDrawArrays(GL_QUADS, 0, 4);

        glUseProgram(0);

しかし、コードをこれに変更して以来、結果として常に黒い画面しか表示されません。だから私はいくつかの簡単な手順を欠いていると思います.glEnable/glDisableやいくつかの設定を適切に行っているかもしれません. 参考までに、頂点シェーダーは次のとおりです。

#version 110
attribute vec2 texCoord;
attribute vec4 position;

// the tex coords for the fragment shader
varying vec2 texCoordY;
varying vec2 texCoordUV;

//the shader entry point is the main method
void main()
{   
    texCoordY = texCoord;
    texCoordUV = texCoordY * 0.5; // U and V are only half the size of Y texture
    gl_Position = gl_ModelViewProjectionMatrix * position;
}

私の推測では、ここで明らかな何かが欠けているか、進行中のプロセスをまだ十分に理解していないだけです。OpenGLShaderBuilder も使用してみましたが、フラグメント シェーダーの元のコードを正しく取得するのに役立ちました (これが、ここに投稿していない理由です)。とにかく position/texCoord 属性がわからない場合、どのように出力を生成するかを知ることができますか?)

4

1 に答える 1

2

すべての行を詳しく調べたわけではありませんが、あなたの論理はほとんど正しいと思います。欠けているのはglEnableVertexAttribArrayです。glDrawArrays を呼び出す前に、両方の頂点属性を有効にする必要があります。

于 2012-05-18T07:45:00.070 に答える