使用 NuGet 快速创建 OpenGL 项目

news2024/12/24 10:30:45

C++ 目前还没有一个标准的 C++ 依赖包管理器,传统上都是手动去下载源码编译(经典的例如 make),或者直接下载预编译好的库文件(例如没有开源的)和头文件。之后在项目里配置对应的头文件路径和库路径。这个过程非常繁琐,而且枯燥。对于 Windows 上的用户,其实可以考虑使用 NuGet 安装所需要的依赖。NuGet 会自动下载依赖并配置好,省去很多繁琐的过程。

什么是 NuGet

简单来讲,它是一个包管理的平台。类似,Python 的 Pip、JavaScript 的 npm。

创建一个项目

  • Visual Studio 2022
  • 平台工具集:v143

NuGet

在 【工具】 中可以打开 NuGet。

NuGet 管理器

引入 SDL2 库

搜索 SDL 并添加到项目中。

NuGet 管理器

现在 SDL 库就引入到项目中了,就是这么简单。可以直接引用头文件使用 SDL 库。接下来,尝试使用一下 SDL。

Game 基础框架

关于这部分内容,推荐参考:Xcode与C++之游戏开发:创建环境

实现一个基础的游戏框架:

// Game.h
#pragma once
#include <SDL.h>

// Game class
class Game
{
public:
	Game();
	// 初始化游戏
	bool Initialize();
	// 运行游戏循环直到游戏结束
	void RunLoop();
	// 关闭游戏
	void Shutdown();
private:
	// 处理进程输入
	void ProcessInput();
	// 更新游戏
	void UpdateGame();
	// 生成输出
	void GenerateOutput();

	// 通过 SDL 创建窗体
	SDL_Window* mWindow;

	// 继续运行
	bool mIsRunning;
};

对应的具体实现:

// Game.cpp
#include "Game.h"

Game::Game()
	:mWindow(nullptr)
	, mIsRunning(true)
{
}

bool Game::Initialize()
{
	int sdlResult = SDL_Init(SDL_INIT_VIDEO);
	if (sdlResult != 0)
	{
		SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
		return false;
	}

	mWindow = SDL_CreateWindow(
		"OpenGLNu",
		100,
		100,
		1024,
		768,
		SDL_WINDOW_OPENGL
	);

	if (!mWindow)
	{
		SDL_Log("Failed to create window: %s", SDL_GetError());
		return false;
	}

	return true;
}

void Game::RunLoop()
{
	while (mIsRunning)
	{
		ProcessInput();
		UpdateGame();
		GenerateOutput();
	}
}

void Game::Shutdown()
{
	SDL_DestroyWindow(mWindow);
	SDL_Quit();
}

void Game::ProcessInput()
{
	SDL_Event event;

	// 有 event 在队列就一直循环
	while (SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			mIsRunning = false;
			break;
		default:
			break;
		}
	}

	// 获取键盘的状态
	const Uint8* state = SDL_GetKeyboardState(nullptr);
	// 如果按了 Esc,结束循环
	if (state[SDL_SCANCODE_ESCAPE])
	{
		mIsRunning = false;
	}
}

void Game::UpdateGame()
{
}

void Game::GenerateOutput()
{
}

创建一个 Main.cpp 调用 Game

#include <iostream>

#include "Game.h"

int main(int argc, char* argv[])
{
	Game game;
	if (game.Initialize())
	{
		game.RunLoop();
	}
	game.Shutdown();
	return 0;
}

可以直接编译运行。

SDL

OpenGL

上面的代码中,SDL_WINDOW_OPENGL 属性指定了使用 OpenGL,下一步就是要创建一个 OpenGL 的上下文(OpenGL 被设计成一个状态机)。上下文可以看成是 OpenGL 的 World(世界),包含了色彩缓冲区、加载的图像或者模型等等。

// Game.h
	SDL_GLContext mContext;

Game::Initialize() 设置 OpenGL 参数,并初始化上下文:

// Game.cpp

	/// 设置 OpenGL 参数
	// core OpenGL
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	// 指定版本 4.2
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	// RGBA
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
	// 双缓冲
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	// 强制使用硬件加速
	SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

	mContext = SDL_GL_CreateContext(mWindow);

OpenGL 支持向后兼容,需要手动查询所需要的扩展,这个过程也很枯燥。为了简化这个过程,通常会使用 OpenGL Extension Wrangler Library(GLEW)。GLEW 可以自动初始化当前 OpenGL 上下文所支持的所有扩展函数。

在 NuGet 中搜索 GLEW 并安装到项目:

GLEW

可以看到有两个下载比较多的 GLEW,从发布日期上看,glew.v140 会比较新,但名称绑定了 v140。这里还是选择了 GLEW

安装完成之后,引入 GLEW 的头文件:

// Game.h
#include <GL/glew.h>

要初始化 GLEW,要在创建上下文之后,添加下面的代码:

	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK)
	{
		SDL_Log("Failed to initialize GLEW.");
		return false;
	}

