OS X 和 Win7 之间的 VBO 差异?

发布于 2024-10-12 11:01:42 字数 2864 浏览 6 评论 0原文

下午好,

问题是在 Win7(C#、VS2010)上编写的显示 OpenGL 平铺网格的代码在 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 次。

Good afternoon,

The problem is that code written on Win7 (C#, VS2010) that displays an OpenGL tile grid displays differently in Mac OS X (C#, MonoDevelop). Each tile is currently rendered separately and the x/y offset are actually stored in the vertex information. The tile is built like so:

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);
}

Since Mac OS X does not support OpenGL 3, the VAO object binds the attributes every time the draw call occurs.

    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);
    }

The shader is pretty straight forward. Vertex shader:

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);
}

Fragment shader:

uniform sampler2D active_texture;

varying vec2 uv;

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

The issue is that the Mac OS X version is overlaying all of the tiles. All 100 tiles will be stacked on top of each other in the position of the first tile. However, on Win7 the tiles will be distributed in a 10x10 grid as expected. Does anyone have any idea why this might be happening? I looked at the vertex data and it is storing the offsets on both Mac OS X and Win7, and the VBO IDs are unique, and the right VBOs are being bound. I'm guessing there must be an issue with my method for binding the attributes, but I cannot see a problem. Is there some funny difference between how OpenGL 2 and 3 handle vertex attributes?

Thanks, and let me know if you need anymore of my code to help me find the issue.

Note: I can store the vertex offset in the shader (as a uniform) and update it it per tile. This works! So, I'm lead to believe that only the first VBO is being bound, and is just being rendered 100 times.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无人问我粥可暖 2024-10-19 11:01:42

事实证明,链接程序后无法绑定属性位置。然而,无论出于何种原因,我的 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);
}

It turns out that you cannot bind an attribute location after linking the program. However, for whatever reason my Win7 PC (with Radeon drivers) decided to allow it. Here's how you should actually bind your attributes.

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文