基于opengl编写一个简易的2d渲染框架02——搭建opengl环境

为了邮箱5 为了邮箱5     2022-08-29     556

关键词:

由于没有使用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(1, &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(0)
        , deviceContext(0)
    {
        this->createOpenGLContext();
    }

    GraphicsContext::~GraphicsContext()
    {
        wglDeleteContext(openglRenderContext);
        ReleaseDC(pRenderWindow->getHwnd(), deviceContext);
    }

    void GraphicsContext::createOpenGLContext()
    {
        if ( openglRenderContext == 0 ) {
            deviceContext = GetDC(pRenderWindow->getHwnd());

            PIXELFORMATDESCRIPTOR pfd = { 0 };
            int color_deep = GetDeviceCaps(deviceContext, BITSPIXEL);

            pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
            pfd.nVersion = 1;
            pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
            pfd.iPixelType = PFD_TYPE_RGBA;
            pfd.cColorBits = color_deep;
            pfd.cDepthBits = 0;
            pfd.cStencilBits = 0;
            pfd.iLayerType = PFD_MAIN_PLANE;

            int pixle_format = ChoosePixelFormat(deviceContext, &pfd);
            SetPixelFormat(deviceContext, pixle_format, &pfd);

            /* 创建 OpenGL 渲染上下文 */
            openglRenderContext = wglCreateContext(deviceContext);
            if ( openglRenderContext == 0 ) exit(0);

            /* 选择 openglRenderContext 作为当前线程的 openglRenderContext */
            if ( wglMakeCurrent(deviceContext, openglRenderContext) == 0 ) exit(1);

            /* GLEW 是用来管理 OpenGL 的函数指针的,所以在调用任何 OpenGL 的函数之前我们需要初始化GLEW */
            if ( glewInit() != GLEW_OK ) exit(1);

            /* 设置视口,大小为客户区大小 */
            SIZE size = pRenderWindow->getClientSize();
            glViewport(0, 0, size.cx, size.cy);
        }
    }

    void GraphicsContext::flip()
    {
        /* 使用一个自定义的颜色清空屏幕,这里使用红色 */
        glClearColor(1.0f, 0, 0, 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 = { 0 };
    while ( msg.message != WM_QUIT ) {
        if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) ) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else {
            graphicsContext.flip();
        }
    }

    return 0;
}

 

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

可以在项目中忽略这个库

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

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

基于opengl编写一个简易的2d渲染框架01——创建窗口

最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了。如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/我用的是vs2013,使用C++语言编写项目。这个小项目叫Simple2D,意味着简易的2D... 查看详情

基于opengl编写一个简易的2d渲染框架-04绘制图片

阅读文章前需要了解的知识,纹理:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/   过程简述:利用FreeImage库加载图像数据,再创建OpenGL纹理,通过Canvas2D画布绘制,最后又Renderer渲染器渲染   本来想用soil库... 查看详情

