如何在单独的 opengl 数组对象中正确渲染网格?
How to correctly render meshes in separate opengl array objects?
我正在尝试使用单独的顶点数组对象渲染两个三角形。我在 C# 上使用 OpenTK(与定义的 OpenGL API 相比,它提供几乎相同的 API)。这是我的代码:
我从声明我的变量开始。
public partial class Form1 : Form
{
public Form1() {
InitializeComponent();
}
bool loaded = false; //do not use glcontrol before it is not loaded
private uint VAO1;
private uint object1_vertex_buffer; private uint object1_vertices_size; private uint object1_index_buffer;
private uint object2_vertex_buffer; private uint object2_vertices_size; private uint object2_index_buffer;
private uint VAO2;
private uint VBO;
int VertexShader;
int FragmentShader;
int ShaderProgram;
private float[] object1_vertices = new float[] {
-0.2f, 0.0f, 0.0f,
0.2f, 0.0f, 0.0f,
0.0f, 0.2f, 0.0f
};
private float[] object2_vertices = new float[] {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.4f, 0.0f
};
private int[] object1_indices = new int[] { 0, 1, 2 };
private int[] object2_indices = new int[] { 0, 1, 2 };
我在这里画每一帧:
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded)//<--------------------------------------
return;//<--------------------------------------
// Clear the color buffer.
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(ShaderProgram);
// Object 1
GL.BindVertexArray(VAO1);
// drawelements requires count of elements, not bytes
GL.DrawElements(PrimitiveType.Triangles, object1_indices.Length, DrawElementsType.UnsignedInt, 0);
// Object 2
GL.BindVertexArray(VAO2);
GL.DrawElements(PrimitiveType.Triangles, object2_indices.Length, DrawElementsType.UnsignedInt, 0);
ErrorCode miauw = GL.GetError(); /// AND I GET HERE NO ERROR!
/// at the end I have a screen filled by a background color, which is set in GL.ClearColor()
glControl1.SwapBuffers();
}
这里我对 OpenGL 数组和缓冲区进行了初始化。我在这里初始化了两个顶点数组对象(每个三角形一个)和两个缓冲区(每个):顶点和索引。我为它们设置了合适的字节长度
private void glControl1_Load(object sender, EventArgs e) {
loaded = true;
GL.ClearColor(Color.SkyBlue);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);
// Load the source of the vertex shader and compile it.
VertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(VertexShader, MyOpenglThings.VertexShaderSource);
GL.CompileShader(VertexShader);
// Load the source of the fragment shader and compile it.
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(FragmentShader, MyOpenglThings.FragmentShaderSource);
GL.CompileShader(FragmentShader);
// Create the shader program, attach the vertex and fragment shaders and link the program.
ShaderProgram = GL.CreateProgram();
GL.AttachShader(ShaderProgram, VertexShader);
GL.AttachShader(ShaderProgram, FragmentShader);
GL.LinkProgram(ShaderProgram);
//
//
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
// Object 1 vertex indices
GL.GenBuffers(1, out object1_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
// Object 2 vertex indices
GL.GenBuffers(1, out object2_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);
}
我释放了分配的opengl资源(这与我的问题无关,现在甚至都没有调用嘿嘿)
private void CleanupOpenGL() {
// ...
}
}
我已经复制了着色器代码:
class MyOpenglThings
{
// A simple vertex shader possible. Just passes through the position vector.
public const string VertexShaderSource = @"
#version 330
layout(location = 0) in vec4 position;
void main(void)
{
gl_Position = position;
}
";
// A simple fragment shader. Just a constant red color.
public const string FragmentShaderSource = @"
#version 330
out vec4 outputColor;
void main(void)
{
outputColor = vec4(1.0, 0.0, 0.0, 1.0);
}
";
}
但是当我启动一个程序时,我只得到一个 window 充满天蓝色的。至少,opengl 能够渲染背景颜色。但我也想得到两个红色三角形。
里面有什么问题吗?如何在顶点数组对象中渲染两个网格?
当您定义一个通用顶点属性数据数组时(GL.VertexAttribPointer
), the Vertex array object 必须绑定存储定义的数组。
VAO2
的规范是这样,但 VAO1
的规范不是这样,因为在
之后
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
顶点数组对象VAO2
已绑定。
此外,通用顶点属性数组必须由 GL.EnableVertexAttribArray
启用。启用或禁用顶点数组的状态也存储在顶点数组对象中:
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]
上面的回答真的很有帮助。 (我在这里发帖,因为评论不适合代码。)
所以,我的加载代码现在看起来像:
private void glControl1_Load(object sender, EventArgs e) {
loaded = true;
GL.ClearColor(Color.SkyBlue);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);
// Load the source of the vertex shader and compile it.
// ....
// Load the source of the fragment shader and compile it.
// ....
// Create the shader program, attach the vertex and fragment shaders and link the program.
// ....
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// Object 1 vertex indices
GL.GenBuffers(1, out object1_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// Object 2 vertex indices
GL.GenBuffers(1, out object2_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);
}
GL.EnableVertexAttribArray 的参数应与着色器程序中的值匹配。
还更改了一点几何坐标,因为三角形曾经重叠。
我正在尝试使用单独的顶点数组对象渲染两个三角形。我在 C# 上使用 OpenTK(与定义的 OpenGL API 相比,它提供几乎相同的 API)。这是我的代码:
我从声明我的变量开始。
public partial class Form1 : Form
{
public Form1() {
InitializeComponent();
}
bool loaded = false; //do not use glcontrol before it is not loaded
private uint VAO1;
private uint object1_vertex_buffer; private uint object1_vertices_size; private uint object1_index_buffer;
private uint object2_vertex_buffer; private uint object2_vertices_size; private uint object2_index_buffer;
private uint VAO2;
private uint VBO;
int VertexShader;
int FragmentShader;
int ShaderProgram;
private float[] object1_vertices = new float[] {
-0.2f, 0.0f, 0.0f,
0.2f, 0.0f, 0.0f,
0.0f, 0.2f, 0.0f
};
private float[] object2_vertices = new float[] {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.4f, 0.0f
};
private int[] object1_indices = new int[] { 0, 1, 2 };
private int[] object2_indices = new int[] { 0, 1, 2 };
我在这里画每一帧:
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded)//<--------------------------------------
return;//<--------------------------------------
// Clear the color buffer.
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(ShaderProgram);
// Object 1
GL.BindVertexArray(VAO1);
// drawelements requires count of elements, not bytes
GL.DrawElements(PrimitiveType.Triangles, object1_indices.Length, DrawElementsType.UnsignedInt, 0);
// Object 2
GL.BindVertexArray(VAO2);
GL.DrawElements(PrimitiveType.Triangles, object2_indices.Length, DrawElementsType.UnsignedInt, 0);
ErrorCode miauw = GL.GetError(); /// AND I GET HERE NO ERROR!
/// at the end I have a screen filled by a background color, which is set in GL.ClearColor()
glControl1.SwapBuffers();
}
这里我对 OpenGL 数组和缓冲区进行了初始化。我在这里初始化了两个顶点数组对象(每个三角形一个)和两个缓冲区(每个):顶点和索引。我为它们设置了合适的字节长度
private void glControl1_Load(object sender, EventArgs e) {
loaded = true;
GL.ClearColor(Color.SkyBlue);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);
// Load the source of the vertex shader and compile it.
VertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(VertexShader, MyOpenglThings.VertexShaderSource);
GL.CompileShader(VertexShader);
// Load the source of the fragment shader and compile it.
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(FragmentShader, MyOpenglThings.FragmentShaderSource);
GL.CompileShader(FragmentShader);
// Create the shader program, attach the vertex and fragment shaders and link the program.
ShaderProgram = GL.CreateProgram();
GL.AttachShader(ShaderProgram, VertexShader);
GL.AttachShader(ShaderProgram, FragmentShader);
GL.LinkProgram(ShaderProgram);
//
//
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
// Object 1 vertex indices
GL.GenBuffers(1, out object1_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
// Object 2 vertex indices
GL.GenBuffers(1, out object2_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);
}
我释放了分配的opengl资源(这与我的问题无关,现在甚至都没有调用嘿嘿)
private void CleanupOpenGL() {
// ...
}
}
我已经复制了着色器代码:
class MyOpenglThings
{
// A simple vertex shader possible. Just passes through the position vector.
public const string VertexShaderSource = @"
#version 330
layout(location = 0) in vec4 position;
void main(void)
{
gl_Position = position;
}
";
// A simple fragment shader. Just a constant red color.
public const string FragmentShaderSource = @"
#version 330
out vec4 outputColor;
void main(void)
{
outputColor = vec4(1.0, 0.0, 0.0, 1.0);
}
";
}
但是当我启动一个程序时,我只得到一个 window 充满天蓝色的。至少,opengl 能够渲染背景颜色。但我也想得到两个红色三角形。
里面有什么问题吗?如何在顶点数组对象中渲染两个网格?
当您定义一个通用顶点属性数据数组时(GL.VertexAttribPointer
), the Vertex array object 必须绑定存储定义的数组。
VAO2
的规范是这样,但 VAO1
的规范不是这样,因为在
GL.GenVertexArrays(1, out VAO1); GL.BindVertexArray(VAO1); GL.GenVertexArrays(1, out VAO2); GL.BindVertexArray(VAO2);
顶点数组对象VAO2
已绑定。
此外,通用顶点属性数组必须由 GL.EnableVertexAttribArray
启用。启用或禁用顶点数组的状态也存储在顶点数组对象中:
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// [...]
上面的回答真的很有帮助。 (我在这里发帖,因为评论不适合代码。) 所以,我的加载代码现在看起来像:
private void glControl1_Load(object sender, EventArgs e) {
loaded = true;
GL.ClearColor(Color.SkyBlue);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);
// Load the source of the vertex shader and compile it.
// ....
// Load the source of the fragment shader and compile it.
// ....
// Create the shader program, attach the vertex and fragment shaders and link the program.
// ....
GL.GenVertexArrays(1, out VAO1);
GL.BindVertexArray(VAO1);
// Object 1 vertex positions
GL.GenBuffers(1, out object1_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object1_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object1_vertices.Length * sizeof(float), object1_vertices,BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// Object 1 vertex indices
GL.GenBuffers(1, out object1_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object1_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object1_indices.Length * sizeof(int), object1_indices, BufferUsageHint.StaticDraw);
GL.GenVertexArrays(1, out VAO2);
GL.BindVertexArray(VAO2);
// Object 2 vertex positions
GL.GenBuffers(1, out object2_vertex_buffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, object2_vertex_buffer);
GL.BufferData(BufferTarget.ArrayBuffer, object2_vertices.Length * sizeof(float), object2_vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(0);
// Object 2 vertex indices
GL.GenBuffers(1, out object2_index_buffer);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, object2_index_buffer);
GL.BufferData(BufferTarget.ElementArrayBuffer, object2_indices.Length*sizeof(int), object2_indices, BufferUsageHint.StaticDraw);
}
GL.EnableVertexAttribArray 的参数应与着色器程序中的值匹配。
还更改了一点几何坐标,因为三角形曾经重叠。