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

Different texture co-ordinates per object when instancing

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

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

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. 包含单个四边形位置的缓冲区对象。
  2. 一些获取每个实例数据以抵消这些位置的机制。

你的问题就是你的期望。你正在用四边形实例化。这意味着您的渲染调用仅使用 4-6 个顶点。对于您的 纹理坐标 和您的位置,这将同样适用。

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

当然,你也不能真正让它们成为每个实例的数据。每个顶点+实例对都有一个单独的纹理坐标值。并且实例化不提供直接执行此操作的方法。相反,您必须使用 gl_VertexIDgl_InstanceID 直接从缓冲区对象中获取数据; SSBO 或缓冲区纹理。

因此,您的问题确实是这样的:

I'm using instancing to draw the same quad multiple times

停止这样做。这不值得。只需将位置放在 CPU 缓冲区数据中。使用proper buffer streaming techniques,您的表现将是合理的。