实例化时每个对象的不同纹理坐标
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);
}
如果你真的在使用实例化来绘制多个四边形,那么显然你必须有:
- 包含单个四边形位置的缓冲区对象。
- 一些获取每个实例数据以抵消这些位置的机制。
你的问题就是你的期望。你正在用四边形实例化。这意味着您的渲染调用仅使用 4-6 个顶点。对于您的 纹理坐标 和您的位置,这将同样适用。
您的问题是您将每个实例数据视为每个顶点数据。纹理坐标随每个实例而变化;因此,它们是每个实例的数据。但是您没有让它们使用实例化,因此它们被视为逐顶点数据。所以只会使用前 6 个顶点的纹理坐标。
当然,你也不能真正让它们成为每个实例的数据。每个顶点+实例对都有一个单独的纹理坐标值。并且实例化不提供直接执行此操作的方法。相反,您必须使用 gl_VertexID
和 gl_InstanceID
直接从缓冲区对象中获取数据; SSBO 或缓冲区纹理。
因此,您的问题确实是这样的:
I'm using instancing to draw the same quad multiple times
停止这样做。这不值得。只需将位置放在 CPU 缓冲区数据中。使用proper buffer streaming techniques,您的表现将是合理的。
我正在使用实例多次绘制同一个四边形,用于游戏引擎中的地板。每个楼层都有不同的纹理坐标,具体取决于它的大小,我的问题是所有实例都使用第一个实例的纹理坐标。
这就是我缓冲数据的方式。
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);
}
如果你真的在使用实例化来绘制多个四边形,那么显然你必须有:
- 包含单个四边形位置的缓冲区对象。
- 一些获取每个实例数据以抵消这些位置的机制。
你的问题就是你的期望。你正在用四边形实例化。这意味着您的渲染调用仅使用 4-6 个顶点。对于您的 纹理坐标 和您的位置,这将同样适用。
您的问题是您将每个实例数据视为每个顶点数据。纹理坐标随每个实例而变化;因此,它们是每个实例的数据。但是您没有让它们使用实例化,因此它们被视为逐顶点数据。所以只会使用前 6 个顶点的纹理坐标。
当然,你也不能真正让它们成为每个实例的数据。每个顶点+实例对都有一个单独的纹理坐标值。并且实例化不提供直接执行此操作的方法。相反,您必须使用 gl_VertexID
和 gl_InstanceID
直接从缓冲区对象中获取数据; SSBO 或缓冲区纹理。
因此,您的问题确实是这样的:
I'm using instancing to draw the same quad multiple times
停止这样做。这不值得。只需将位置放在 CPU 缓冲区数据中。使用proper buffer streaming techniques,您的表现将是合理的。