openTK开发环境搭建
上周我们讨论了一个问题:关于Unity支持平台的问题。我当时提出了一个观点,就是只要能运行MonoGame,就能运行Unity引擎。而MonoGame图形底层就是openTK(openTK又基于SDL2)。openGL的C# binding其实不少,甚至FNA还提供了一个单文件版。不过个人还是觉得openTK开发体验比较好。
顺便来句题外话,MonoGame和FNA两个项目最初的目的也都是提供一个XNA的开源跨平台实现。两者也都不约而同的使用了SDL2作为底层。欧美独立游戏开发者使用XNA的比例其实很高,比如最近大火的《星露谷物语》,就是作者耗时4年完成。从NX消息披露,到NS发布会上公布独立游戏名单,也不过数月,星露谷就在NS可以运行,也足见XNA移植MonoGame可能真的非常简单。
1. 新建工程
打开rider,在C#的IDE方面,个人更偏向于rider而非蓝星最强IDE VS,不光因为我是JB粉,更因为Mac版的VS没那么好用(其实还是MonoDevelop)。
新建一个ConsoleApplication
然后写个Hello world测试一下C#环境是不是OK。
2. 为项目添加openTK依赖
要说C#项目添加外部依赖,最方便的方法自然是使用NuGet。无论Rider,Visual Studio还是Mono Develop都已经集成了NuGet的支持。
用图中方法,为项目添加openTK,openTK.GLControl两个依赖。接下来就开始正戏了。
3. 创建窗口
新建一个名为MainWindow的类,内容改为如下:
using OpenTK;
using OpenTK.Graphics.OpenGL4;
namespace OGLApplication1
{
public sealed class MainWindow : GameWindow
{
}
}
修改Program.cs为如下内容:
using System;
using System.Collections.Generic;
namespace OGLApplication1
{
internal class Program
{
[STAThread]
public static void Main(string[] args)
{
new MainWindow().Run(60);
}
}
}
点击运行,看见一个空窗口。那么恭喜成功。
4. 初始化OpenGL上下文
修改MainWindow的构造函数如下:
public MainWindow() : base(800, // initial width
600, // initial height
GraphicsMode.Default,
"dreamstatecoding", // initial title
GameWindowFlags.Default,
DisplayDevice.Default,
4, // OpenGL major version
0, // OpenGL minor version
GraphicsContextFlags.ForwardCompatible)
{
Title += ": OpenGL Version: " + GL.GetString(StringName.Version);
}
点击运行,如果看到窗口标题为dreamstatecoding加上你的OpenGL版本(还有显卡驱动版本),那么恭喜,这步也成功。
5. 一个完整示例
一个清屏&显示FPS&ESC退出的示例代码
using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
namespace OGLApplication1
{
public sealed class MainWindow : GameWindow
{
public MainWindow() : base(800, // initial width
600, // initial height
GraphicsMode.Default,
"dreamstatecoding", // initial title
GameWindowFlags.Default,
DisplayDevice.Default,
4, // OpenGL major version
0, // OpenGL minor version
GraphicsContextFlags.ForwardCompatible)
{
Title += ": OpenGL Version: " + GL.GetString(StringName.Version);
}
protected override void OnResize(EventArgs e)
{
GL.Viewport(0, 0, Width, Height);
}
protected override void OnLoad(EventArgs e)
{
CursorVisible = true;
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
HandleKeyboard();
}
private void HandleKeyboard()
{
var keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Key.Escape))
{
Exit();
}
}
protected override void OnRenderFrame(FrameEventArgs e)
{
Title = $"(Vsync: {VSync}) FPS: {1f / e.Time:0}";
GL.ClearColor(0.3f, 0.1f, 0.1f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
SwapBuffers();
}
}
}
点击运行,屏幕被清理为棕红色,窗口的标题显示帧数,以及垂直同步是否开启。运行效果如下: