C#中使用OpenGL(API)创建OpenGL渲染环境
在C#中调用1.1版本的OpenGL函数,但是光有OpenGL函数还不能绘制图形,就像一个画家,他即使拥有绘画的技巧,还有画笔和颜料,如果没有画布,他也没有地方画画。有了画布,画家还需要画板把画布支起来才能画。OpenGL渲染环境就类似于画布和画板,只有创建了渲染环境,使用OpenGL函数才会起作用。它不是OpenGL的一部分,而是隶属于操作系统,所以不同的操作系统,创建OpenGL渲染环境的方法也不同。由于是在C#中使用OpenGL,所以本文将使用winAPI创建OpenGL渲染环境。
C# OpenGL接口源码、C# OpenGL编程例子可在百度网盘下载:链接:https://pan.baidu.com/s/1dnIo1s-l6aqlE3IgaMJA5g
提取码:wc0x
一、选择显示窗口
显示窗口就类似于画家的画板,它的作用就是支撑画布,使得我们能够看到画布上的图画。在使用C/C++语言开发OpenGL程序,都需要自己创建显示窗口,当然,glut、glfw等库提供了在Windows系统中创建窗口的函数,这使得创建窗口变得很方便。然而,用C#语言开发OpenGL程序的时候,完全没有必要自己创建显示窗口,因为C#本身提供了大量可视控件,这些可视控件都有一个窗口,我们只需选择一个控件作为显示窗口即可。
上图展现的是在文本框、图片框和按钮上绘制三角形。只要控件是可视的(像Timer这类控件是非可视控件),它都可以作为显示窗口。只要你愿意,你可以把图形绘制在窗体(Form)、图片框(pictureBox)、标签(Label)…甚至是文本框(TextBox)。本文选择PictureBox控件作为显示窗口。
二、用到的winAPI函数
创建OpenGL渲染环境需要用到五个windows API。
1.取得设备上下文(DC,Device Context)
HDC GetDC(HWND hWnd);
1
参数是窗口句柄,返回值是设备上下文句柄。
2.选择像素格式
int ChoosePixelFormat(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd);
1
第一个参数是设备上下文句柄,第二个参数是像素格式描述器(Pixel Format Descriptor),返回值是一个整型,如果成功则返回像素格式索引号,否则返回0;
其中,PIXELFORMATDESCRIPTOR类型是一个结构体,其C语言描述如下:
typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;//该结构体占用存储空间的大小
WORD nVersion;//版本号
DWORD dwFlags;//格式属性
BYTE iPixelType;//颜色模式
BYTE cColorBits;//颜色比特位数
BYTE cRedBits;//红色分量比特位数
BYTE cRedShift;//红色分量偏移量
BYTE cGreenBits;//绿色分量比特位数
BYTE cGreenShift;//绿色分量偏移量
BYTE cBlueBits;//蓝色分量比特位数
BYTE cBlueShift;//蓝色分量偏移量
BYTE cAlphaBits;//alpha分量比特位数
BYTE cAlphaShift;//alpha分量偏移量
BYTE cAccumBits;//累积缓冲区一个像素占用比特位数
BYTE cAccumRedBits;//累积缓冲区红色分量的比特位数
BYTE cAccumGreenBits;//累积缓冲区绿色分量的比特位数
BYTE cAccumBlueBits;//累积缓冲区蓝色分量的比特位数
BYTE cAccumAlphaBits;//累积缓冲区alpha分量的比特位数
BYTE cDepthBits;//深度缓冲区中一个像素占用的比特位数
BYTE cStencilBits;//模板缓冲区中一个像素占用的比特位数
BYTE cAuxBuffers;//辅助缓冲区
BYTE iLayerType;//用于早期的OpenGL,现已忽略
BYTE bReserved;//指定表层与底层的平面数目
DWORD dwLayerMask;//用于早期的OpenGL,现已忽略
DWORD dwVisibleMask;//指定一个底层平面的透明颜色或索引
DWORD dwDamageMask;//用于早期的OpenGL,现已忽略
} PIXELFORMATDESCRIPTOR
3.设置像素格式
BOOL SetPixelFormat(HDC hdc,int format, CONST PIXELFORMATDESCRIPTOR * ppfd);
1
第一个参数是设备上下文句柄,通过GetDC获得;第二个参数是像素格式索引号,通过ChoosePixelFormat获得;第三个是像素格式描述器,需要用户自行设置;如果设置成功则返回true,否则返回false。
4.创建OpenGL渲染上下文
HGLRC wglCreateContext( HDC hdc );
1
参数是设备上下文句柄(HDC),返回值是OpenGL渲染上下文句柄(HGLRC)。HGLRC与HDC具有一样的像素格式。
5.指定OpenGL当前渲染上下文
BOOL wglMakeCurrent( HDC hdc, HGLRC hglrc);
1
第一个参数是设备上下文句柄,第二个参数是OpenGL渲染上下文句柄,如果成功则返回true,否则返回false。
三、C#语言声明windows API
windows API都是用C语言写的,在C#中调用winAPI需要先对这些外部函数进行声明。
1.数据类型的变换
凡是句柄类型,在C#中都用IntPtr类型表示。如HWND类型、HDC类型、HGLRC类型都统一用IntPtr类型表示。对于PIXELFORMATDESCRIPTOR 类型,其C#版的结构体声明如下:
[StructLayout(LayoutKind.Sequential,Pack =1)]
public struct PIXELFORMATDESCRIPTOR
{
public ushort nSize;
public ushort nVersion;
public uint dwFlags;
public byte iPixelType;
public byte cColorBits;
public byte cRedBits;
public byte cRedShift;
public byte cGreenBits;
public byte cGreenShift;
public byte cBlueBits;
public byte cBlueShift;
public byte cAlphaBits;
public byte cAlphaShift;
public byte cAccumBits;
public byte cAccumRedBits;
public byte cAccumGreenBits;
public byte cAccumBlueBits;
public byte cAccumAlphaBits;
public byte cDepthBits;
public byte cStencilBits;
public byte cAuxBuffers;
public byte iLayerType;
public byte bReserved;
public uint dwLayerMask;
public uint dwVisibleMask;
public uint dwDamageMask;
};
2.C#方法声明
[DllImport("user32.dll", ExactSpelling = false, EntryPoint = "GetDC", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll", ExactSpelling = false, EntryPoint = "ChoosePixelFormat", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern int ChoosePixelFormat(IntPtr hdc, IntPtr ppfd);
[DllImport("gdi32.dll", ExactSpelling = false, EntryPoint = "SetPixelFormat", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetPixelFormat(IntPtr hdc, int format, IntPtr ppfd);
[DllImport("opengl32.dll", ExactSpelling = false, EntryPoint = "wglCreateContext", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr wglCreateContext(IntPtr hdc);
[DllImport("opengl32.dll", ExactSpelling = false, EntryPoint = "wglMakeCurrent", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern bool wglMakeCurrent(IntPtr hdc, IntPtr hglrc);
四、创建OpenGL渲染环境
下面通过C#代码来说明如何创建OpenGL渲染环境。
要调用windows API需要先引用名称空间:
using System.Runtime.InteropServices;
1
由于还会用到不安全代码,所以还要在“项目->属性”中勾选允许不安全代码。
示例代码:
IntPtr hWnd=pictureBox1.Handle;//图片框的窗口句柄
IntPtr hdc =GetDC(hWnd);//取得设备上下文
PIXELFORMATDESCRIPTOR pfd;//定义一个像素格式描述器
//设置像素格式
pfd.nSize = 40;
pfd.nVersion = 1;
pfd.dwFlags = PFD.PFD_DRAW_TO_WINDOW | PFD.PFD_SUPPORT_OPENGL | PFD.PFD_DOUBLEBUFFER;
pfd.iPixelType = (byte)PFD.PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 0;
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16;
pfd.cStencilBits = 0;
pfd.cAuxBuffers = 0;
pfd.iLayerType = (byte)PFD.PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
int pixelFormat;
unsafe
{
PIXELFORMATDESCRIPTOR* ppfd=&pfd;
pixelFormat =ChoosePixelFormat(hdc,(IntPtr)ppfd);//选择像素格式
SetPixelFormat(hdc, pixelFormat, (IntPtr)ppfd);//设置像素格式
IntPtr hglrc;
hglrc =wglCreateContext(hdc);//建立OpenGL渲染上下文
wglMakeCurrent(hdc, hglrc);//激活当前渲染上下文
}
通过以上一小段代码,OpenGL渲染环境的搭建就完成了。为验证正确性,做了一个实验,该实验是在pictureBox上绘制图形,结果如下图:
结语
之前的一些文章已经探讨过OpenGL常量、1.1版本的OpenGL,还有参数传递问题。本文着重介绍了如何在C#中创建OpenGL渲染环境,到目前为止,已经可以利用1.1版本的OpenGL进行图形绘制。下一步是探讨如何在C#中调用高版本的OpenGL。欲知道更详细的操作,可以浏览我的源码。
————————————————
版权声明:本文为CSDN博主「shifenglv」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28249373/article/details/78835336
之前的文章介绍了如何在C#中调用1.1版本的OpenGL函数,但是光有OpenGL函数还不能绘制图形,就像一个画家,他即使拥有绘画的技巧,还有画笔和颜料,如果没有画布,他也没有地方画画。有了画布,画家还需要画板把画布支起来才能画。OpenGL渲染环境就类似于画布和画板,只有创建了渲染环境,使用OpenGL函数才会起作用。它不是OpenGL的一部分,而是隶属于操作系统,所以不同的操作系统,创建OpenGL渲染环境的方法也不同。由于是在C#中使用OpenGL,所以本文将使用winAPI创建OpenGL渲染环境。
C# OpenGL接口源码、C# OpenGL编程例子可在百度网盘下载:链接:https://pan.baidu.com/s/1dnIo1s-l6aqlE3IgaMJA5g
提取码:wc0x
一、选择显示窗口
显示窗口就类似于画家的画板,它的作用就是支撑画布,使得我们能够看到画布上的图画。在使用C/C++语言开发OpenGL程序,都需要自己创建显示窗口,当然,glut、glfw等库提供了在Windows系统中创建窗口的函数,这使得创建窗口变得很方便。然而,用C#语言开发OpenGL程序的时候,完全没有必要自己创建显示窗口,因为C#本身提供了大量可视控件,这些可视控件都有一个窗口,我们只需选择一个控件作为显示窗口即可。
上图展现的是在文本框、图片框和按钮上绘制三角形。只要控件是可视的(像Timer这类控件是非可视控件),它都可以作为显示窗口。只要你愿意,你可以把图形绘制在窗体(Form)、图片框(pictureBox)、标签(Label)…甚至是文本框(TextBox)。本文选择PictureBox控件作为显示窗口。
二、用到的winAPI函数
创建OpenGL渲染环境需要用到五个windows API。
1.取得设备上下文(DC,Device Context)
HDC GetDC(HWND hWnd);
1
参数是窗口句柄,返回值是设备上下文句柄。
2.选择像素格式
int ChoosePixelFormat(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd);
1
第一个参数是设备上下文句柄,第二个参数是像素格式描述器(Pixel Format Descriptor),返回值是一个整型,如果成功则返回像素格式索引号,否则返回0;
其中,PIXELFORMATDESCRIPTOR类型是一个结构体,其C语言描述如下:
typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;//该结构体占用存储空间的大小
WORD nVersion;//版本号
DWORD dwFlags;//格式属性
BYTE iPixelType;//颜色模式
BYTE cColorBits;//颜色比特位数
BYTE cRedBits;//红色分量比特位数
BYTE cRedShift;//红色分量偏移量
BYTE cGreenBits;//绿色分量比特位数
BYTE cGreenShift;//绿色分量偏移量
BYTE cBlueBits;//蓝色分量比特位数
BYTE cBlueShift;//蓝色分量偏移量
BYTE cAlphaBits;//alpha分量比特位数
BYTE cAlphaShift;//alpha分量偏移量
BYTE cAccumBits;//累积缓冲区一个像素占用比特位数
BYTE cAccumRedBits;//累积缓冲区红色分量的比特位数
BYTE cAccumGreenBits;//累积缓冲区绿色分量的比特位数
BYTE cAccumBlueBits;//累积缓冲区蓝色分量的比特位数
BYTE cAccumAlphaBits;//累积缓冲区alpha分量的比特位数
BYTE cDepthBits;//深度缓冲区中一个像素占用的比特位数
BYTE cStencilBits;//模板缓冲区中一个像素占用的比特位数
BYTE cAuxBuffers;//辅助缓冲区
BYTE iLayerType;//用于早期的OpenGL,现已忽略
BYTE bReserved;//指定表层与底层的平面数目
DWORD dwLayerMask;//用于早期的OpenGL,现已忽略
DWORD dwVisibleMask;//指定一个底层平面的透明颜色或索引
DWORD dwDamageMask;//用于早期的OpenGL,现已忽略
} PIXELFORMATDESCRIPTOR
3.设置像素格式
BOOL SetPixelFormat(HDC hdc,int format, CONST PIXELFORMATDESCRIPTOR * ppfd);
1
第一个参数是设备上下文句柄,通过GetDC获得;第二个参数是像素格式索引号,通过ChoosePixelFormat获得;第三个是像素格式描述器,需要用户自行设置;如果设置成功则返回true,否则返回false。
4.创建OpenGL渲染上下文
HGLRC wglCreateContext( HDC hdc );
1
参数是设备上下文句柄(HDC),返回值是OpenGL渲染上下文句柄(HGLRC)。HGLRC与HDC具有一样的像素格式。
5.指定OpenGL当前渲染上下文
BOOL wglMakeCurrent( HDC hdc, HGLRC hglrc);
1
第一个参数是设备上下文句柄,第二个参数是OpenGL渲染上下文句柄,如果成功则返回true,否则返回false。
三、C#语言声明windows API
windows API都是用C语言写的,在C#中调用winAPI需要先对这些外部函数进行声明。
1.数据类型的变换
凡是句柄类型,在C#中都用IntPtr类型表示。如HWND类型、HDC类型、HGLRC类型都统一用IntPtr类型表示。对于PIXELFORMATDESCRIPTOR 类型,其C#版的结构体声明如下:
[StructLayout(LayoutKind.Sequential,Pack =1)]
public struct PIXELFORMATDESCRIPTOR
{
public ushort nSize;
public ushort nVersion;
public uint dwFlags;
public byte iPixelType;
public byte cColorBits;
public byte cRedBits;
public byte cRedShift;
public byte cGreenBits;
public byte cGreenShift;
public byte cBlueBits;
public byte cBlueShift;
public byte cAlphaBits;
public byte cAlphaShift;
public byte cAccumBits;
public byte cAccumRedBits;
public byte cAccumGreenBits;
public byte cAccumBlueBits;
public byte cAccumAlphaBits;
public byte cDepthBits;
public byte cStencilBits;
public byte cAuxBuffers;
public byte iLayerType;
public byte bReserved;
public uint dwLayerMask;
public uint dwVisibleMask;
public uint dwDamageMask;
};
2.C#方法声明
[DllImport("user32.dll", ExactSpelling = false, EntryPoint = "GetDC", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll", ExactSpelling = false, EntryPoint = "ChoosePixelFormat", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern int ChoosePixelFormat(IntPtr hdc, IntPtr ppfd);
[DllImport("gdi32.dll", ExactSpelling = false, EntryPoint = "SetPixelFormat", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetPixelFormat(IntPtr hdc, int format, IntPtr ppfd);
[DllImport("opengl32.dll", ExactSpelling = false, EntryPoint = "wglCreateContext", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr wglCreateContext(IntPtr hdc);
[DllImport("opengl32.dll", ExactSpelling = false, EntryPoint = "wglMakeCurrent", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
internal static extern bool wglMakeCurrent(IntPtr hdc, IntPtr hglrc);
四、创建OpenGL渲染环境
下面通过C#代码来说明如何创建OpenGL渲染环境。
要调用windows API需要先引用名称空间:
using System.Runtime.InteropServices;
1
由于还会用到不安全代码,所以还要在“项目->属性”中勾选允许不安全代码。
示例代码:
IntPtr hWnd=pictureBox1.Handle;//图片框的窗口句柄
IntPtr hdc =GetDC(hWnd);//取得设备上下文
PIXELFORMATDESCRIPTOR pfd;//定义一个像素格式描述器
//设置像素格式
pfd.nSize = 40;
pfd.nVersion = 1;
pfd.dwFlags = PFD.PFD_DRAW_TO_WINDOW | PFD.PFD_SUPPORT_OPENGL | PFD.PFD_DOUBLEBUFFER;
pfd.iPixelType = (byte)PFD.PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 0;
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16;
pfd.cStencilBits = 0;
pfd.cAuxBuffers = 0;
pfd.iLayerType = (byte)PFD.PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
int pixelFormat;
unsafe
{
PIXELFORMATDESCRIPTOR* ppfd=&pfd;
pixelFormat =ChoosePixelFormat(hdc,(IntPtr)ppfd);//选择像素格式
SetPixelFormat(hdc, pixelFormat, (IntPtr)ppfd);//设置像素格式
IntPtr hglrc;
hglrc =wglCreateContext(hdc);//建立OpenGL渲染上下文
wglMakeCurrent(hdc, hglrc);//激活当前渲染上下文
}
C#中使用OpenGL(API)创建OpenGL渲染环境相关推荐
- 在Web应用程序中使用Canvas API
更多HTML 5文章请查阅HTML 6在线网站http://www.html5online.com.cn 本文概述 本文介绍如何在一个Web应用程序中利用HTML 5中的Canvas API创建.编辑 ...
- 在Win32程序中创建OpenGL渲染环境
在Win32程序中创建OpenGL渲染环境 创建opengl渲染环境步骤: 选定像素格式 //WinMain()HDC dc = GetDC(hwnd);PIXELFORMATDESCRIPTOR p ...
- 如何在Python中创建OpenGL/Glut
OpenGL(开放图形库)是一种跨语言.多平台的应用程序编程接口(API),用于绘制二维和三维计算机图形. API通常用于与图形处理单元(GPU)交互,以实现硬件加速渲染.OpenGL由Silicon ...
- 【OpenGL从入门到精通(一)】Windows搭建OpenGL的渲染环境,并初始化一个OPenGL窗口
注意:需要在Windows 窗口程序下,而不能是控制台程序,Windows平台的VS下已经包含了OpenGL相关的API,可以直接引用 #include <windows.h> #incl ...
- OpenGL API简介
转自http://blog.csdn.net/menguio/article/details/6112733 OpenGL API 简介 开发基于OpenGL的应用程序,必须先了解OpenGL的库函数 ...
- Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据
系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...
- OpenGL渲染模型 || 3. opengl 将模型成渲染图片
前言 最近项目中需要使用到OpenGL对3D模型进行渲染. 已有数据为: 带纹理的3D模型 模型上的关键点. 需要实现的功能: 读取和保存 带纹理的3D模型.读取模型的关键点 对模型进行渲染,保存 ...
- 利用现代OpenGL API大幅度减少由于执行驱动导致CPU的开销
link:http://www.wtoutiao.com/p/1e5gLML.html Imagination Tech · 2016-01-02 11:15 作者:octday 影响OpenGL绘制 ...
- android opengl流程,【Android OpenGL ES】Android Opengl ES创建流程
在android 1.0rc2 sdk中,提供了以下包支持Opengl ES 编程: 一.openglES包 android.opengl Class: GLDebugHelper:用于调试OpenG ...
最新文章
- CRFsuite:CRF 工具包及sklearn-crfsuite
- 根据一级分类查询所有子级分类
- select + 线程池 回应服务器(windows)
- CANopen | 对象字典OD 04 - 创建对象字典的变量(映射变量)
- 漂亮的页面过渡动画源码
- js 取得数组下标_剖析JS和Redis的数据结构设计:数组
- 孙鑫VC学习笔记:第三讲 MFC应用程序框架
- 关于TUN/TAP网卡二三事以及物理网卡Ring buffer
- while循环python次数定义_Python学习笔记之While循环用法分析
- 怎样压缩图片到100k?如何把电脑图片缩小kb?
- iOS视频添加水印两种方式(不用到第三方框架)
- 微信每天处理2.05亿通话 运营商只剩卖流量
- 大连商务英语学校百家外语国际部商务英语与普通英语的不同之处
- 计算机毕业设计java+ssm酒店管理系统(源码+系统+mysql数据库+Lw文档)
- 正则表达式(常用正则表达式)
- CAD颜色索转RGB(方法一)
- 西门子1200PLC大型项目包膜机程序,气缸,通讯,机械手,模拟量等,各种FB块
- 【转】程序语言不是工具
- springboot整合redis,使用redisTemplate实现简易秒杀功能,使用jmeter压力测试秒杀接口
- 金三银四如何抱佛脚?2022 最新大厂 Java 面试真题合集(附权威答案)
热门文章
- K 个一组翻转链表Python解法
- python学习-模块和包
- python可视化添加文本_python Matplotlib基础--如何添加文本和标注
- bbs php redis,LAMP+redis搭建discuz论坛
- tomcat 设置java内存_Tomcat 设置JVM内存大小
- double处理arithmeticexception为什么不报错_板式换热器为什么冷热不均匀?应怎样检查并简单处理?...
- iframe嵌套的html高度,iframe 多层嵌套 无限嵌套 高度自适应的解决方案
- java new class 直接调用_java中创建对象的的两种方式具体解释,一个是new一个是调用Class类的newinstance方法?...
- 后氧传感器损坏的危害_几种快速判断氧传感器故障的简便方法
- matlab程序生成.dll,matlab 调用fortran生成DLL