我在C#中使用OpenGL.net(可通过NuGet获得),并且试图将现代OpenGL的最小工作示例放在一起。

清除屏幕并进行着色器编译工作,但是在第158行的Gl.DrawArrays调用中得到了AccessViolationException。

到目前为止,我所做的是:


放心的顶点数据已上传
检查Gl.DrawArrays中的count参数是否正确
检查的着色器正确无误并已编译
Checked Size Argument在任何地方都是正确的
在使用OpenGL和C#的上下文中,遍历了错误消息上的Google链接的前几页


码:

using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using OpenGL;
using System.Runtime.ExceptionServices;

namespace RenderEngine
{
    public class RenderForm : Form
    {
        private Timer tmr_Render;
        private System.ComponentModel.IContainer components;
        private GlControl glc_screen;
        MemoryLock vertexArrayLock;
        uint vertexArrayID;
        uint vertexbuffer;
        uint shaderProgram;
        private static readonly float[] _ArrayPosition = new float[] {
            0.0f, 0.0f,
            0.5f, 1.0f,
            1.0f, 0.0f
        };

        private static readonly float[] _ArrayColor = new float[] {
            1.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 1.0f
        };


        public RenderForm()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.glc_screen = new OpenGL.GlControl();
            this.tmr_Render = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            //
            // glc_screen
            //
            this.glc_screen.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
            this.glc_screen.ColorBits = ((uint)(24u));
            this.glc_screen.DepthBits = ((uint)(0u));
            this.glc_screen.Dock = System.Windows.Forms.DockStyle.Fill;
            this.glc_screen.Location = new System.Drawing.Point(0, 0);
            this.glc_screen.MultisampleBits = ((uint)(0u));
            this.glc_screen.Name = "glc_screen";
            this.glc_screen.Size = new System.Drawing.Size(784, 561);
            this.glc_screen.StencilBits = ((uint)(0u));
            this.glc_screen.TabIndex = 0;
            this.glc_screen.ContextCreated += new System.EventHandler<OpenGL.GlControlEventArgs>(this.glc_screen_ContextCreated);
            this.glc_screen.Render += new System.EventHandler<OpenGL.GlControlEventArgs>(this.glc_screen_Render);
            //
            // tmr_Render
            //
            this.tmr_Render.Enabled = true;
            this.tmr_Render.Interval = 16;
            this.tmr_Render.Tick += new System.EventHandler(this.tmr_Render_Tick);
            //
            // RenderForm
            //
            this.ClientSize = new System.Drawing.Size(784, 561);
            this.Controls.Add(this.glc_screen);
            this.Name = "RenderForm";
            this.ResumeLayout(false);

        }

