前言:做视频渲染,在windows平台有很多种方式(如d3d9,WriteableBitmap等)。然而著名的openGl是大家的首选。在.net中,微软提供好了已经封装过的openGl库,即sharpGl。接下来以wpf为例进行纹理部分的讲解。
经过本文的阅读,您不仅可以了解如何在wpf中使用sharpGl纹理,还可以触类旁通,学习OpenGl的在其他平台的使用方式,比如openGL ES等等。
一、纹理基本介绍
1、纹理介绍:纹理一般是指将图片贴到预先渲染的多边形上的某个指定区域上,以达到精美的效果。也可以不贴图片,直接贴RGB颜色空间也可以。
2、纹理的坐标:纹理和顶点坐标(这个会在基础章节讲解)不一样,他的坐标是st坐标,对应顶点坐标的x轴和y轴,且他的标准取值范围是(0,1)没有负数。(标准范围是0-1,当取非标准时范围时,如取3,可以用参数做伸缩和重复渲染处理)
3、纹理使用效果图:
(使用纹理的3种效果图示)
二、wpf代码实现
1、新建一个wpf项目;
2、通过NuGet管理器下载shrpGL.WPF版本的dll到本地(也可从别的地方拷贝到项目):
3、在 MainWindow.xaml 界面中使用OpenGLControl控件:
<Grid>
<wpf:OpenGLControl x:Name="openGLControl1"
OpenGLDraw="OpenGLControl1_OpenGLDraw"
OpenGLInitialized="OpenGLControl1_OpenGLInitialized"
RenderContextType="FBO"
FrameRate="20">
</wpf:OpenGLControl>
</Grid>
4、后台代码(MainWindow.xaml.cs)
using SharpGL;
using System;
using System.Runtime.InteropServices;
using System.Windows;
namespace sharpGlGetPara
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
OpenGL gl;
double rateDouTexture = 0; //旋转角度
SharpGL.SceneGraph.Assets.Texture _texture; //申明一个纹理
public MainWindow()
{
InitializeComponent();
}
//初始化openGl
private void OpenGLControl1_OpenGLInitialized(object sender, SharpGL.WPF.OpenGLRoutedEventArgs args)
{
gl = openGLControl1.OpenGL;
gl.ClearColor(0, 0, 0F, 1.0f);
gl.Color(1.0, 0.0, 0.0, 0.0); //设置背景色
gl.Enable(OpenGL.GL_TEXTURE_2D);
_texture = new SharpGL.SceneGraph.Assets.Texture();
_texture.Create(gl, "jingdong.png");//作为方便演示,我直接放到Debug输出文件夹了
_texture.Bind(gl);
}
//渲染视频,这个方法根据FrameRate="20"的帧率决定执行频率
private void OpenGLControl1_OpenGLDraw(object sender, SharpGL.WPF.OpenGLRoutedEventArgs args)
{
Dispatcher.Invoke(new Action(() =>
{
float[] verts = //正方形的顶点数组
{
-0.5f, 0.5f,-0f,
0.5f, 0.5f, -0f,
0.5f, -0.5f,-0f,
-0.5f, -0.5f,-0f,
};
float[] colors = //颜色数组(rgba参数-渐变)
{
1f, 1f, 1f, 1f,//白色
1f, 1f, 1f, 1f,//白色
0.94f, 0.69f, 0.45f,1f,//橙色
0.94f, 0.69f, 0.45f,1f//橙色
};
float[] textures = //纹理坐标数组,注意:图片的纹理t轴是反的,这里通过1-处理
{
0f, 1-1f,
1f, 1-1f,
1f, 1-0f,
0f, 1-0f
};
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.LoadIdentity();
gl.Translate(0f, 0f, -6f);//将坐标系后移动,让用户可见视图
gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY); //允许设置顶点
gl.EnableClientState(OpenGL.GL_COLOR_ARRAY); //允许设置顶点颜色数组
gl.EnableClientState(OpenGL.GL_TEXTURE_COORD_ARRAY); //允许设置顶点纹理坐标数组
IntPtr pArray = Marshal.AllocHGlobal(verts.Length * sizeof(float)); //申请数组的指针
IntPtr pColorArray = Marshal.AllocHGlobal(colors.Length * sizeof(float));
IntPtr pTextureArray = Marshal.AllocHGlobal(textures.Length * sizeof(float));
try
{
Marshal.Copy(verts, 0, pArray, verts.Length);
gl.VertexPointer(3, OpenGL.GL_FLOAT, 0, pArray);//设置正方形的顶点数据
Marshal.Copy(colors, 0, pColorArray, colors.Length);
gl.ColorPointer(4, OpenGL.GL_FLOAT, 0, pColorArray);//设置正方形的顶点颜色数据
Marshal.Copy(textures, 0, pTextureArray, textures.Length);
//绑定纹理
gl.ActiveTexture(_texture.TextureName);
gl.BindTexture(OpenGL.GL_TEXTURE_2D, _texture.TextureName);
//当纹理坐标范围超出(0,1)时,下面4行用来配置拉伸效果
//gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
//gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);
//gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, OpenGL.GL_CLAMP_TO_EDGE);
//gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, OpenGL.GL_CLAMP_TO_EDGE);
//设置顶点纹理坐标。但设置了顶点纹理坐标,那么顶点颜色自动失效
gl.TexCoordPointer(2, OpenGL.GL_FLOAT, 0, pTextureArray);
gl.Rotate(rateDouTexture, 0, 1f, 0); //变换,模拟播放效果(这里是绕着y轴旋转)
}
finally
{
Marshal.FreeHGlobal(pArray); //释放数组内存
Marshal.FreeHGlobal(pColorArray);
Marshal.FreeHGlobal(pTextureArray);
}
gl.DrawArrays(OpenGL.GL_QUADS, 0, 4); //绘制正方形
gl.DisableClientState(OpenGL.GL_VERTEX_ARRAY); //关闭顶点数组
gl.DisableClientState(OpenGL.GL_COLOR_ARRAY); //关闭顶点颜色数组
gl.DisableClientState(OpenGL.GL_TEXTURE_COORD_ARRAY); //关闭顶点纹理坐标数组
rateDouTexture += 0.5d;
}));
}
}
}
5、效果图(这里用了gl.Rotate旋转和OpenGLDraw渲染方法,达到实时视频渲染效果)
好了,本次关于sharpGL的纹理篇就讲到这里了,更多内容,请期待下次的讲述
欢迎有问题的伙伴及时留意讨论,有不足之处还望指正
祝大家生活工作愉快~