由于没有使用GLFW库,接下来得费一番功夫。

阅读这篇文章前请看一下这个网页:https://learnopengl-cn.github.io/01%20Getting%20started/02%20Creating%20a%20window/

以下,我摘取了一点片段

Windows上的OpenGL库

  如果你是Windows平台,opengl32.lib已经包含在Microsoft SDK里了,它在Visual Studio安装的时候就默认安装了。由于这篇教程用的是VS编译器,并且是在Windows操作系统上,我们只需将opengl32.lib添加进连接器设置里就行了。

GLEW

到这里,我们仍然有一件事要做。因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。取得地址的方法因平台而异,在Windows上会是类似这样:

// 定义函数原型
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// 找到正确的函数并赋值给函数指针
GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// 现在函数可以被正常调用了
GLuint buffer;
glGenBuffers(, &buffer);

你可以看到代码非常复杂,而且很繁琐,我们需要对每个可能使用的函数都要重复这个过程。幸运的是,有些库能简化此过程,其中GLEW是目前最新,也是最流行的库。

编译和链接GLEW

  GLEW是OpenGL Extension Wrangler Library的缩写,它能解决我们上面提到的那个繁琐的问题。因为GLEW也是一个库,我们同样需要构建并将其链接进工程。GLEW可以从这里下载,你同样可以选择下载二进制版本,如果你的目标平台列在上面的话,或者下载源码编译,步骤和编译GLFW时差不多。记住,如果不确定的话,选择32位的二进制版本。

  我们使用GLEW的静态版本glew32s.lib(注意这里的“s”),将库文件添加到你的库目录,将include内容添加到你的include目录。接下来,在VS的链接器选项里加上glew32s.lib。注意GLFW3(默认)也是编译成了一个静态库。

  如果你希望静态链接GLEW,必须在包含GLEW头文件之前定义预处理器宏GLEW_STATIC

#define GLEW_STATIC
#include <GL/glew.h>

如果你希望动态链接,那么你可以省略这个宏。但是记住使用动态链接的话你需要拷贝一份.DLL文件到你的应用程序目录。

接下来要做的是链接 opengl32.lib 和 glew32s.lib这 两个库进工程

在Windows中,OpenGL命令是通过OpenGL Render Context(以下简称RC)来执行的。这个RC是OpenGL和Windows之间的纽带。

每个RC创建时,必须指定一个DC(Windows Device Context 也就是那个通常用于GDI的设备环境DC)。RC的绘制目标,就是这个DC所对应的窗口。

每次RC创建时,应该设置一下DC的像素格式。

添加一个新类 GraphicsContext 头文件

#pragma once
#define GLEW_STATIC #include "Common.h"
#include <Windows.h>
#include "GLEW\glew.h" namespace Simple2D
{
class RenderWindow; class DLL_export GraphicsContext
{
public:
GraphicsContext(RenderWindow* renderWindow);
~GraphicsContext(); void createOpenGLContext();
void flip(); private:
RenderWindow* pRenderWindow; HGLRC openglContext;
HDC deviceContext;
};
}

注意代码中的这个宏  #define GLEW_STATIC,没有它你可能编译错误。

它的实现

#include "GraphicsContext.h"
#include "RenderWindow.h" namespace Simple2D
{
GraphicsContext::GraphicsContext(RenderWindow* renderWindow)
: pRenderWindow(renderWindow)
, openglRenderContext()
, deviceContext()
{
this->createOpenGLContext();
} GraphicsContext::~GraphicsContext()
{
wglDeleteContext(openglRenderContext);
ReleaseDC(pRenderWindow->getHwnd(), deviceContext);
} void GraphicsContext::createOpenGLContext()
{
if ( openglRenderContext == ) {
deviceContext = GetDC(pRenderWindow->getHwnd()); PIXELFORMATDESCRIPTOR pfd = { };
int color_deep = GetDeviceCaps(deviceContext, BITSPIXEL); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = ;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = color_deep;
pfd.cDepthBits = ;
pfd.cStencilBits = ;
pfd.iLayerType = PFD_MAIN_PLANE; int pixle_format = ChoosePixelFormat(deviceContext, &pfd);
SetPixelFormat(deviceContext, pixle_format, &pfd); /* 创建 OpenGL 渲染上下文 */
openglRenderContext = wglCreateContext(deviceContext);
if ( openglRenderContext == ) exit(); /* 选择 openglRenderContext 作为当前线程的 openglRenderContext */
if ( wglMakeCurrent(deviceContext, openglRenderContext) == ) exit(); /* GLEW 是用来管理 OpenGL 的函数指针的,所以在调用任何 OpenGL 的函数之前我们需要初始化GLEW */
if ( glewInit() != GLEW_OK ) exit(); /* 设置视口,大小为客户区大小 */
SIZE size = pRenderWindow->getClientSize();
glViewport(, , size.cx, size.cy);
}
} void GraphicsContext::flip()
{
/* 使用一个自定义的颜色清空屏幕,这里使用红色 */
glClearColor(1.0f, , , 1.0f); /* 调用glClear函数来清空屏幕的颜色缓冲 */
glClear(GL_COLOR_BUFFER_BIT); // 交换当前缓冲区和后台缓冲区
SwapBuffers(deviceContext);
}
}

最后在主函数中创建 GraphicsContext

#pragma once