基于opengl编写一个简易的2d渲染框架-09重构渲染器-shader

  Shader只是进行一些简单的封装,主要功能:    1、编译着色程序    2、绑定Uniform数据    3、根据着色程序的顶点属性传递顶点数据到GPU   着色程序的编译GLuintShader::createShaderProgram(constchar*vsname,constchar*p... 查看详情

基于opengl编写一个简易的2d渲染框架-13使用例子

 这是重构渲染器的最后一部分了,将会给出一个demo,测试模板测试、裁剪测试、半透明排序等等: 上图是本次demo的效果图,中间的绿色图形展现的是模板测试。 模板测试voidinit(Pass*&p1,Pass*&p2){p1=newPass;p2=newPass;... 查看详情

基于opengl编写一个简易的2d渲染框架-12重构渲染器-blockallocator

 BlockAllocator的内存管理情况可以用下图表示   整体思路是,先分配一大块内存Chunk,然后将Chunk分割成小块Block。由于Block是链表的一个结点,所以可以通过链表的形式把未使用的Block连接起来,并保存到pFreeLists中。当... 查看详情

基于opengl编写一个简易的2d渲染框架-08重构渲染器-整体架构

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

基于opengl编写一个简易的2d渲染框架-11重构渲染器-renderer

 假如要渲染一个纯色矩形在窗口上,应该怎么做?先确定顶点的格式,一个顶点应该包含位置信息vec3以及颜色信息vec4,所以顶点的结构体定义可以这样:structVertex{Vec3position;Vec4color;};然后填充矩形四个顶点是数据信息:Verte... 查看详情

基于opengl编写一个简易的2d渲染框架-07鼠标事件和键盘事件

这次为程序添加鼠标事件和键盘事件   当检测到鼠标事件和键盘事件的信息时,捕获其信息并将信息传送到需要信息的对象处理。为此,需要一个可以分派信息的对象,这个对象能够正确的把信息交到正确的对象。 实... 查看详情

基于opengles的深度学习框架编写

基于OpenGLES的深度学习框架编写背景与工程定位背景项目组基于深度学习实现了视频风格化和人像抠图的功能,但这是在PC/服务端上跑的,现在需要移植到移动端,因此需要一个移动端的深度学习的计算框架。同类型的库caffe-andr... 查看详情

在 MacOS 中模糊的 Opengl 像素完美渲染

】在MacOS中模糊的Opengl像素完美渲染【英文标题】:OpenGLpixel-perfectrenderingblurredinMacOSX【发布时间】:2014-08-2419:02:06【问题描述】:我正在编写一个跨平台应用程序,它使用OpenGL绘制从PNG文件读取的2d图像。我的程序适用于Linux、Wi... 查看详情

opengl绘制三角形(代码片段)

...对象:ElementBufferObject,EBO或IndexBufferObject,IBO渲染管线在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素。3D坐标转为2D坐标的处理过程是由Ope... 查看详情

OpenGL 2D像素完美渲染

】OpenGL2D像素完美渲染【英文标题】:OpenGL2Dpixelperfectrendering【发布时间】:2013-12-2115:04:10【问题描述】:我正在尝试渲染2D图像,以便它完全覆盖整个窗口。对于我的测试,我设置了一个窗口,使客户区正好是320x240,纹理也是... 查看详情

OpenGL 2d矩形没有被渲染

】OpenGL2d矩形没有被渲染【英文标题】:OpenGL2drectanglenotbeingrendered【发布时间】:2016-12-2200:07:43【问题描述】:我正在尝试在屏幕上渲染一个矩形。程序运行时,只显示清晰的颜色,没有矩形显示。代码如下:glClearColor(0.0,0.0,0.0,... 查看详情

OpenGL:如何在 3d 模式下优化多层相互重叠的 2d 渲染?

】OpenGL:如何在3d模式下优化多层相互重叠的2d渲染?【英文标题】:OpenGL:Howtooptimize2drenderingwithmultiplelayersoverlappingeachotherin3dmode?【发布时间】:2011-06-0612:36:31【问题描述】:我知道如何通过简单地首先渲染最近的平面来加速3d渲... 查看详情

opengl工作流程

  在OpenGL中,一切事物都在3D空间中,但我们的屏幕坐标确实2D像素数组,OpenGL大部分工作就是把3D坐标转换成适应屏幕的2D像素。3D坐标转换成2D屏幕坐标的过程是有OpenGL的图形渲染管线管理的。图形渲染管线的工作可以被划分... 查看详情

opengl-渲染流程

参考技术A在OpenGL中,任何事物都处于3D空间中,而屏幕和窗口却都是2D像素数组,这就导致了OpenGL大部分工作都是关于把3D坐标转变为适配你屏幕的2D像素,3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(指的是一堆原始图... 查看详情

使用 opencl 将软件渲染到 opengl 2d 视图 [关闭]

】使用opencl将软件渲染到opengl2d视图[关闭]【英文标题】:softwarerenderingwithopenclontoopengl2dview[closed]【发布时间】:2011-07-0606:59:44【问题描述】:我想构建一个小的软件渲染库,因为我喜欢体素的想法,以及其他可能的替代渲染方... 查看详情

iOS 中基于矢量的实时 OSM 渲染器(使用 OpenGL ES)

】iOS中基于矢量的实时OSM渲染器(使用OpenGLES)【英文标题】:Realtimevector-basedOSMrendereriniOS(usingOpenGLES)【发布时间】:2013-04-2415:30:09【问题描述】:我正在寻找一种解决方案,它允许使用OpenStreetMap数据在iOS中渲染基于矢量的2D俯... 查看详情