大二的时候开始想着做游戏,因为学校的课程实在是无聊就想着做些有意义的事情。毕竟学了编程这一行就得做些实事,于是就在网上搜了一下图形编程,偶然的了解到了Opengl (同时还有Windows上的Direct3D 但由于Opengl的跨平台等原因入了坑)。虽然到现在也没写出什么小游戏出来,毕竟一个用一个那么底层的图像接口做一个有玩法有乐趣的游戏工作量还是很大的。然后因为最近刚开了博客想起这段学习经历,于是这几天就再看了一下我之前写过的代码,把我的理解写

下来希望对别人有帮助同时也写给未来的自己。

  首先我是在Windows上编写OpenGL的,但网上大多数都叫你去下一个glut库来创建Windows窗口,因为这样简单方便不用再去学Windows的API。这些教程也就不需要再给你介绍这些东西,但我个人觉得应该用Windows的API来创建窗口;这因为Windows提供很多API,通过这些API我们可以实现很多功能,而创建窗口的这些API是很基础的;学习这些API你可以更好的了解Windows,而且使用API可以更加灵活的定制你自己想要的窗口和实现甘glut库没有提供的功能。对于Linux由于我学识有限还不知道怎么使用Opengl大家可以自行百度一下。

// Win32Project.cpp : 定义应用程序的入口点。
// #include "stdafx.h" //Windows消息循环 处理各种信息
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{ switch (message)
{
case WM_CREATE:
return ;
case WM_CLOSE:
PostQuitMessage();
return ; case WM_DESTROY:
return ; case WM_KEYDOWN: //键盘按下消息
return ; default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
} //Windows程序入口函数
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int iCmdShow)
{ HDC hDC;
HGLRC hRC;
MSG msg;
BOOL bQuit = FALSE; WNDCLASS wc; wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = ;
wc.cbWndExtra = ;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("GLSample");
RegisterClass(&wc); //下面这个函数中间的4个数字前两个是屏幕的x,y后面是高宽
HWND hWnd = CreateWindowA("GLSample", "OpenGL Sample", WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, , , , , NULL, NULL, hInstance, NULL);
if (hWnd == NULL) return -; hDC = GetDC(hWnd); PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = ;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = ;
pfd.cDepthBits = ;
pfd.iLayerType = PFD_MAIN_PLANE; int iFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, iFormat, &pfd); hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC); while (!bQuit)
{ if (PeekMessage(&msg, NULL, , , PM_REMOVE))
{ if (msg.message == WM_QUIT)
{
bQuit = TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{ glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*
   在这里添加Opengl代码
*/
SwapBuffers(hDC); Sleep();
}
} wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
DestroyWindow(hWnd); return msg.wParam;
}

  开头CallBack标志的函数是消息回调函数,Windows是一个由窗口组成的操作系统,每一个窗口都由唯一的一个窗口句柄(四个字节的数字标识),窗口之间有父子关系,操作系统会给主窗口分配一个消息队列,当用户操作时比如移动鼠标(WM_MOUSEMOVE)、按下键盘(WM_KEYDOWN)都会有一个对应的消息被送到消息队列中,而这里的CallBack函数就是默认的处理消息的函数,四个参数也是Windows要求的默认格式,其中重要的参数是UINT message,每次有消息发送到窗口,处理函数被调用消息通过UINT message传进来,我们添加一个判断语句switch就可以对对应消息处理,比如对按下键盘进行处理switch(message) case WM_KEYDOWN: return 0;在return 0之前可以加任何你想得到操作。return 0;表示的是消息已经被你处理,返回告诉系统不需要进行处理,对于你没有处理的消息通过return DefWindowProc(hWnd, message, wParam, lParam)来交给系统处理。

  WinMain函数是程序的入口点有固定的格式,Win32程序开始执行时从这里进入并开始执行程序,相当与控制台程序的main函数,他的四个参数:第一个是窗口的实例句柄,第二个是之前的实例句柄,第三个是通过控制台来启动程序是传入的字符串指针,第四个是窗口的显示方式列如SW_NORMAL,WM_HIDE。接下来是窗口创建过程,首先你要了解Windows的窗口是包含很多数据的,比如他的位置大小、窗口名称和样式以及图标信息等等,是由很多数据组成的。而你要创建窗口就必须要给出这些信息,Windowsi给开发者提供了一个创建窗口的Api ---- CreateWindowA() (A表示的是Ascll码 字符串是Ascll格式)CreateWindow有很多参数,不过都比较好记忆。前面说了创建窗口需要很多信息所以在调用CreateWindow之前需要填写窗口信息,Windows提供了一个WNDCLASS的结构体调用CreateWindow之前必须声明一个WNDCLASS变量并填写信息,填写好了后再通过RegisterClass这个API把这个结构体提交给系统。CreateWIndow就可以创建一个窗口了。PIXELFORMATDESCRIPTOR结构体是为了使窗口能显示OpenGL渲染后的图片在窗口上填写的信息,然后  int iFormat = ChoosePixelFormat(hDC, &pfd);  SetPixelFormat(hDC, iFormat, &pfd);  这两段代码分别是把结构体PIXELFORMATDESCRIPTOR与设备环境句柄HDC绑定在一起,这个设备环境句柄是在Windows窗口上渲染图片或画图之类的十分重要的句柄(句柄在Windows里是一个很重要的概念,你可以把它理解为一个四字节的标识符,Windows有很多窗口要管理,窗口又有子窗口,每个窗口都有设备环境所以要通过一个值来区分开他们)。

    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);
 

第一句代码是通过HDC生成OpenGL资源环境句柄hRC,而第二句则是把设备环境句柄和OpenGL环境句柄绑定在一起。之后就可以调用OpenGL的基本语句了(列如:glColor3f、glVertex3f、glBegin、glEnd。。。)不过最后要记得 调用

  wglMakeCurrent(NULL, NULL);

  wglDeleteContext(hRC);

  ReleaseDC(hWnd, hDC);

来解绑和释放OpenGL资源环境句柄、设备环境句柄。

  上面这个代码你要用Visual Studio或Visual C++创建一个Win32工程来使用,因为我用的是Visual Studio 2015所以以下的图片都是在VS2015截的,VS和VC的向导界面是不同的,但大概意思的选项还是能找到的,因为博主比较懒所以就只在关键步骤发图了。

  打开VS或VC → 新建 → 项目

  弹出创建向导,找到Visual C++下的Win32,里面有个Win32控制台和Win32项目,选择Win32项目写一个喜欢的项目名字点确定。

  之后会再弹出一个向导,直接点下一步确定不,过要注意以下选项。

  如果你是初学者,你应该在创建向导界面不要勾选空项目这个选项,他自己生成的代码可以帮助你更好的分析和入门

接下来VS会帮你创建好很多文件,这些文件你可能不知道有什么作用。

如下图:

但关键的文件就4个stdafx.h , stdafx.cpp ,你取的工程名加.h 和工程名.cpp(PS:这里我取得名字为Win32Project3)。

然后再简单讲解一下4个文件的作用

stdafx.h:你把VS自带的头文件例如<iostream>、<Windows.h>都包含在这个文件中。在你第一次编译时生成一个.pch文件之后编译编译器会利用这个文件加快你的编译速度

stdafx.cpp:包含stdafx.h头文件具体为什么要有这个文件我就不太清楚了知道的大佬可以留言给我

Win32Project.h:头文件可以写你自己定义的结构体、类和变量

Win32Project.cpp:这次我们的代码就写在这里WinMain主要的文件

现在创建好了一个工程你点调试→开始调试运行就能弹出一个Windows窗口

接下来双击打开Win32Project.cpp删除原来的代码把文章开头的代码粘贴过来

开始调试发现报错因为没有引入头文件

在stdafx.h文件中加入 #include <gl/GL.h>当然你也可以直接加在Win32Project.cpp文件里

再次调试运行 一般情况下都会出现如下结果

这是因为没有引入OpenGL的Lib库文件可以在stdafx.h 或 Win32Project.cpp加入#pragma comment(lib, "opengl32.lib")来引用OpenGL库文件

最后调试运行

如果你的窗口变黄了就代表你成功了

下篇Blog我打算写OpenGL的glew库的使用,个人觉得glew对OpenGL来说是十分重要的。

Opengl 之 窗口初体验 ------ By YDD的铁皮锅的更多相关文章

  1. Opengl ES Glew库 ----- By YDD的铁皮锅

    前一篇随笔我写了Opengl的窗口创建,这一篇随笔我要写OpenGL glew库的使用.首先需要引入头文件h,库文件Lib和动态链接库DLL, 百度搜索OpenGL glew库找到这个纯英文网站,尽量 ...

  2. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  3. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  4. python窗体——pyqt初体验

    连续两周留作业要写ftp的作业,从第一周就想实现一个窗体版本的,但是时间实在太短,qt零基础选手表示压力很大,幸好又延长了一周时间,所以也就有了今天这篇文章...只是为了介绍一些速成的方法,还有初学者 ...

  5. node.js 初体验

    node.js 初体验 2011-10-31 22:56 by 聂微东, 174545 阅读, 118 评论, 收藏, 编辑 PS: ~ 此篇文章的进阶内容在为<Nodejs初阶之express ...

  6. iOS7初体验(1)——第一个应用程序HelloWorld

    iOS7 Beta已经发布了,迫不及待地下载了iOS 7及Xcode 5并体验了一下.先做一个简单的Hello World看看都有哪些变化吧. 1. 启动Xcode5-DP: 2. 从菜单选择File ...

  7. Python基础学习参考(一):python初体验

    一.前期准备 对于python的学习,首先的有一个硬件电脑,软件python的运行环境.说了一句废话,对于很多初学者而言,安装运行环境配置环境变量的什么的各种头疼,常常在第一步就被卡死了,对于pyth ...

  8. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  9. 中文代码示例之NW.js桌面应用开发初体验

    先看到了NW.js(应该是前身node-webkit的缩写? 觉得该起个更讲究的名字, 如果是NorthWest之意的话, logo(见下)里的指南针好像也没指着西北啊)和Electron的比较文章: ...

随机推荐

  1. python改变导入模块中的变量的问题

    Python中循环函数1调用函数2,函数2中import了一个模块,函数1: def run(): for a in b: runTest(a,patter) 函数2: def runTest(cas ...

  2. MultipartFile 图片上传到Linux服务器Tomcat下的webapps目录

    第一次接触 linux 服务器,做图片上传的时候遇到了些坑,搞了些天总算成功了,记录一下 /** * 上传图片 * * @param request * @param file * @return * ...

  3. 在线清空nohup.out内容

    通过 cat /dev/null > filename 命令可以在线清空nohup.out里的内容

  4. 插件化框架解读之Android 资源加载机制详解(二)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680Android提供了一种非常灵活的资源系统,可以根据不同的条件提供 ...

  5. git 上传本地代码

    新增本地代码到远程库 http://blog.csdn.net/hanhailong726188/article/details/46738929 github配置教程 http://www.runo ...

  6. python内存管理及垃圾回收

    一.python的内存管理 python内部将所有类型分成两种,一种由单个元素组成,一种由多个元素组成.利用不同结构体进行区分 /* Nothing is actually declared to b ...

  7. 高精度求A*B(FFT)

    A * B Problem Plus 链接:http://acm.hdu.edu.cn/showproblem.php?pid=1402 Time Limit: 2000/1000 MS (Java/ ...

  8. 解决VMwave下卡死的办法

    在VMwave路径下找到vmwave.log文件: 如上图所示:在资源监视器中找到name = vmwave-vmx.exe ,pid = 5940的进程,然后杀死.

  9. Spring、SpringMVC、SpringBoot、SpringCloud概述

    spring和springMvc: 1. spring是一个一站式的轻量级的java开发框架,核心是控制反转(IOC)和面向切面(AOP),针对于开发的WEB层(springMvc).业务层(Ioc) ...

  10. Qt QSS图片样式切割,三种状态normal,hover,pressed

    要切割的样式图片如下: pix_Button->setStyleSheet("QPushButton{ border-image:url(:/image/MyButtonimage/m ...