        private void glc_screen_ContextCreated(object sender, GlControlEventArgs e)
        {
            GlControl glControl = (GlControl)sender;

            shaderProgram = LoadShaders("../../../RenderEngine/vertex.shader", "../../../RenderEngine/fragment.shader");

            vertexArrayID = Gl.GenVertexArray();
            Gl.BindVertexArray(vertexArrayID);
            Gl.EnableVertexAttribArray(vertexArrayID);

            vertexArrayLock = new MemoryLock(_ArrayPosition);
            vertexbuffer = Gl.GenBuffer();
            Gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexbuffer);
            Gl.BufferData(BufferTargetARB.ArrayBuffer, /*sizeof(float)*(uint)_ArrayPosition.Length*/ 100, vertexArrayLock.Address, BufferUsageARB.DynamicDraw);
            int indexInShader = 0;// Gl.GetAttribLocation(shaderProgram, "vertexPosition_modelspace");
            int floatsPerVertex = 2;
            bool normalized = false;
            int stride = floatsPerVertex*sizeof(float);
            int arrayBufferOffset = 0;
            Gl.VertexAttribPointer((uint)indexInShader, floatsPerVertex, Gl.FLOAT, normalized, stride, arrayBufferOffset);
            Gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);
        }

        private uint LoadShaders(string vertexPath, string fragmentPath) {
            uint vertexShaderId = Gl.CreateShader(Gl.VERTEX_SHADER);
            uint fragmentShaderId = Gl.CreateShader(Gl.FRAGMENT_SHADER);

            string vertexCode = File.ReadAllText(vertexPath);
            string fragmentCode = File.ReadAllText(fragmentPath);

            int vertexResult;
            int vertexInfoLogLength;
            StringBuilder vertexInfoLog = new StringBuilder(200);
            Gl.ShaderSource(vertexShaderId, new string[] { vertexCode }/*vertexCode.Split(new char[] { '\r', '\n' })*/);
            Gl.CompileShader(vertexShaderId);
            Gl.GetShader(vertexShaderId, Gl.COMPILE_STATUS, out vertexResult);
            Gl.GetShaderInfoLog(vertexShaderId, 200, out vertexInfoLogLength, vertexInfoLog);
            Console.WriteLine(vertexInfoLog.Length == 0 ? "Vertex shader compiled sucessfully" : vertexInfoLog.ToString());

            int fragmentResult;
            int fragmentInfoLogLength;
            StringBuilder fragmentInfoLog = new StringBuilder(200);
            Gl.ShaderSource(fragmentShaderId, new string[] { fragmentCode }/*fragmentCode.Split(new char[] { '\r', '\n' })*/);
            Gl.CompileShader(fragmentShaderId);
            Gl.GetShader(fragmentShaderId, Gl.COMPILE_STATUS, out fragmentResult);
            Gl.GetShaderInfoLog(fragmentShaderId, 200, out fragmentInfoLogLength, fragmentInfoLog);
            Console.WriteLine(fragmentInfoLog.Length==0 ? "Fragment shader compiled sucessfully" : fragmentInfoLog.ToString());

            uint programId = Gl.CreateProgram();
            Gl.AttachShader(programId, vertexShaderId);
            Gl.AttachShader(programId, fragmentShaderId);
            Gl.LinkProgram(programId);
            int programResult;
            int programInfoLogLength;
            StringBuilder programInfoLog = new StringBuilder(200);
            Gl.GetProgram(programId, Gl.LINK_STATUS, out programResult);
            Gl.GetProgramInfoLog(programId, 200, out programInfoLogLength, programInfoLog);
            Console.WriteLine(programInfoLog.Length == 0 ? "Program linked sucessfully" : programInfoLog.ToString());

            Gl.DetachShader(programId, vertexShaderId);
            Gl.DetachShader(programId, fragmentShaderId);

            Gl.DeleteShader(vertexShaderId);
            Gl.DeleteShader(fragmentShaderId);

            return programId;
        }

        private void glc_screen_Render(object sender, GlControlEventArgs e)
        {
            GlControl senderControl = (GlControl)sender;

            Gl.BindVertexArray(vertexArrayID);
            Gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexbuffer);


            Gl.CheckErrors();
            Console.WriteLine(Gl.GetError());
            int floatsPerVertex = 2;
            int start = 0;
            int verticies = _ArrayPosition.Length / floatsPerVertex;
            Gl.Clear(ClearBufferMask.ColorBufferBit);
            Gl.ClearColor(1f, .5f, 1f, 0f);
            Gl.UseProgram(shaderProgram);
            Gl.DrawArrays(PrimitiveType.Triangles, start, verticies);

            Gl.DisableVertexAttribArray(vertexArrayID);
        }

        private void tmr_Render_Tick(object sender, EventArgs e)
        {
            glc_screen.Invalidate();
        }
    }
}


顶点着色器:

#version 330 core
layout(location = 0) in vec2 vertexPosition_modelspace;
void main() {
    gl_Position.xy = vertexPosition_modelspace;
    gl_Position.z = 1.0;
    gl_Position.w = 1.0;
}


片段着色器:

#version 330 core
out vec4 color;
void main() {
    color = vec4(1, 0, 0, 0);
}


我不知道这是什么问题,我们将不胜感激。

最佳答案

我怀疑

Gl.BufferData(BufferTargetARB.ArrayBuffer, /*sizeof(float)*(uint)_ArrayPosition.Length*/ 100, vertexArrayLock.Address, BufferUsageARB.DynamicDraw);


是问题的根源。您要告诉OpenGL定义一个100字节的缓冲区,并初始化vertexArrayLock.Address中的内容。可悲的是,vertexArrayLock.Address指向一个大6 * sizeof(float)= 24字节的内存。

但是,我不明白为什么您在DrawArrays上遇到异常;可能还有其他我没看到的问题。

-几分钟后-

得到它了。删除行:

Gl.BindBuffer(BufferTargetARB.ArrayBuffer, 0);


来自glc_screen_ContextCreated。它将以不使用缓冲区的方式更改VAO状态。 VAO状态向量的焦点,您将获得成功的DrawArrays。

关于c# - Gl.DrawArrays中的AccessViolationException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43005460/

10-11 23:11