OpenTK 的官方文档是真心的少,他们把怎么去安装 OpenTK 说的很清楚,但是也就仅限于此,这有一篇 learn opentk in 15 的教程(链接已经失效,译者注),但是并不完美。你可以在 15 分钟内做一些简单的事情,但是却很难理解代码的内部机制。本文使用了一部分该教程的代码,使用的是过时的方式(非 VBO),但是有助于理解 OPENTK/OPENGL 的绘图机制。
首先,安装 OpenTK。 这是一个非常简单的过程,可以参考官方教程,我这里推荐使用
。
- Nuget
打开自己喜欢的 IDE(集成开发环境)。 我使用 Visual Studio,但是 MonoDevelop 和 SharpDevelop 应该都可以正常工作。
新建一个控制台(console)程序,右键点击工程,管理 nuget 引用,输入 opentk,安装就 ok 了。
现在我们有一个空的项目。 我们首先要做的是打开 Program.cs 文件。现在这是一个基础类,什么都不做。我们将继续为我们的主要功能。要开始显示图形,我们需要制作 GameWindow 类型的子类。 添加一个名为 "Game" 的新类。 使它成为 GameWindow 的子类(您需要为 OpenTK 添加一个 using 指令才能使用该类)。
差不多是这样:
- using OpenTK;
- using OpenTK.Graphics.OpenGL;
- using System;
- namespace OpentkTutorials
- {
- class Game : GameWindow
- {
- }
- }
回到 Program.cs,添加代码:
- namespace OpentkTutorials
- {
- class Program
- {
- static void Main(string[] args)
- {
- using (var game = new Game())
- {
- game.Run(30.0);
- }
- }
- }
- }
运行就可以看到效果了:
这是一个空窗口,但是说明我们成功了。
GameWindow 的 Run 方法有多个重载。使用 30.0 的 float 类型参数,Run 函数会以 30 次 / 秒的频率引发窗口的 UpdateFrame 事件,同样的,计算机将处理相同频率的 RenderFrame 事件。
现在,我们来让窗口做一些更有趣的事情。 在 Game 类中,您可以使用几种方法来重载以添加新功能。 我们要重载的第一个是 onLoad。如果您使用 Visual Studio,只需输入 "override" 并添加一个空格即可给出一个可用于覆盖的 GameWindow 类中的方法列表。此方法的基本形式为:
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- }
我们再写点别的:
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- //修改窗口标题
- Title = "Hello OpenTK!";
- //设置背景颜色为,额,不知道什么蓝(需要添加 OpenTK.Graphics.OpenGL and System.Drawing引用)
- GL.ClearColor(Color.CornflowerBlue);
- }
我们必须再做一件事情,然后才会看到这种颜色变化。 使用以下代码为 OnRenderFrame 方法添加另一个重载:
- protected override void OnRenderFrame(FrameEventArgs e)
- {
- base.OnRenderFrame(e);
- GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
- SwapBuffers();
- }
先上车,以后再解释这部分。我们应该能看到修改效果:
现在的背景是蓝色,标题也改过来了。
接下来,当正确调整窗口大小时,我们将添加代码来处理。我们需要告诉 OpenGL 如何调整新窗口大小,所以我们需要一些处理它的代码。
- protected override void OnResize(EventArgs e) {
- base.OnResize(e);
- GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
- Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float) Math.PI / 4, Width / (float) Height, 1.0f, 64.0f);
- GL.MatrixMode(MatrixMode.Projection);
- GL.LoadMatrix(ref projection);
- }
这段代码只是告诉 OpenGL 窗口的位置,以及我们想要绘制的窗口。现在这些不重要,但是当我们实际绘制一些东西,或者做一个真实的游戏时,处理大小调整将非常重要。
我们回到
方法,并实际绘制一些东西。 我们需要做的第一件事就是告诉 OpenGL 我们正在从哪个方向看。因为我们实际上有可能会在 3D 中制作一些东西,所以我们面对的方向(视角)很重要。
- OnRenderFrame
在调用
之前,下一节的所有代码将进入
- SwapBuffers()
。 这是因为我们需要画一些东西才能交换缓冲区。默认情况,我们使用 "双缓冲" 设置。 当我们要把东西画到屏幕上时,我们首先绘制一个 "缓冲区",后来被 "交换" 到屏幕内容。 这样可以确保在屏幕更新之前,所有内容都会在屏幕上绘制出来。
- OnRenderFrame
以下代码将在准备一个平面,我们可以在上面画三角形。
- Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
- GL.MatrixMode(MatrixMode.Modelview);
- GL.LoadMatrix(ref modelview);
现在我们要画三角形本身。 第一步是告诉 OpenGL 我们想画些东西。 我们用 GL.Begin 函数做到这一点。 它需要一个参数,即使用的绘图模式。 可以选择绘制四边形,三角形,点,多边形和 "条"。 我们只是使用一个三角形,所以我们需要的代码是:
- GL.Begin(BeginMode.Triangles);
BeginMode 有以下几种模式,(现在调用这个方法会显示已经过时,需要使用 PrimitiveType 代替)可以参考 OPENGL 文档,或者园子里有人写过:
http://www.cnblogs.com/helloj2ee/archive/2013/03/12/2956181.html
现在我们已经告诉 OPENTK 如何绘制,我们需要给它形状的顶点。 为此,我们使用 GL.Vertex3 函数。3D 空间中单个点的坐标需要三个浮点数。
- GL.Vertex3( - 1.0f, -1.0f, 4.0f);
- GL.Vertex3(1.0f, -1.0f, 4.0f);
- GL.Vertex3(0.0f, 1.0f, 4.0f);
在将所有点送到显卡之前,我们需要告诉 OPENGL 我们打完收工了。
- GL.End();
跑完,应该是这个效果:
我们再深入一步,添加一点色彩。使用 GL.Color3 函数,可以设置定点颜色,需要在设置位置之前调用。
- GL.Color3(1.0f, 0.0f, 0.0f);
- GL.Vertex3( - 1.0f, -1.0f, 4.0f);
- GL.Color3(0.0f, 1.0f, 0.0f);
- GL.Vertex3(1.0f, -1.0f, 4.0f);
- GL.Color3(0.0f, 0.0f, 1.0f);
- GL.Vertex3(0.0f, 1.0f, 4.0f);
最后效果差不多是这样:
为什么它是一个渐变的三角形? 这是因我们使用的是默认着色器(shader)。着色器允许许多非常惊人的效果,例如凹凸贴图,照明,phong 光照等。默认值在绘制顶点时简单地插入给它们的颜色和位置的值。着色器是一个更复杂的功能(甚至使用自己的脚本语言),以后我们会讲到。
原文代码可以在 github 上找到。
来源: http://www.cnblogs.com/podolski/p/7406628.html