如果在 v143 下尝试编译,会发现链接失败了,因为依赖包指定了版本

glew 绑定了版本

其实 C++ API 还是相对比较稳定的,我觉得绑定平台反而看起来不是一个很好设计。

glew 链接

直接复制修改

复制了 v110,修改文件夹名为 v143。修改 glew.targets 文件,将 v110 替换为 v143。当然,这种方法比较简单粗暴,不是特别提倡。

NuGet 中,动态运行库 .dll 是单独列出来的,同样拷贝 v110 文件夹作为 v143,修改 glew.redist.targets,将 v110 替换成为 v143

这样就可以运行了。

然而,对于 Debug 版本,由于目前我用的是 V143,并没有 v110 的工具集,会发现运行的时候少了一个 msvcr110d.dll。这个问题比较好解决,直接去 下载 一个对应的 dll,拷贝 Debug 程序的目录下就可以了(不推荐拷到 System 下面)。

这样,无论是 Debug 版本还是 Release 都可以正常运行了。

OpenGL 的依赖

OpenGL 还需要使用到系统自带的 OpenGL32.lib,否则下面代码会出现链接错误。

void Game::GenerateOutput()
{
	// 灰色
	glClearColor(0.86f, 0.86f, 0.86f, 1.0f);
	// 清除颜色缓冲区
	glClear(GL_COLOR_BUFFER_BIT);

	// TODO: 绘制场景

	// 交换缓冲区
	SDL_GL_SwapWindow(mWindow);
}

由于是系统自带,只需要在项目设置中的附加依赖项直接加入 OpenGL32.lib

OpenGL32.lib 依赖项

最终

灰色背景的效果

这就意味着 OpenGL 环境搭建好并正常工作了。

推荐参考这篇继续开发 OpenGL:Xcode与C++之游戏开发:OpenGL

小结

NuGet 的确省去了很多繁琐的过程,但很明显,很多包的更新赶不上 Visual Studio 的工具集,而 NuGet 大概是为了可重入才绑定了对应的工具集,导致有时候无法找到对应版本的库。NuGet 显然并不完美,无法做到全自动,但相对于传统的方式,还是大大简化了。不过,这种方式对于源码版本的控制显然会更难,推崇源码构建的开发者自然不会选择用这种方式。自主可控和方便快捷之间永远是需要权衡的。对于初学者,显然使用 NuGet 搭建环境还是比较方便的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/98290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Nodejs计算机毕业设计基于响应式交友网站Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

蚁巢相遇问题

一 问题描述 有 N 个蚁巢&#xff0c;编号为 1&#xff5e;N 。第 i 个蚁巢的位置是(xi , yi)&#xff0c;没有两个蚁巢在同一位置。所有蚂蚁都遵守一些规律&#xff1a; ① 当一只蚂蚁在蚁巣 p 时&#xff0c;它总是移动到离 p 最近的另一个蚁巣&#xff0c;若有多个蚁巣与 …

