2

こんにちは、

問題は、OpenGL タイル グリッドを表示する Win7 (C#、VS2010) で記述されたコードが、Mac OS X (C#、MonoDevelop) では異なって表示されることです。現在、各タイルは個別にレンダリングされており、x/y オフセットは実際には頂点情報に格納されています。タイルは次のように作成されます。

private void BuildTile()
{
    Vector3[] vertices = new Vector3[4];
    Vector2[] uvs = new Vector2[] { new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 1), new Vector2(1, 0) };
    int[] indices = new int[] { 1, 0, 2, 1, 2, 3 };

    // build vertex list based on position
    vertices[0] = new Vector3(Location.X, Location.Y + 1, 0);
    vertices[1] = new Vector3(Location.X, Location.Y, 0);
    vertices[2] = new Vector3(Location.X + 1, Location.Y + 1, 0);
    vertices[3] = new Vector3(Location.X + 1, Location.Y, 0);

    VBO<Vector3> vertex = new VBO<Vector3>(vertices, BufferTarget.ArrayBuffer, BufferUsageHint.StaticRead);
    VBO<Vector2> uv = new VBO<Vector2>(uvs, BufferTarget.ArrayBuffer, BufferUsageHint.StaticRead);
    VBO<int> element = new VBO<int>(indices, BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticRead);

    VAO = new VAO(ShaderProgram, vertex, uv, element);
}

Mac OS X は OpenGL 3 をサポートしていないため、ドローコールが発生するたびに VAO オブジェクトが属性をバインドします。

    public void BindAttributes()
    {
        if (vertex == null) throw new Exception("Error binding attributes.  No vertices were supplied.");
        if (element == null) throw new Exception("Error binding attributes.  No element array was supplied.");
        uint array = 0;

        Gl.EnableVertexAttribArray(array);
        Gl.BindAttribLocation(Program.ProgramID, array, "in_position");
        Gl.BindBuffer(vertex.BufferTarget, vertex.vboID);
        Gl.VertexAttribPointer(array++, vertex.Size, vertex.PointerType, true, 12, new IntPtr(0));

        Gl.EnableVertexAttribArray(array);
        Gl.BindAttribLocation(Program.ProgramID, array, "in_uv");
        Gl.BindBuffer(uv.BufferTarget, uv.vboID);
        Gl.VertexAttribPointer(array++, uv.Size, uv.PointerType, true, 8, new IntPtr(0));

        Gl.BindBuffer(BufferTarget.ElementArrayBuffer, element.vboID);
    }

シェーダーは非常に簡単です。頂点シェーダー:

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;

attribute vec3 in_position;
attribute vec2 in_uv;

varying vec2 uv;

void main(void)
{
  uv = in_uv;

  gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
}

フラグメント シェーダー:

uniform sampler2D active_texture;

varying vec2 uv;

void main(void)
{
  gl_FragColor = texture2D(active_texture, uv);
}

問題は、Mac OS X バージョンがすべてのタイルをオーバーレイしていることです。100 個のタイルはすべて、最初のタイルの位置に積み重ねられます。ただし、Win7 では、タイルは予想どおり 10x10 グリッドに分散されます。なぜこれが起こっているのか誰にも分かりますか?頂点データを調べたところ、Mac OS X と Win7 の両方でオフセットが格納されており、VBO ID は一意であり、正しい VBO がバインドされています。属性をバインドする方法に問題があるに違いないと推測していますが、問題は見当たりません。OpenGL 2 と 3 が頂点属性を処理する方法に面白い違いはありますか?

ありがとうございます。問題を見つけるために私のコードが必要な場合はお知らせください。

注:頂点オフセットをシェーダーに (ユニフォームとして) 格納し、タイルごとに更新することができます。これはうまくいきます!そのため、最初の VBO のみがバインドされ、100 回レンダリングされていると考えるようになりました。

4

1 に答える 1

1

プログラムをリンクした後、属性の場所をバインドできないことが判明しました。ただし、何らかの理由で、私のWin7 PC(Radeonドライバーを搭載)はそれを許可することにしました。実際に属性をバインドする方法は次のとおりです。

public void BindAttributes()
{
    if (vertex == null) throw new Exception("Error binding attributes.  No vertices were supplied.");
    if (element == null) throw new Exception("Error binding attributes.  No element array was supplied.");

    uint loc = (uint)Gl.GetAttribLocation(Program.ProgramID, "in_position");
    Gl.EnableVertexAttribArray(loc);
    Gl.BindBuffer(vertex.BufferTarget, vertex.vboID);
    Gl.VertexAttribPointer(loc, vertex.Size, vertex.PointerType, true, 12, new IntPtr(0));


    loc = (uint)Gl.GetAttribLocation(Program.ProgramID, "in_uv");
    Gl.EnableVertexAttribArray(loc);
    Gl.BindBuffer(uv.BufferTarget, uv.vboID);
    Gl.VertexAttribPointer(loc, uv.Size, uv.PointerType, true, 8, new IntPtr(0));

    Gl.BindBuffer(BufferTarget.ElementArrayBuffer, element.vboID);
}
于 2011-01-17T00:26:44.183 に答える