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工程链接
这个会自动安装到当前的VS中,安装包链接
<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:OpenGLControl
Name="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 DepthBuffer
gl.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 face
gl.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 face
gl.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 face
gl.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 face
gl.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 face
gl.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 face
gl.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可以随便改