OpenGL DrawArray仅绘制一个三角形/直线/点(OpenTK/C#)
在这个基本的渲染测试中,我从一个文件中加载了32个顶点的数据。当它绘制时,它将只绘制一个基本体,而忽略数组的其余部分。例如,如果我调用OpenGL DrawArray仅绘制一个三角形/直线/点(OpenTK/C#),c#,opengl,glsl,opentk,C#,Opengl,Glsl,Opentk,在这个基本的渲染测试中,我从一个文件中加载了32个顶点的数据。当它绘制时,它将只绘制一个基本体,而忽略数组的其余部分。例如,如果我调用GL.drawArray(PrimitiveType.Triangles,I,3)它将绘制元素I 数组包含的数据远不止一个三角形,因为这里的示例代码每次单击时都会绘制一个不同的三角形,但每次渲染时也只有一个三角形。如果我使用不同的int-first参数多次调用DrawArrays,它还会为每次调用绘制一个额外的三角形。(我敢肯定,将所有数据放入GPU缓冲区的目的不
GL.drawArray(PrimitiveType.Triangles,I,3)
它将绘制元素I
数组包含的数据远不止一个三角形,因为这里的示例代码每次单击时都会绘制一个不同的三角形,但每次渲染时也只有一个三角形。如果我使用不同的int-first参数多次调用DrawArrays
,它还会为每次调用绘制一个额外的三角形。(我敢肯定,将所有数据放入GPU缓冲区的目的不是为了让您可以进行无数次draw调用。)
我曾尝试使用DrawArray的drawelements作为替代品,但无论我为参数设置了什么,我都会得到System.AccessViolationException。我能找到的所有教程都只是绘制一个三角形和/或使用抽屉元素,因此我无法找到代码示例来帮助我了解绘制多个原语的不同之处
Form1只是一个空白表单,上面有一个glcontrol。我正在使用NuGet包OpenTK 3.1.0和OpenTK.GLControl 3.1.0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK.Graphics.OpenGL4;
using OpenTK;
namespace _3dRenderingTesting
{
public partial class Form1 : Form
{
int program;
int myVAO;
int i = 0;
private void glControl1_MouseClick(object sender, MouseEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.UseProgram(program);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
GL.DrawArrays(PrimitiveType.Triangles, i, 3);
glControl1.SwapBuffers();
i++;
}
private void Form1_Load(object sender, EventArgs e)
{
program = compileShaders();
getMeshFromFile();
}
public Form1()
{
InitializeComponent();
}
private int compileShaders()
{
string vShader;
using (System.IO.StreamReader file = new System.IO.StreamReader(@"vertexshader.txt"))
{
vShader = file.ReadToEnd();
}
string fShader = "";
using (System.IO.StreamReader file = new System.IO.StreamReader(@"fragmentshader.txt"))
{
fShader = file.ReadToEnd();
}
int vertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertexShader, vShader);
GL.CompileShader(vertexShader);
int fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragmentShader, fShader);
GL.CompileShader(fragmentShader);
int program = GL.CreateProgram();
GL.AttachShader(program, vertexShader);
GL.AttachShader(program, fragmentShader);
GL.LinkProgram(program);
GL.DeleteShader(vertexShader);
GL.DeleteShader(fragmentShader);
return program;
}
private int vertBuffer;
private int vertLength;
private void getMeshFromFile()
{
List<string> fileContents = new List<string>();
List<float> fVerts = new List<float>();
List<int> fFaces = new List<int>();
System.IO.StreamReader file = new System.IO.StreamReader(@"C:\Users\abc\Desktop\32 Vertex Sphere.obj");
while (!file.EndOfStream)
{
string ts = file.ReadLine().Trim().ToLower();
//find all lines that begin with "v"
//these are vertices
if (ts.Length > 0)
{
if (ts.Substring(0, 1) == "v")
{
const string reduceMultiSpace = @"[ ]{2,}";
string[] tSplit = System.Text.RegularExpressions.Regex.Replace(ts.Replace(" ", ",").Replace("\t", ","), reduceMultiSpace, ",").Split(',');
if (tSplit.Length < 4)
{
MessageBox.Show("Vertex list failure (< 3 vertices)");
Application.Exit();
}
fVerts.Add(float.Parse(tSplit[1]));
fVerts.Add(float.Parse(tSplit[2]));
fVerts.Add(float.Parse(tSplit[3]));
}
if (ts.Substring(0, 1) == "f")
{
const string reduceMultiSpace = @"[ ]{2,}";
string[] tSplit = System.Text.RegularExpressions.Regex.Replace(ts.Replace(" ", ",").Replace("\t", ","), reduceMultiSpace, ",").Split(',');
if (tSplit.Length < 4)
{
MessageBox.Show("Face list failure (< 3 vertices)");
Application.Exit();
}
fFaces.Add(int.Parse(tSplit[1]));
fFaces.Add(int.Parse(tSplit[2]));
fFaces.Add(int.Parse(tSplit[3]));
}
}
}
file.Close();
float[] fVArray = new float[fVerts.Count];
for (int i = 0; i < fVerts.Count; i++) fVArray[i] = fVerts[i];
GL.CreateBuffers(1, out vertBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, vertBuffer);
GL.NamedBufferStorage(vertBuffer, sizeof(float) * fVerts.Count, fVArray, BufferStorageFlags.MapWriteBit | BufferStorageFlags.MapReadBit);
vertLength = fVerts.Count;
GL.CreateVertexArrays(1, out myVAO);
GL.BindVertexArray(myVAO);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
}
}
}
简单的v&f着色器:
#版本450核心
vec4位置的布局(位置=0);
真空总管(真空)
{
gl_位置=位置;
}
#版本450核心
out vec4 FragColor;
真空总管(真空)
{
FragColor=vec4(1.0,1.0,1.0,1.0);
}
中说明了元素数组缓冲区
,因此必须先绑定顶点数组对象,然后才能绑定元素数组缓冲区。看
图纸:
GL.DrawElements(BeginMode.Triangles, indexCount, DrawElementsType.UnsignedInt, 0);
中说明了
元素数组缓冲区
,因此必须先绑定顶点数组对象,然后才能绑定元素数组缓冲区。看
图纸:
GL.DrawElements(BeginMode.Triangles, indexCount, DrawElementsType.UnsignedInt, 0);
@拉比它第一次渲染的时候就是这样的,因为第一次我是0。它只渲染一个三角形(使用顶点0,1,2),然后停止。下一次通过它渲染一个三角形(使用顶点1、2、3)等。我还使用它渲染了一个使用所有32个顶点的lineloop/linestrip,这很有效(它渲染了一大堆线),所以这是另一种方式,我确定所有(或至少超过3个)顶点都可用。使用DrawArray时没有访问冲突。如果我将它设置为31,它将只绘制一条线,>31它不会绘制任何内容,但不会崩溃或报告任何错误。我只有在尝试使用抽屉元素时才会遇到accessviolation。问题是,“如何让它渲染整个数组,而不仅仅是一个三角形?”如果我将它设置为从0开始,并且有32个顶点,那么它(据我所知)应该渲染三角形,直到顶点用完为止。32不能被3整除。但是
GL.drawArray(PrimitiveType.Triangles,0,30)代码>将呈现10个三角形primitives@Rabbid76这正是它第一次渲染时所做的,因为第一次渲染时i为0。它只渲染一个三角形(使用顶点0,1,2),然后停止。下一次通过它渲染一个三角形(使用顶点1、2、3)等。我还使用它渲染了一个使用所有32个顶点的lineloop/linestrip,这很有效(它渲染了一大堆线),所以这是另一种方式,我确定所有(或至少超过3个)顶点都可用。使用DrawArray时没有访问冲突。如果我将它设置为31,它将只绘制一条线,>31它不会绘制任何内容,但不会崩溃或报告任何错误。我只有在尝试使用抽屉元素时才会遇到accessviolation。问题是,“如何让它渲染整个数组,而不仅仅是一个三角形?”如果我将它设置为从0开始,并且有32个顶点,那么它(据我所知)应该渲染三角形,直到顶点用完为止。32不能被3整除。但是GL.drawArray(PrimitiveType.Triangles,0,30)
将渲染10个三角形基本体,这至少消除了崩溃。我想我还需要设置atttributes并启用此缓冲区等,以使其绘制面,但使用顶点数组作为模板应该更容易。谢谢,这至少消除了崩溃。我想我还必须设置AttAttributes并启用此缓冲区等,才能让它绘制面,但使用顶点数组作为模板应该更容易。
GL.DrawElements(BeginMode.Triangles, indexCount, DrawElementsType.UnsignedInt, 0);