#include <Windows.h>
#include "RenderWindow.h"
#include "GraphicsContext.h" using namespace Simple2D; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
RenderWindow window(DEFAULT_WIN_W, DEFAULT_WIN_H);
GraphicsContext graphicsContext(&window); MSG msg = { };
while ( msg.message != WM_QUIT ) {
if ( PeekMessage(&msg, , , , PM_REMOVE) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
graphicsContext.flip();
}
} return ;
}

编译代码,如果出现以下错误

可以在项目中忽略这个库

运行后出现这个窗口,显示为红色,证明搭建成功了

需要源码的可以点击这个链接:http://files.cnblogs.com/files/ForEmail5/Simple2D-02.rar

基于OpenGL编写一个简易的2D渲染框架-02 搭建OpenGL环境的更多相关文章

  1. 基于OpenGL编写一个简易的2D渲染框架-06 编写一个粒子系统

    在这篇文章中,我将详细说明如何编写一个简易的粒子系统. 粒子系统可以模拟许多效果,下图便是这次的粒子系统的显示效果.为了方便演示,就弄成了一个动图. 图中,同时显示了 7 种不同粒子效果,看上去效果挺 ...

  2. 基于OpenGL编写一个简易的2D渲染框架-05 渲染文本

    阅读文章前需要了解的知识:文本渲染 https://learnopengl-cn.github.io/06%20In%20Practice/02%20Text%20Rendering/ 简要步骤: 获 ...

  3. 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口

    最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了. 如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/ 我用的 ...

  4. 基于OpenGL编写一个简易的2D渲染框架-08 重构渲染器-整体架构

    事实上,前面编写的渲染器 Renderer 非常简陋,虽然能够进行一些简单的渲染,但是它并不能满足我们的要求. 当渲染粒子系统时,需要开启混合模式,但渲染其他顶点时却不需要开启混合模式.所以同时渲染粒 ...

  5. 基于OpenGL编写一个简易的2D渲染框架-03 渲染基本几何图形

    阅读文章前需要了解的知识,你好,三角形:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 要 ...

  6. 基于OpenGL编写一个简易的2D渲染框架-04 绘制图片

    阅读文章前需要了解的知识,纹理:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 过程简述:利用 FreeI ...

  7. 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader

    Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...

  8. 基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer

    假如要渲染一个纯色矩形在窗口上,应该怎么做? 先确定顶点的格式,一个顶点应该包含位置信息 vec3 以及颜色信息 vec4,所以顶点的结构体定义可以这样: struct Vertex { Vec3 p ...

  9. 基于OpenGL编写一个简易的2D渲染框架-10 重构渲染器-Pass

    Pass,渲染通路,一个渲染通路指的是一次像素处理和一次顶点处理,也就是指的是一次绘制.简单来说就是顶点数据在渲染管线中走一遍最后绘制. 渲染粒子系统的粒子时,需要开启 OpenGL 的混合模式,并使 ...

随机推荐

  1. 使用ioctl获取网卡统计信息

    ethtool -S获取接口统计信息总共分三步: 1.获取统计项个数,使用SIOCETHTOOL+ETHTOOL_GSSET_INFO 2.(可选)获取统计项名字,使用SIOCETHTOOL+ETHT ...

  2. enjoy dollar vs cash dollar

    當 enJoy 卡 客 戶 憑 enJoy 卡 於 enJoy 卡 「 特 約 商 戶 」 簽 賬 消 費 , 累 積 之 enJoy Dollars 及 Cash Dollars 可 在 同 一 交 ...

  3. Flyway 简单入门教程

    原文地址:Flyway 简单入门教程 博客地址:http://www.extlight.com 一.前言 Flyway 是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式.Flyway 可以 ...

  4. 大快DKhadoop安装教程与常见问题汇总

    上周分别就DKHadoop的安装准备工作以及服务器操作系统配置写了两篇分享的文章,这是个人第一次尝试写一个系统性的分享文章,必然会有很多疏漏的地方,还望见谅吧.今天分享的是DKHadoop安装以及常见 ...

  5. CC2530中串口波特率改为9600时单个数据包来不及接收的解决方案

    在调试CC2530过程中发现波特率改为9600时,单个包仅有3个Byte时,接收DMA就会启动 因而数据包被强迫拆分成多个,显然只要将接收DMA启动延时做到足够大即可. 具体修改内容如下图所示: 经过 ...

  6. rainmeter 修正天气插件信息不准确 设置居住城市

    rainmeter天气插件的原理是用爬虫抓取一个天气网页然后用自带的那一套正则表达式匹配出天气信息 在国外官网社区下载的插件的天气信息城市都会出现问题(因为插件作者又不知道你在哪),解决方法是在原基础 ...

  7. "二阶“条件概率

    公式: P(E|F)=P(E|GF)P(G|F)+P(E|GcF)P(Gc|F) 解释: 已知F发生,E发生的条件概率为P(E|F). 现在多考虑一个条件G,G可能发生也可能不发生. 若F已发生条件下 ...

  8. [转][C#]验证

    文件下载 本文仅做备份,参考自:http://www.cnblogs.com/LoveJenny/p/opensource_software_license_tool__easyhelper_easy ...

  9. shell 11函数

    函数定义 function 方法名(){ command return int; } 注意:function可加可不加 #shell #!/bin/sh function fun1(){ echo & ...

  10. Apache JMeter配置、安装

    一. 工具描述 apache jmeter是100%的java桌面应用程序,它被设计用来加载被测试软件功能特性.度量被测试软件的性能.设计jmeter的初衷是测试web应用,后来又扩充了其它的功能.j ...