原文地址:https://billc.io/2019/10/fpainter/
计算机图形学的第一个大作业是用 OpenGL 或 DirectX3d 实现一个平面的画图,应当具备直线和圆形的功能。正好国庆放假时间比较充裕,就稍微完善了一下界面,实现了一个画图。
关于 SharpGL
为了使 OpenGL 能正确地与 C# 互动,可以采用动态链接的方式直接手动将 OpenGl 的 dll 链接进自己工程中,但这种方法比较繁琐,况且网上已经有许多人做了重复的工作,于是我选择了一个似乎并不是特别受欢迎的包装库 SharpGL 来在 C# 中使用 OpenGL 的函数。
如果采用 OpenGLControl 控件获取 OpenGL 对象,那么使用 SharpGL 的代码风格会是这样:
//C# SharpeGL.OpenGL gl = glCanvas.OpenGL; gl.Color(0, 0, 0); gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); gl.LoadIdentity(); gl.Translate(-4.68f, 4.11f, -10f);
相比对应的 OpenGL 在 C/C++ 中的代码,可以流畅地转换。同时这个库还省去了 Glut 函数后面的 3f 等恼人的参数,全部重载了一起。
//C glColor3f(0, 0, 0); glClear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(-4.68f, 4.11f, -10f);
你可以在这里 https://github.com/dwmkerr/sharpgl 了解到关于 SharpGL 的更多信息。
运行效果
主要的功能如图。基本的画图功能都可以实现,刷新率大概在每秒30帧的样子。需要运行在 .Net Framework 4.6以上,因为需要一个高 dpi 感知的 manifest。
目前还有两个需要探索的问题,一个是在拖动绘制直线的时候能够实时显示当前的绘制效果而不是抬起鼠标之后才绘制。也许要设计一些 buffer 相关的知识但目前自己的能力似乎还做不到。
同时使用如下代码开启抗锯齿后,圆形的绘制会有较大问题。在每一次绘制的时候多边形都会填充一次,造成绘制出来的圆形会成为这个样子:
//抗锯齿 gl.Enable(OpenGL.GL_BLEND); gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA); gl.Enable(OpenGL.GL_POINT_SMOOTH); gl.Enable(OpenGL.GL_LINE_SMOOTH); gl.Enable(OpenGL.GL_POLYGON_SMOOTH);
//圆形的绘制代码 case Tools.circle: //使用参数函数 x = Acos; y = Bsin画椭圆 double lenA = Math.Abs(fx - pointQueue.Peek().fx) / 2.0; double lenB = Math.Abs(fy - pointQueue.Peek().fy) / 2.0; fPoint center = new fPoint((fx + pointQueue.Peek().fx) / 2.0, (fy + pointQueue.Peek().fy) / 2.0); int n = 90; //精度,以n边的多边形代替椭圆 gl.Begin(OpenGL.GL_POLYGON); { for (double alpha = 0; alpha < Math.PI * 2; alpha += Math.PI / n) { gl.Vertex(center.fx + Math.Cos(alpha) * lenA, center.fy + Math.Sin(alpha) * lenB, 0f); } } gl.End(); pointQueue.Clear(); break;
Code
你可以在这里找到源代码: https://github.com/BillChen2000/LearningRepo/tree/master/Course/ComputerGraphics/FPainter
之前本来的要求是用 MFC 实现图形界面,但看了看上世纪的框架文档实在是没有心思继续钻研下去。不知道什么时候大学的老师们能够在 ppt 里稍微去掉一些 199x 年的古董。