实例化时每个对象的不同纹理坐标

时间:2017-07-05 10:57:49

标签: opengl glsl opentk

我使用实例化多次绘制相同的四边形,用于游戏引擎中的地板。每个楼层都有不同的纹理坐标,具体取决于它的大小,我的问题是所有实例都使用第一个实例的纹理坐标。

enter image description here

这就是我缓冲数据的方式。

public static void UploadTextureCooridnates()
{
    // Construct texture co-ordinate array
    List<Vector2> textureCoords = new List<Vector2>();
    foreach (Floor floor in Floor.collection)
    {
        float xCoordLeft = 0;
        float yCoordBottom = 0;
        float yCoordTop = floor.scale.X;
        float xCoordRight = floor.scale.Z;

        textureCoords.Add(new Vector2(xCoordLeft, yCoordBottom));
        textureCoords.Add(new Vector2(xCoordRight, yCoordBottom));
        textureCoords.Add(new Vector2(xCoordRight, yCoordTop));

        textureCoords.Add(new Vector2(xCoordLeft, yCoordBottom));
        textureCoords.Add(new Vector2(xCoordRight, yCoordTop));
        textureCoords.Add(new Vector2(xCoordLeft, yCoordTop));
    }    
    Vector2[] texCoords = textureCoords.ToArray();

    // Buffer data
    GL.BindBuffer(BufferTarget.ArrayBuffer, VBOtexcoordsInstanced);
    GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(texCoords.Length * Vector2.SizeInBytes), texCoords, BufferUsageHint.StaticDraw);
    GL.EnableVertexAttribArray(1);
    GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0);
    GL.VertexAttribDivisor(1, 0);
}

1 个答案:

答案 0 :(得分:3)

如果你真的使用实例来绘制多个四边形,那么显然你必须:

  1. 包含单个四元组位置的缓冲区对象。
  2. 获取每个实例数据以抵消这些位置的一些机制。
  3. 你的问题是你的期望。你是用四边形进行实例化的。这意味着您的渲染调用仅使用4-6个顶点。对于您的纹理坐标,这与您的位置一样。

    您的问题是您将每个实例数据视为每个顶点数据。纹理坐标随每个实例而变化;因此,它们是每个实例的数据。但是你没有使用实例化,所以它们被视为每顶点数据。因此,只使用前6个顶点的纹理坐标。

    当然,你也无法真正制作每个实例的数据。每个顶点+实例对都有一个单独的纹理坐标值。实例化并没有提供直接这样做的方法。相反,您必须使用gl_VertexIDgl_InstanceID直接从缓冲区对象获取数据; SSBO或缓冲区纹理。

    因此,你的问题确实如此:

      

    我正在使用实例化多次绘制相同的四元组

    停止这样做。这不值得。只需将位置放在CPU缓冲区数据中即可。使用适当的缓冲流技术,您的表现将是合理的。