计算机毕设Python+Vue心理健康网站(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[leetcode 739] 每日温度

题目链接&#xff1a;https://leetcode.cn/problems/daily-temperatures/ 第一个想法是简单两个 for 循环&#xff0c;但是可能会超时&#xff08;其实用C不会超时&#xff09;。 因为最近在做栈的题目&#xff0c;所以想到了最小栈&#xff08;原来叫作最小栈啊~&#xff09;…

Rust 从入门到放弃,再入门到贡献 nacos-sdk-rust

Rust 从入门到放弃&#xff0c;再入门到贡献 nacos-sdk-rust Rust 上手难度大&#xff1f;我想是的。从文章标题便可知一二&#xff0c;小编水平有限经历了多次入门&#xff0c;得来的经验之谈。本文不涉及详细的技术剖析&#xff0c;仅表达入门的心路历程&#xff0c;供客官参…

Centos7配置nfs

NFS NFS 就是 Network FileSystem ,此系统可以让不同操作系统、不同主机通过网络彼此分享文件&#xff0c;可以将其视为一个文件服务器。使用NFS可以将远程NFS服务器的分享目录挂载到本地主机上&#xff0c;本地主机访问共享目录就是访问远程的NFS服务器。本地主机被称为客户端…

Nacos 简介与 本地调试环境搭建

目录 1、简介 2、Nacos架构 3、本地调试环境搭建 3.1 源码下载 3.3 单机启动 Nacos 3.4 集群方式启动&#xff1a;基于文件方式 4、Nacos源码模块介绍 5. 约定说明 1、简介 Nacos是Dynamic Naming and Configuration Service的首字母简称 Nacos由阿里巴巴开源&#x…

PyTorch入门

开发环境 ANACONDA 官网&#xff1a;Anaconda | The World’s Most Popular Data Science Platform cmd窗口验证安装成功 CUDA 官网&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 选择匹配pytorch的版本下载安装 命令窗口验证安装成功 PyTorch 官网&#xff1a;…

【JavaSE】泛型

目录 一、泛型概念 二、泛型的语法 1、语法 2、实例化 4、泛型如何编译 5、泛型的上界 6、泛型方法 三、通配符 1、使用场景 2、使用 3、通配符的上下界 一、泛型概念 泛型就是适用于许多许多类型&#xff0c;是在jdk1.5引入的 二、泛型的语法 1、语法 class 类名&l…

Apache Hudi Table Query Types

目录 Table Types​ Query types​​​​​​​ Copy On Write Table Merge On Read ​​​​​​​Table & Query Types | Apache Hudi Hudi表类型定义了如何在DFS上对数据进行索引和布局&#xff0c;以及如何在这样的组织之上实现上述原语和时间线活动&#…

区块链入门的几个基本问题

目录前言比特币区块链区块链大揭秘抛砖引玉故事一故事二总结引人入胜侃侃而谈去中心化开放性不可篡改性相关技术共识机制共识机制的两大核心达成共识的主要过程&#xff08;产生新区块的过程&#xff09;工作量如何理解&#xff1f;Hash计算Bits和目标Hash值Merkle Root双花问题…

新手python学什么最吃香?

前言 今天跟大家聊聊Python的几个主要发展和就业方向&#xff0c;给准备学习Python的小伙伴解惑。 “ 我想学Python&#xff0c;但是学完Python后都能干啥&#xff1f;” “ 现在学Python&#xff0c;哪个方向最简单&#xff1f;哪个方向最吃香&#xff1f;” “ …… ” …

LeetCode题解 二叉树(五):226 翻转二叉树;101 对称二叉树;100 相同的树;572 另一个树的子树

226 翻转二叉树 easy 这道题有一段广为人知的传说&#xff1a;曾有人说Homebrew&#xff08;适用于macOS和Linux的开源软件包管理器&#xff09;的作者Max Howell&#xff0c;没有在白板上写出这道题目&#xff0c;被Google拒绝了。 至于是不是真的因为没做出来这道题就被拒绝…

深入浅出JVM之执行引擎的解释执行与编译执行

本篇文章围绕执行引擎&#xff0c;深入浅出的解析执行引擎中解释器与编译器的解释执行和编译执行、执行引擎的执行方式、逃逸分析带来的栈上分配、锁消除、标量替换等优化以及即时编译器编译对热点代码的探测 执行引擎 hotspot执行引擎结构图 执行引擎分为解释器、JIT即时编译…

大数据框架Hadoop篇之Hadoop入门

1. 写在前面 今天开始&#xff0c;想开启大数据框架学习的一个新系列&#xff0c;之前在学校的时候就会大数据相关技术很是好奇&#xff0c;但苦于没有实践场景&#xff0c;对这些东西并没有什么体会&#xff0c;到公司之后&#xff0c;我越发觉得大数据的相关知识很重要&…

Jmeter(二十二):硬件性能监控指标

硬件性能监控指标 一、性能监控初步介绍 性能测试的主要目标 1.在当前的服务器配置情况&#xff0c;最大的用户数 2.平均响应时间ART&#xff0c;找出时间较长的业务 3.每秒事务数TPS&#xff0c;服务器的处理能力 性能测试涉及的内容 1.客户端性能测试&#xff1a;web前…

洛谷——【入门2】分支结构

文章目录题单简介【深基1-2】小学数学 N 合一题目描述问题 1问题 2问题 3问题 4问题 5问题 6问题 7问题 8问题 9问题 10问题 11问题 12问题 13问题 14输入格式输出格式样例 #1样例输入 #1样例输出 #1提示AC代码【深基2.习6】Apples Prologue / 苹果和虫子题目描述输入格式输出格…

尝鲜:SpreadJS-en已出 16.0 SpreadJS-cn 16.0-23年1月出

此次版本更新将带来众多的增强功能&#xff0c;而其中新的文件结构尤为重要&#xff0c;是近几个版本中最重要的架构级更新&#xff01; 其设计目标是 *减少 SSJSON 的体积&#xff0c;平均减小到原来 30% *提供按需加载&#xff08;Lazyload&#xff09;能力&#xff0c;相对…

【学习】https://gitee.com/DingJiaxiong

【学习】https://gitee.com/DingJiaxiong 文章目录【学习】<https://gitee.com/DingJiaxiong>0 前言1 Java SE2 Java Web3 Maven基础4 Git5 SSM框架6 MybatisPlus7 SpringBoot0 前言 事情是这样&#xff0c;我准备把之前所有的笔记都放到Gitee 上了 不用GitHub … 就别问…

Spring的AOP切面应用对【后台对接口增强】

目录&#x1f4da;简介&#xff1a;&#x1f4a8;切面表达式&#xff1a;&#x1f4ad;切面通知类型&#xff1a;&#x1f5fa;️创建项目演示&#xff1a;&#x1f3a2;创建项目&#xff1a;&#x1f383;添加依赖&#xff1a;&#x1f4a8;编写切面类&#xff1a;&#x1f68…