如何使用新的OperGL/OpenTk API渲染示例

wpcxdonn  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(334)

我试图将本教程中的信息(Advanced-OpenGL/Instancing)和这些答案(How to render using 2 VBO)(New API Clarification)结合在一起,以便渲染正方形的示例,通过ArrayBuffer将每个示例的模型矩阵提供给着色器。我以下面的代码结束。我切片并测试了任何部分,问题似乎是模型矩阵本身没有正确传递到着色器。我正在使用Visual Studio中的OpenTK。

为了简单和调试,池只包含一个正方形,所以我仍然没有除数问题或其他我仍然不能处理的有趣的事情。

我的顶点数据数组包含位置的3个浮点数和颜色的4个浮点数(Stride=7倍浮点大小)。

我使用附加代码得到的结果是:

  • 如果我删除顶点着色器中的模型倍增,我会得到我所期望的,一个红色正方形(渲染为两个三角形)和一个绿色边框(渲染为线环)。
  • 如果我更改着色器并乘以模型矩阵,我会在屏幕中心上方看到一条红线,它的长度会随着时间的推移而变化。动画很有意义,因为模拟旋转的是正方形,因此Angular 会定期更新,因此计算的模型矩阵也会发生变化。另一个很好的结果,因为我实际上是在将动态数据发送到着色器。然而,我不能让我原来的正方形旋转和平移。

有什么线索吗?非常感谢。

顶点明暗器:


# version 430 core

layout (location = 0) in vec3  aPos;
layout (location = 1) in vec4  aCol;
layout (location = 2) in mat4 imodel;
out vec4 fColor;
uniform mat4 view;
uniform mat4 projection;

void main() {
    fColor = aCol;
    gl_Position = vec4(aPos, 1.0) * imodel * view * projection;
}

片段着色器:


# version 430 core

in vec4 fColor;
out vec4 FragColor;

void main() {
    FragColor = fColor;
}

OnLoad代码段(初始化):

InstanceVBO = GL.GenBuffer();
GL.GenBuffers(2, VBO);

GL.BindBuffer(BufferTarget.ArrayBuffer, VBO[0]);
GL.BufferData(BufferTarget.ArrayBuffer,
    7 * LineLoopVertCount  * sizeof(float), 
    LineLoopVertData, BufferUsageHint.StaticDraw);

GL.BindBuffer(BufferTarget.ArrayBuffer, VBO[1]);
GL.BufferData(BufferTarget.ArrayBuffer,
    7 * TrianglesVertCount * sizeof(float),
    TrianglesVertData, BufferUsageHint.StaticDraw);

GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

// VAO SETUP

VAO = GL.GenVertexArray();
GL.BindVertexArray(VAO);

// Position
GL.EnableVertexAttribArray(0);
GL.VertexAttribFormat(0, 3, VertexAttribType.Float, false, 0);
GL.VertexArrayAttribBinding(VAO, 0, 0);

// COlor
GL.EnableVertexAttribArray(1);
GL.VertexAttribFormat(1, 4, VertexAttribType.Float, false, 3 * sizeof(float));
GL.VertexArrayAttribBinding(VAO, 1, 0);

int vec4Size = 4;
GL.EnableVertexAttribArray(2);
GL.VertexAttribFormat(2, 4, VertexAttribType.Float, false, 0 * vec4Size * sizeof(float));
GL.VertexAttribFormat(3, 4, VertexAttribType.Float, false, 1 * vec4Size * sizeof(float));
GL.VertexAttribFormat(4, 4, VertexAttribType.Float, false, 2 * vec4Size * sizeof(float));
GL.VertexAttribFormat(5, 4, VertexAttribType.Float, false, 3 * vec4Size * sizeof(float));

GL.VertexAttribDivisor(2, 1);
GL.VertexAttribDivisor(3, 1);
GL.VertexAttribDivisor(4, 1);
GL.VertexAttribDivisor(5, 1);

GL.VertexArrayAttribBinding(VAO, 2, 1);

GL.BindVertexArray(0);

OnFrameRender代码片断:

shader.Use();
shader.SetMatrix4("view", cameraViewMatrix);
shader.SetMatrix4("projection", cameraProjectionMatrix);

int mat4Size = 16;

for (int i = 0; i < simulation.poolCount; i++)
{
    modelMatrix[i] = Matrix4.CreateFromAxisAngle(
        this.RotationAxis, simulation.pool[i].Angle);

    modelMatrix[i] = matrix[i] * Matrix4.CreateTranslation(new Vector3(
        simulation.pool[i].Position.X,
        simulation.pool[i].Position.Y,
        0f));

    //modelMatrix[i] = Matrix4.Identity;
}

// Copy model matrices into the VBO
// ----------------------------------------
GL.BindBuffer(BufferTarget.ArrayBuffer, InstanceVBO);
GL.BufferData(BufferTarget.ArrayBuffer,
    simulation.poolCount * mat4Size * sizeof(float),
    modelMatrix, BufferUsageHint.DynamicDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
// ----------------------------------------

GL.BindVertexArray(VAO);

GL.BindVertexBuffer(1, InstanceVBO, IntPtr.Zero, mat4Size * sizeof(float));

GL.BindVertexBuffer(0, VBO[0], IntPtr.Zero, 7 * sizeof(float));
GL.DrawArraysInstanced(PrimitiveType.LineLoop, 0, LineLoopVertCount, simulation.poolCount);

GL.BindVertexBuffer(0, lifeFormVBO[1], IntPtr.Zero, lifeFormTrianglesFStride * sizeof(float));
GL.DrawArraysInstanced(PrimitiveType.Triangles, 0, TrianglesVertCount, simulation.poolCount);

GL.BindVertexArray(0);
jpfvwuh4

jpfvwuh41#

这里有很多错误之处。

首先,您没有启用2之后的任何属性数组,即使着色器显示您的读数也是3-5。同样,您不需要为2之后的任何数组设置属性绑定。

但您更大的问题是使用glVertexAttribDivisor。对于你想要做的事情来说,这是一个“错误的功能”。这是设置除数的旧API。

在单独的属性格式中,除数是缓冲区绑定的一部分,而不是顶点属性。因此,需要用glVertexBindingDivisor设置除数,给它的索引是您打算将缓冲区绑定到的索引。它应该是1。

因此,您的代码应该如下所示:

int vec4Size = 4;
for(int ix = 0; ix < 4; ++ix)
{
  int attribIx = 2 + ix;
  GL.EnableVertexAttribArray(attribIx);
  GL.VertexAttribFormat(attribIx, 4, VertexAttribType.Float, false, ix * vec4Size * sizeof(float));
  GL.VertexArrayAttribBinding(VAO, attribIx, 1); //All use the same buffer binding
}

GL.VertexBindingDivisor(1, 1);

相关问题