我正在关注此tutorial以了解如何在C#中使用OpenGL。一切都运行良好,直到这部分:OpenGL 4 with OpenTK in C# Part 5: Buffers and Triangle。我没有使用与本教程中使用的完全相同的OpenTK。我在这里使用的是与.NET Core兼容的版本:https://www.nuget.org/packages/OpenTK.NETCore/
当我运行程序时,我的控制台显示以下堆栈跟踪:
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at OpenTK.Graphics.OpenGL.GL.NamedBufferStorage[T2](Int32 buffer, Int32 size, T2[] data, BufferStorageFlags flags)
at Minecraft.RenderObject..ctor(Vertex[] vertices) in d:\users\user\documents\visual studio 2017\Projects\Minecraft\Minecraft\RenderObject.cs:line 22
at Minecraft.Game.OnLoad(EventArgs e) in d:\users\user\documents\visual studio 2017\Projects\Minecraft\Minecraft\Program.cs:line 42
at OpenTK.GameWindow.Run(Double updates_per_second, Double frames_per_second)
at Minecraft.Program.Main(String[] args) in d:\users\user\documents\visual studio 2017\Projects\Minecraft\Minecraft\Program.cs:line 183
我的代码与教程中的代码非常匹配:
using System;
using OpenTK.Graphics.OpenGL;
namespace Minecraft
{
public class RenderObject : IDisposable
{
private bool initialized;
private readonly int vertexArray;
private readonly int buffer;
private readonly int verticeCount;
public RenderObject(Vertex[] vertices)
{
this.verticeCount = vertices.Length;
this.vertexArray = GL.GenVertexArray();
this.buffer = GL.GenBuffer();
GL.BindVertexArray(this.vertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.buffer);
GL.NamedBufferStorage(
this.buffer,
Vertex.Size * vertices.Length, // the size needed by this buffer
vertices, // data to initialize with
BufferStorageFlags.MapWriteBit); // at this point we will only write to the buffer
GL.VertexArrayAttribBinding(this.vertexArray, 0, 0);
GL.EnableVertexArrayAttrib(this.vertexArray, 0);
GL.VertexArrayAttribFormat(
this.vertexArray,
0, // attribute index, from the shader location = 0
4, // size of attribute, vec4
VertexAttribType.Float, // contains floats
false, // does not need to be normalized as it is already, floats ignore this flag anyway
0); // relative offset, first item
GL.VertexArrayAttribBinding(this.vertexArray, 1, 0);
GL.EnableVertexArrayAttrib(this.vertexArray, 1);
GL.VertexArrayAttribFormat(
this.vertexArray,
1, // attribute index, from the shader location = 1
4, // size of attribute, vec4
VertexAttribType.Float, // contains floats
false, // does not need to be normalized as it is already, floats ignore this flag anyway
16); // relative offset after a vec4
GL.VertexArrayVertexBuffer(this.vertexArray, 0, this.buffer, IntPtr.Zero, Vertex.Size);
this.initialized = true;
}
public void Render()
{
GL.BindVertexArray(this.vertexArray);
GL.DrawArrays(PrimitiveType.Triangles, 0, this.verticeCount);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this.initialized)
{
GL.DeleteVertexArray(this.vertexArray);
GL.DeleteBuffer(this.buffer);
this.initialized = false;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
namespace Minecraft
{
class Game : GameWindow
{
public Game() :
base(
800,
600,
GraphicsMode.Default,
string.Empty,
GameWindowFlags.Default,
DisplayDevice.Default,
4,
5,
GraphicsContextFlags.ForwardCompatible)
{
this.VSync = VSyncMode.On;
}
private int program;
private List<RenderObject> renderObjects = new List<RenderObject>();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Vertex[] vertices =
{
new Vertex(new Vector4(-0.25f, 0.25f, 0.5f, 1 - 0f), Color4.HotPink),
new Vertex(new Vector4(0.0f, -0.25f, 0.5f, 1 - 0f), Color4.HotPink),
new Vertex(new Vector4(0.25f, 0.25f, 0.5f, 1 - 0f), Color4.HotPink),
};
this.renderObjects.Add(new RenderObject(vertices));
this.CursorVisible = true;
this.program = this.CreateProgram();
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
GL.PatchParameter(PatchParameterInt.PatchVertices, 3);
}
{...}
/// <summary>
/// Compiles all shaders
/// </summary>
/// <returns> An OpenGL program </returns>
private int CompileShader(ShaderType shaderType, string path)
{
// 1. Create the shader object
var shader = GL.CreateShader(shaderType);
// 2. Read the shader source from file
var src = File.ReadAllText(path);
// 3. Assign the shader source to the shader object
GL.ShaderSource(shader, src);
// 4. Compile it so OpenGL can use it :)
GL.CompileShader(shader);
// Check if anything was written to the info log during the
// compilation of this specific shader and write it to Debug log
var info = GL.GetShaderInfoLog(shader);
if (!string.IsNullOrWhiteSpace(info))
{
Debug.WriteLine($"{nameof(GL)}.{nameof(GL.CompileShader)} [{shaderType}] had info log: {info}");
}
return shader;
}
private int CreateProgram()
{
var program = GL.CreateProgram();
var shaders = new List<int>();
shaders.Add(
this.CompileShader(
ShaderType.VertexShader,
@"Components\Shaders\1Vert\vertexShader.vert"));
shaders.Add(
this.CompileShader(
ShaderType.FragmentShader,
@"Components\Shaders\5Frag\fragmentShader.frag"));
foreach (var shader in shaders)
{
GL.AttachShader(program, shader);
}
GL.LinkProgram(program);
var info = GL.GetProgramInfoLog(program);
if (!string.IsNullOrWhiteSpace(info))
{
Debug.WriteLine($"{nameof(GL)}.{nameof(GL.LinkProgram)} had info log: {info}");
}
foreach (var shader in shaders)
{
GL.AttachShader(program, shader);
GL.DeleteShader(shader);
}
return program;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
this.Title = $"FPS: {1.0f / e.Time:0}";
GL.ClearColor(new Color4 { A = 1.0f, R = 0.1f, G = 0.1f, B = 0.3f });
// Clear all the buffers to start drawing afresh
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(this.program);
foreach (var renderObject in this.renderObjects)
{
renderObject.Render();
}
// Present the rendered scene to the user
this.SwapBuffers();
}
}
class Program
{
[STAThread]
static void Main(string[] args)
{
// the 'using' idiom guarantees proper resource cleanup.
// We request 60 UpdateFrame events per second, and unlimited
// RenderFrame events (as fast as the computer can handle).
using (Game game = new Game())
{
game.Run(60);
}
}
}
}
我是OpenGL的新手,所以我不明白这是什么。请帮我。谢谢:))
似乎我的问题与使用哪个版本的OpenGL有关。因为我正在使用NVIDIA Optimus的笔记本电脑上进行开发,所以它选择使用仅具有OpenGL 4.3的Intel HD Graphics 4600,而使用的OpenGL功能是OpenGL 4.5的一部分。
我所做的是迫使Optimus使用支持OpenGL 4.5的NVIDIA GPU启动所有应用程序。现在我的程序启动没有任何问题。
我现在的问题是: