我正在尝试在 opentk 中实现索引缓冲区对象,但不知道在绘制东西时如何实际使用它
i'm trying to implement index buffer object in opentk but don't know how to actually use it when drawing things
我正在尝试使用索引缓冲区,但不知道如何使用
我真的不知道我应该尝试什么。
none 的教程确实显示了与我的代码类似的任何内容,这主要是我遇到问题的原因。我可能不得不重写立方体顶点数组创建器。 (换句话说,也许我不应该把 opengl 推到一些现成的代码中)现在我只启用了顶面以查看发生了什么。
/// <summary>
/// Draws the specified Cube Onsccreen.
/// </summary>
public void Draw()
{
GL.UseProgram(VSID);
Vector3 ObjectPosition = new Vector3((new Vector(1, 1) * (Position - Offset)))
{
Z = Layer * 0.1f
};
Matrix4 Scale = Matrix4.CreateScale(Width + highlight, Height + highlight, Height + highlight);
Matrix4 Translation = Matrix4.CreateTranslation(ObjectPosition);
Matrix4 ViewPoint = Matrix4.CreateOrthographic(Game.window.Width , Game.window.Height, -1, 1000);
ViewPoint = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI-Zoom,Game.window.Width/Game.window.Height,0.0001f,1000);
Matrix4 Rotation = Matrix4.CreateRotationZ((float)Angle);
Matrix4 CameraRotX = Matrix4.CreateRotationX((float)Math.PI / 180 * 40f);
Matrix4 CameraRotZ = Matrix4.CreateRotationZ(Game.CameraAngle);
Matrix4 Combined = Scale * Rotation * Translation * ViewPoint * CameraRotZ * CameraRotX;
GL.ProgramUniformMatrix4(VSID, GL.GetUniformLocation(VSID, "QuadMatrix"), false, ref Combined);
GL.ProgramUniform4(VSID, GL.GetUniformLocation(VSID, "ColorIn"), Color);
GL.ProgramUniform1(VSID, GL.GetUniformLocation(VSID, "SS"), 0);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.IndexArray);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, Texture);
GL.BindVertexArray(QID);
GL.DrawArrays(PrimitiveType.Triangles, 0, indices.Length);
}
public static void CreateVisuals()
{
int VS = Shaders.Load("Shaders.vs", ShaderType.VertexShader);
int FS = Shaders.Load("Shaders.fs", ShaderType.FragmentShader);
VSID = Visuals.Create(VS, FS);
}
public static void CreateCube()
{
QID = GL.GenVertexArray();
GL.BindVertexArray(QID);
int VID =GL.GenBuffer();
float[] Verticles =
{
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f
};
GL.BindBuffer(BufferTarget.ArrayBuffer, VID);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * Verticles.Length, Verticles,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
int UVID = GL.GenBuffer();
float[] UVs =
{
0, 1,
1, 1,
0, 0,
0, 0,
1, 1,
1, 0
};
GL.BindBuffer(BufferTarget.ArrayBuffer, UVID);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * UVs.Length, UVs, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(1);
indices = new uint[]
{
0, 1, 2,
2, 1, 3 /*,
0, 1, 5,
0, 1, 4,
1, 3, 5,
3, 5, 7,
2, 3, 7,
2, 6, 7,
0, 2, 6,
0, 4, 6,
4, 5, 6,
5, 6, 7 //*/
};
IBO = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBO);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(sizeof(uint) * indices.Length), indices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(IBO,1,VertexAttribPointerType.UnsignedInt,false,0,0);
GL.EnableVertexAttribArray(2);
}
不是绘制一个简单的四边形,而是以错误的顺序绘制了 2 个三角形。它实际上只是使用 space 中的坐标而不是这些坐标的索引
目前看起来像这样:
Index buffer name (value) is stated in the state vector of the Vertex Array Object.
要 "use" 它,你已经绑定了顶点数组对象并调用 glDrawElements
instead of glDrawArrays
:
GL.BindVertexArray(QID);
GL.DrawElements(PrimitiveType.Triangles, 0, DrawElementsType.UnsignedInt, NULL);
您必须 "duplicate" 顶点位置。参见 Rendering meshes with multiple indices。顶点坐标及其属性(如纹理坐标)形成一个元组。您可以将 3D 顶点坐标和 2D 纹理坐标想象成一个 5D 坐标。
至少你必须为立方体的两条边使用单独的顶点和属性。这意味着您至少需要 8+2*2=12 组不同的顶点属性。
x y z u v
0 : -0.5 0.5 0.5 0 0
1 : 0.5 0.5 0.5 1 0
2 : -0.5 -0.5 0.5 0 1
3 : 0.5 -0.5 0.5 1 1
4 : -0.5 -0.5 -0.5 0 0
5 : 0.5 -0.5 -0.5 1 0
6 : -0.5 0.5 -0.5 0 1
7 : 0.5 0.5 -0.5 1 1
8 : -0.5 0.5 0.5 1 1
9 : -0.5 0.5 -0.5 1 0
10 : 0.5 0.5 0.5 0 1
11 : 0.5 0.5 -0.5 0 0
注意,索引为0、2、4和6的顶点属性集具有相同的u坐标0。索引为1、3、5和7的顶点属性集具有相同的u-坐标 1.
如果您想将纹理包裹成四边形,则必须改变 u 和 v 坐标。因此,您必须添加单独的顶点属性集 8、9、10 和 11。
通过顶点坐标和纹理坐标的设置,您可以定义立方体的 12 个三角形面:
0 - 2 - 1 2 - 3 - 1
8 - 9 - 2 9 - 4 - 2
2 - 4 - 3 4 - 5 - 3
3 - 5 - 10 5 - 11 - 10
4 - 6 - 5 6 - 7 - 5
6 - 0 - 7 0 - 1 - 7
所以我的问题是我从 2d 到 3d,从简单的四边形到索引缓冲对象,当你从你使用的顶点绘制直线时
GL.DrawArrays();
但是当您使用索引缓冲区对象时,您应该使用
GL.DrawElements();
因为您要将索引保存到此处的元素缓冲区中:
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBO);
我正在尝试使用索引缓冲区,但不知道如何使用
我真的不知道我应该尝试什么。 none 的教程确实显示了与我的代码类似的任何内容,这主要是我遇到问题的原因。我可能不得不重写立方体顶点数组创建器。 (换句话说,也许我不应该把 opengl 推到一些现成的代码中)现在我只启用了顶面以查看发生了什么。
/// <summary>
/// Draws the specified Cube Onsccreen.
/// </summary>
public void Draw()
{
GL.UseProgram(VSID);
Vector3 ObjectPosition = new Vector3((new Vector(1, 1) * (Position - Offset)))
{
Z = Layer * 0.1f
};
Matrix4 Scale = Matrix4.CreateScale(Width + highlight, Height + highlight, Height + highlight);
Matrix4 Translation = Matrix4.CreateTranslation(ObjectPosition);
Matrix4 ViewPoint = Matrix4.CreateOrthographic(Game.window.Width , Game.window.Height, -1, 1000);
ViewPoint = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI-Zoom,Game.window.Width/Game.window.Height,0.0001f,1000);
Matrix4 Rotation = Matrix4.CreateRotationZ((float)Angle);
Matrix4 CameraRotX = Matrix4.CreateRotationX((float)Math.PI / 180 * 40f);
Matrix4 CameraRotZ = Matrix4.CreateRotationZ(Game.CameraAngle);
Matrix4 Combined = Scale * Rotation * Translation * ViewPoint * CameraRotZ * CameraRotX;
GL.ProgramUniformMatrix4(VSID, GL.GetUniformLocation(VSID, "QuadMatrix"), false, ref Combined);
GL.ProgramUniform4(VSID, GL.GetUniformLocation(VSID, "ColorIn"), Color);
GL.ProgramUniform1(VSID, GL.GetUniformLocation(VSID, "SS"), 0);
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.IndexArray);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, Texture);
GL.BindVertexArray(QID);
GL.DrawArrays(PrimitiveType.Triangles, 0, indices.Length);
}
public static void CreateVisuals()
{
int VS = Shaders.Load("Shaders.vs", ShaderType.VertexShader);
int FS = Shaders.Load("Shaders.fs", ShaderType.FragmentShader);
VSID = Visuals.Create(VS, FS);
}
public static void CreateCube()
{
QID = GL.GenVertexArray();
GL.BindVertexArray(QID);
int VID =GL.GenBuffer();
float[] Verticles =
{
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f
};
GL.BindBuffer(BufferTarget.ArrayBuffer, VID);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * Verticles.Length, Verticles,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
int UVID = GL.GenBuffer();
float[] UVs =
{
0, 1,
1, 1,
0, 0,
0, 0,
1, 1,
1, 0
};
GL.BindBuffer(BufferTarget.ArrayBuffer, UVID);
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * UVs.Length, UVs, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(1);
indices = new uint[]
{
0, 1, 2,
2, 1, 3 /*,
0, 1, 5,
0, 1, 4,
1, 3, 5,
3, 5, 7,
2, 3, 7,
2, 6, 7,
0, 2, 6,
0, 4, 6,
4, 5, 6,
5, 6, 7 //*/
};
IBO = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBO);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(sizeof(uint) * indices.Length), indices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(IBO,1,VertexAttribPointerType.UnsignedInt,false,0,0);
GL.EnableVertexAttribArray(2);
}
不是绘制一个简单的四边形,而是以错误的顺序绘制了 2 个三角形。它实际上只是使用 space 中的坐标而不是这些坐标的索引 目前看起来像这样:
Index buffer name (value) is stated in the state vector of the Vertex Array Object.
要 "use" 它,你已经绑定了顶点数组对象并调用 glDrawElements
instead of glDrawArrays
:
GL.BindVertexArray(QID);
GL.DrawElements(PrimitiveType.Triangles, 0, DrawElementsType.UnsignedInt, NULL);
您必须 "duplicate" 顶点位置。参见 Rendering meshes with multiple indices。顶点坐标及其属性(如纹理坐标)形成一个元组。您可以将 3D 顶点坐标和 2D 纹理坐标想象成一个 5D 坐标。
至少你必须为立方体的两条边使用单独的顶点和属性。这意味着您至少需要 8+2*2=12 组不同的顶点属性。
x y z u v
0 : -0.5 0.5 0.5 0 0
1 : 0.5 0.5 0.5 1 0
2 : -0.5 -0.5 0.5 0 1
3 : 0.5 -0.5 0.5 1 1
4 : -0.5 -0.5 -0.5 0 0
5 : 0.5 -0.5 -0.5 1 0
6 : -0.5 0.5 -0.5 0 1
7 : 0.5 0.5 -0.5 1 1
8 : -0.5 0.5 0.5 1 1
9 : -0.5 0.5 -0.5 1 0
10 : 0.5 0.5 0.5 0 1
11 : 0.5 0.5 -0.5 0 0
注意,索引为0、2、4和6的顶点属性集具有相同的u坐标0。索引为1、3、5和7的顶点属性集具有相同的u-坐标 1.
如果您想将纹理包裹成四边形,则必须改变 u 和 v 坐标。因此,您必须添加单独的顶点属性集 8、9、10 和 11。
通过顶点坐标和纹理坐标的设置,您可以定义立方体的 12 个三角形面:
0 - 2 - 1 2 - 3 - 1
8 - 9 - 2 9 - 4 - 2
2 - 4 - 3 4 - 5 - 3
3 - 5 - 10 5 - 11 - 10
4 - 6 - 5 6 - 7 - 5
6 - 0 - 7 0 - 1 - 7
所以我的问题是我从 2d 到 3d,从简单的四边形到索引缓冲对象,当你从你使用的顶点绘制直线时
GL.DrawArrays();
但是当您使用索引缓冲区对象时,您应该使用
GL.DrawElements();
因为您要将索引保存到此处的元素缓冲区中:
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBO);