[英]OpenTK (OpenGL) correct usage of BufferData and BufferSubData
[英]OpenTK (OpenGL) How to correctly use BufferSubData and DrawElements with multiple Objects
我試圖實現一個僅使用一個 VBO 和一個 EBO 來存儲所有對象頂點和索引的渲染器。 為此,我找到了一些教程,最后得出了一個相當不錯的結果。
問題是它只適用於一個單一的對象。 一旦我想添加另一個,渲染就會顯示奇怪的行為。
你能幫我解決這個問題嗎?
您可以在此處找到完整代碼: https : //github.com/BanditBloodwyn/TerritorySimulator 。 重要的類是:
這是Renderer中的初始化方法:
public void Initialize(GLShape[] shapeArray)
{
Shapes = shapeArray;
GL.Enable(EnableCap.DepthTest);
GL.ClearColor(0.0f, 0.0f, 0.10f, 1.0f);
InitializeBuffers(Shapes);
InitializeVertexArrayObject(Shapes);
SetupShader();
BindBuffers();
}
子方法如下所示。
private void InitializeBuffers(GLShape[] shapeArray)
{
int vertexBufferSize = shapeArray.Sum(shape => shape.VertexBufferSize);
int indexBufferSize = shapeArray.Sum(shape => shape.IndexBufferSize);
// Vertex buffer
vertexBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, vertexBufferSize, (IntPtr)0, BufferUsageHint.StaticDraw);
IntPtr offset = (IntPtr)0;
foreach (GLShape shape in shapeArray)
{
GL.BufferSubData(BufferTarget.ArrayBuffer, offset, shape.VertexBufferSize, shape.Vertices);
offset += shape.VertexBufferSize;
}
// Element buffer
elementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, indexBufferSize, (IntPtr)0, BufferUsageHint.StaticDraw);
offset = (IntPtr)0;
foreach (GLShape shape in shapeArray)
{
GL.BufferSubData(BufferTarget.ElementArrayBuffer, offset, shape.IndexBufferSize, shape.Indices);
offset += shape.IndexBufferSize;
}
}
private void InitializeVertexArrayObject(GLShape[] shapeArray)
{
foreach (GLShape shape in shapeArray)
{
shape.VertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(shape.VertexArrayObject);
}
}
private void SetupShader()
{
// shader
string vertexPath = Path.Combine(Environment.CurrentDirectory, @"GLSL\", "Vertex.vert");
string fragmentPath = Path.Combine(Environment.CurrentDirectory, @"GLSL\", "Fragment.frag");
shader = new Shader(vertexPath, fragmentPath);
shader.Use();
int vertexLocation = shader.GetAttribLocation("aPosition");
GL.EnableVertexAttribArray(vertexLocation);
GL.VertexAttribPointer(
vertexLocation,
3,
VertexAttribPointerType.Float,
false,
5 * sizeof(float),
0);
int texCoordLocation = shader.GetAttribLocation("aTexCoord");
GL.EnableVertexAttribArray(texCoordLocation);
GL.VertexAttribPointer(
texCoordLocation,
2,
VertexAttribPointerType.Float,
false,
5 * sizeof(float),
3 * sizeof(float));
shader.SetInt("texture0", 0);
shader.SetInt("texture1", 1);
}
private void BindBuffers()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferObject);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBufferObject);
}
渲染函數本身看起來像這樣。
public void Render()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (Shapes == null || Shapes.Length == 0)
return;
IntPtr offset = (IntPtr)0;
foreach (GLShape shape in Shapes)
{
foreach (var texture in shape.Textures)
{
if (LayerConfiguration.ShowEarthTexture)
texture.Key.Use(texture.Value);
else
texture.Key.MakeTransparent(texture.Value);
}
ApplyModelTransforms(shape, out Matrix4 model);
shader.SetMatrix4("model", model);
shader.SetMatrix4("view", Camera.GetViewMatrix());
GL.DrawElements(PrimitiveType.Triangles, shape.Indices.Length, DrawElementsType.UnsignedInt, offset);
offset += shape.IndexBufferSize;
}
shader.SetMatrix4("projection", Camera.GetProjectionMatrix());
shader.Use();
}
一旦我想添加另一個,渲染就會顯示奇怪的行為
當然,因為第二個和以下對象的索引是錯誤的。 您需要將先前網格的頂點總和添加到索引中。 第一個網格的索引必須添加 0,第二個網格的索引必須添加第一個網格的頂點數,第三個網格的索引必須添加頂點的總和第一個和第二個網格,...
offset = (IntPtr)0;
uint firstVertexIndex = 0;
foreach (GLShape shape in shapeArray)
{
var indexArray = shape.Indices.Select(index => index + firstVertexIndex).ToArray();
GL.BufferSubData(
BufferTarget.ElementArrayBuffer, offset, shape.IndexBufferSize, indexArray);
offset += shape.IndexBufferSize;
firstVertexIndex += (uint)(shape.VertexBufferSize / (5 * sizeof(float)));
}
完整方法InitializeBuffers
:
private void InitializeBuffers(GLShape[] shapeArray)
{
int vertexBufferSize = shapeArray.Sum(shape => shape.VertexBufferSize);
int indexBufferSize = shapeArray.Sum(shape => shape.IndexBufferSize);
// Vertex buffer
vertexBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, vertexBufferSize, (IntPtr)0, BufferUsageHint.StaticDraw);
IntPtr offset = (IntPtr)0;
foreach (GLShape shape in shapeArray)
{
GL.BufferSubData(BufferTarget.ArrayBuffer, offset, shape.VertexBufferSize, shape.Vertices);
offset += shape.VertexBufferSize;
}
// Element buffer
elementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, indexBufferSize, (IntPtr)0, BufferUsageHint.StaticDraw);
offset = (IntPtr)0;
uint firstVertexIndex = 0;
foreach (GLShape shape in shapeArray)
{
var indexArray = shape.Indices.Select(index => index + firstVertexIndex).ToArray();
GL.BufferSubData(BufferTarget.ElementArrayBuffer, offset, shape.IndexBufferSize, indexArray);
offset += shape.IndexBufferSize;
firstVertexIndex += (uint)(shape.VertexBufferSize / (5 * sizeof(float)));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.