SharpGL是对OpenGl的C#的封装,支持Net4.0及以上,由于SharpGL仅仅是对C++写的OpenGL做了接口的封装,所以SharpGL的运行效率不用多说,是非常高效的,不会说因为C#是即时性语言而导致性能下降很多,在测试中使用我的笔记本i57300HQ的CPU占用率仅仅0.1%,说明这东西确实运行很高效,虽然没有Unity那样的GPU渲染优化(Unity3D的美化与渲染真的很好),但是这样低的CPU占用率依然很诱人(使用Unity3D时CPU占用率在1.3%~1.6%左右,GPU占用率高,占用线程多),对于轻量级(即便是很简单的一个三维场景,Unity3D一般拖家带口几十Mb甚至上百Mb,而SharpGL则为几Mb)的三维显示,SharpGL无疑是一个很好的选择。因此我在做三维姿态上位机过程中,又学习了一下SharpGL,当然很感谢官方的源码例程,基本所有的操作都是跟着官方例程来的。在这里分享一下:
本文ShaprGL WPF工程链接
安装SharpGL-1.vsix
这个会自动安装到当前的VS中,安装包链接
创建一个SharpGL的WPF窗体:
xaml文件:
<Window x:Class=\"SharpGLWPFApplication1.MainWindow\"xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"Title=\"SharpGL WPF Application\" Height=\"554\" Width=\"800\"xmlns:sharpGL=\"clr-namespace:SharpGL.WPF;assembly=SharpGL.WPF\"><Grid><!-- The OpenGL control provides a OpenGL drawing surface. --><sharpGL:OpenGLControlName=\"openGLControl\" OpenGLDraw=\"openGLControl_OpenGLDraw\"OpenGLInitialized=\"openGLControl_OpenGLInitialized\" Resized=\"openGLControl_Resized\"DrawFPS=\"false\" RenderContextType=\"FBO\" FrameRate=\"20\" Margin=\"0,0,0.4,-0.2\"/><Button Content=\"暂停/继续\" FontSize=\"28\" HorizontalAlignment=\"Left\" Width=\"135\" Margin=\"0,435,0,0\" Click=\"Button_Click\"/></Grid></Window>
设计完大概这样:
设置背景色:
当然你觉得黑色不好看的话可换个纯色背景,只需要改改这句话就可以了(其中的透明度好像不能用,设置了好像也没什么变化,前三个RGB值是可以使用的,像我这样设置的话是藏蓝色的):
gl.ClearColor(0.1f, 0.2f,0.3f, 0.01f);//RGB值和透明度
贴图代码:
当然,贴图有两种方式,当然,我推荐简单的一种(虽然我在工程中没有这样做,┗( ▔, ▔ )┛)
简单的版本:
using SharpGL.SceneGraph.Assets;OpenGL gl = openGLControl.OpenGL;Texture[] mytexture = new Texture[6];//创建6个面的贴图mytexture[0].Create(gl, \"Pictures/Right.png\");//依次生成贴图.........
一定需要注意的是,贴图前一定要保证已经使能了贴图功能,不然是贴不上去的,必须要有这一句话:
gl.Enable(OpenGL.GL_TEXTURE_2D);
然后就是贴图了,需要注意的是,贴图是
以 gl.Begin(OpenGL.GL_QUADS);开始
以 gl.End();结束
所以贴不同的面都要添上这两句
贴图中用到的三个函数的参数说明为:
/* gl.Normal3i(1, 0, 0); 四边形面的法向量*/
/gl.TexCoord(0, 0); 第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧。第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部/
/gl.Vertex(halfXdimension, -halfYdimension, -halfZdimension); 绘制的四边形的顶点的坐标/
OpenGL gl = openGLControl.OpenGL;;gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); // Clear screen and DepthBuffergl.LoadIdentity();gl.PolygonMode(OpenGL.GL_FRONT, OpenGL.GL_FILL);//设置照相机的位置gl.Translate(0, 0, -1.0f * CameraDistance);switch (CameraView){case (CameraViews.Right):gl.Rotate(-90, 0, 1, 0);gl.Rotate(-90, 1, 0, 0);break;case (CameraViews.Left):gl.Rotate(90, 0, 1, 0);gl.Rotate(-90, 1, 0, 0);break;case (CameraViews.Back):gl.Rotate(90, 1, 0, 0);gl.Rotate(180, 0, 1, 0);break;case (CameraViews.Front):gl.Rotate(-90, 1, 0, 0);break;case (CameraViews.Top):break;case (CameraViews.Bottom):gl.Rotate(180, 1, 0, 0);break;}gl.PushMatrix();//使用旋转矩阵旋转//gl.glMultMatrixf(transformationMatrix); //根据旋转矩阵旋转方块//根据欧拉角旋转/*绕 X 轴旋转 Y->Z 为正*/ /*绕 Y 轴旋转 Z->X 为正*/ /*绕 Z 轴旋转 X->Y 为正*/gl.Rotate((float)angle, 1, 0, 0); gl.Rotate((float)angle, 0, 1, 0); gl.Rotate((float)angle, 0, 0, 1);// +\'ve x facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[0]);//绑定贴图gl.Begin(OpenGL.GL_QUADS);//开始四边形/* gl.Normal3i(1, 0, 0); 法向量*//*gl.TexCoord(0, 0); 第一个参数是X坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧。第二个参数是Y坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部*//*gl.Vertex(halfXdimension, -halfYdimension, -halfZdimension); 坐标取决于摄像机位置 */gl.Normal3i(1, 0, 0); gl.TexCoord(0, 0); gl.Vertex(halfXdimension, -halfYdimension, -halfZdimension);gl.Normal3i(1, 0, 0); gl.TexCoord(0, 1); gl.Vertex(halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(1, 0, 0); gl.TexCoord(1, 1); gl.Vertex(halfXdimension, halfYdimension, halfZdimension);gl.Normal3i(1, 0, 0); gl.TexCoord(1, 0); gl.Vertex(halfXdimension, halfYdimension, -halfZdimension);gl.End();// -\'ve x facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[1]);gl.Begin(OpenGL.GL_QUADS);gl.Normal3i(-1, 0, 0); gl.TexCoord(1, 0); gl.Vertex(-halfXdimension, -halfYdimension, -halfZdimension);gl.Normal3i(-1, 0, 0); gl.TexCoord(1, 1); gl.Vertex(-halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(-1, 0, 0); gl.TexCoord(0, 1); gl.Vertex(-halfXdimension, halfYdimension, halfZdimension);gl.Normal3i(-1, 0, 0); gl.TexCoord(0, 0); gl.Vertex(-halfXdimension, halfYdimension, -halfZdimension);gl.End();// +\'ve y facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[2]);gl.Begin(OpenGL.GL_QUADS);gl.Normal3i(0, 1, 0); gl.TexCoord(1, 0); gl.Vertex(-halfXdimension, halfYdimension, -halfZdimension);gl.Normal3i(0, 1, 0); gl.TexCoord(1, 1); gl.Vertex(-halfXdimension, halfYdimension, halfZdimension);gl.Normal3i(0, 1, 0); gl.TexCoord(0, 1); gl.Vertex(halfXdimension, halfYdimension, halfZdimension);gl.Normal3i(0, 1, 0); gl.TexCoord(0, 0); gl.Vertex(halfXdimension, halfYdimension, -halfZdimension);gl.End();// -\'ve y facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[3]);gl.Begin(OpenGL.GL_QUADS);gl.Normal3i(0, -1, 0); gl.TexCoord(0, 0); gl.Vertex(-halfXdimension, -halfYdimension, -halfZdimension);gl.Normal3i(0, -1, 0); gl.TexCoord(0, 1); gl.Vertex(-halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(0, -1, 0); gl.TexCoord(1, 1); gl.Vertex(halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(0, -1, 0); gl.TexCoord(1, 0); gl.Vertex(halfXdimension, -halfYdimension, -halfZdimension);gl.End();// +\'ve z facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[4]);gl.Begin(OpenGL.GL_QUADS);gl.Normal3i(0, 0, 1); gl.TexCoord(0, 0); gl.Vertex(-halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(0, 0, 1); gl.TexCoord(1, 0); gl.Vertex(halfXdimension, -halfYdimension, halfZdimension);gl.Normal3i(0, 0, 1); gl.TexCoord(1, 1); gl.Vertex(halfXdimension, halfYdimension, halfZdimension);gl.Normal3i(0, 0, 1); gl.TexCoord(0, 1); gl.Vertex(-halfXdimension, halfYdimension, halfZdimension);gl.End();// -\'ve z facegl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[5]);gl.Begin(OpenGL.GL_QUADS);gl.Normal3i(0, 0, -1); gl.TexCoord(0, 1); gl.Vertex(-halfXdimension, -halfYdimension, -halfZdimension);gl.Normal3i(0, 0, -1); gl.TexCoord(1, 1); gl.Vertex(halfXdimension, -halfYdimension, -halfZdimension);gl.Normal3i(0, 0, -1); gl.TexCoord(1, 0); gl.Vertex(halfXdimension, halfYdimension, -halfZdimension);gl.Normal3i(0, 0, -1); gl.TexCoord(0, 0); gl.Vertex(-halfXdimension, halfYdimension, -halfZdimension);gl.End();gl.PopMatrix();gl.Flush();
最终的实现效果:
设置刷新率:
SharpGL是一个非常的人性化的设置,可以直接调节刷新率,也就省去了开启一个定时器,使用定时器来进行软刷新了,基本省去了定时器的麻烦,反正就是相当于他帮你开启了一个定时器,如果想调节定时器刷新频率的话,很简单,只需要在xaml里修改一下参数就可以了。将FrameRate=\”20\”中的20改成你想要的刷新频率,单位是Hz,不过这个速率我试了下超过100Hz好像就没什么变化了,有可能是人家觉得不需要那么高的刷新率,反正实际FPS的需要也不需要太高吧。
或者这样做也行,添加一句:
openGLControl.FrameRate = 20;//这个20就是FPS可以随便改