VS2022版 如何从零开始建一个游戏引擎之二-初步认识OpenGL

OpenGL是什么?

OpenGL主要被认为是一种API(一种应用程序编程接口)规范,它为我们提供了一系列可以用来操作图形和图像的功能。然而,OpenGL本身并不是一个API,而只是一个由Khronos集团开发和维护的规范。

OpenGL图标,太熟悉了,以后你会更加熟悉

OpenGL规范确切地指定了每个函数的结果/输出应该是什么以及它应该如何执行。然后,实现此规范的开发人员可以提出此函数应该如何操作的解决方案。由于OpenGL规范没有给我们提供实现细节,因此允许实际开发的OpenGL版本具有不同的实现,只要它们的结果符合规范(因此对用户来说是相同的)。

开发实际OpenGL库的人通常是图形卡制造商。您购买的每张图形卡都支持特定版本的OpenGL,这些版本是专门为该卡(系列)开发的OpenGL版本。在使用苹果系统时,OpenGL库由苹果自己维护,在Linux下,存在图形供应商版本和业余爱好者对这些库的改编组合。这也意味着,每当OpenGL显示出不应该出现的奇怪行为时,这很可能是图形卡制造商(或开发/维护库的人)的错。

由于大多数实现都是由图形卡制造商构建的,因此每当实现中出现错误时,通常都会通过更新视频卡驱动程序来解决;这些驱动程序包括您的卡支持的最新版本的OpenGL。这就是为什么总是建议偶尔更新图形驱动程序的原因之一。

Khronos公开托管所有OpenGL版本的所有规范文档。感兴趣的读者可以在这里找到3.3版

(这是我们将要使用的),如果你想深入了解OpenGL的细节,这是一本好书(注意它们大多只是描述结果而不是实现)。这些规范也为找到其功能的确切工作原理提供了很好的参考。

下面,我们需要介绍一下OpenGL的一些特点,这些特点的提前介绍将有助于您在开发自己的游戏引擎过程中,节省时间与精力。出于阅读的考虑,以及便于大家参考英文材料,在文中第一次出现中文概念的时候,都将给出英文对应的概念。

核心配置文件与即时模式(Core-profile vs Immediate mode)

在过去,使用OpenGL意味着以即时模式(通常称为固定功能管道)进行开发,这是一种易于使用的绘图方法。OpenGL的大部分功能都隐藏在库中,开发人员对OpenGL的计算方式没有太多控制权。开发人员最终渴望更大的灵活性,随着时间的推移,规范也变得更加灵活;开发人员对他们的图形有了更多的控制权。即时模式确实易于使用和理解,但它的效率也非常低。出于这个原因,该规范从3.2版本开始弃用即时模式功能,并开始激励开发人员在OpenGL的核心配置文件模式下进行开发,这是OpenGL规范的一个部分,删除了所有旧的弃用功能。

当使用OpenGL的核心配置文件时,OpenGL迫使我们使用现代实践。每当我们尝试使用OpenGL的一个弃用函数时,OpenGL都会引发错误并停止绘图。学习现代方法的优点是它非常灵活和高效。然而,它也更难学习。即时模式从OpenGL执行的实际操作中抽象了很多,虽然很容易学习,但很难掌握OpenGL的实际操作方式。现代方法要求开发人员真正理解OpenGL和图形编程,虽然有点困难,但它允许更大的灵活性、更高的效率,最重要的是:更好地理解图形编程。
这也是这里以OpenGL 3.3版为核心配置文件的原因。虽然更难,但非常值得努力。

截至今天,OpenGL的更高版本可供选择(现在已经到了4.6了),你可能会问:为什么在OpenGL 4.6已经发布的情况下,我还想学习OpenGL 3.3?这个问题的答案相对简单。从3.3开始的OpenGL的所有未来版本都在不改变OpenGL核心机制的情况下为OpenGL添加了额外的有用功能;新版本只是引入了更高效或更有用的方法来完成相同的任务。其结果是,所有概念和技术在现代OpenGL版本中保持不变,因此学习OpenGL 3.3是完全有效的。只要你准备好了和/或更有经验,你就可以很容易地使用最新OpenGL版本的特定功能。

当使用最新版本的OpenGL的功能时,只有最先进的图形卡才能运行您的应用程序。这通常就是为什么大多数开发人员通常针对较低版本的OpenGL,并可选地启用较高版本的功能。

扩展性

OpenGL的一大特点是它对扩展的支持。每当图形公司提出一种新技术或新的大规模渲染优化时,通常都会在驱动程序中实现的扩展中找到。如果应用程序运行的硬件支持这样的扩展,则开发人员可以使用扩展提供的功能来实现更高级或更高效的图形。这样,图形开发人员仍然可以使用这些新的渲染技术,而无需等待OpenGL在其未来版本中包含该功能,只需检查图形卡是否支持该扩展即可。通常,当一个扩展很受欢迎或非常有用时,它最终会成为未来OpenGL版本的一部分。
开发人员在使用这些扩展之前必须查询是否有任何扩展可用(或使用OpenGL扩展库)。这允许开发人员根据扩展是否可用来做得更好或更高效:

if(GL_ARB_extension_name)
{
    // Do cool new and modern stuff supported by hardware
}
else
{
    // Extension not supported: do it the old way
}

对于OpenGL 3.3版本,我们很少需要对大多数技术进行扩展,但只要有必要,就会提供适当的说明。

如何确定本机显卡OpenGL的版本

确定版本的方法有多种,这里介绍一个最简单的方式,那就是采用GLview,链接在此处:https://www.realtech-vr.com/home/?page_id=1402

我的GPU配置,好低啊,有没有???

此处,本人的OpenGL版本就是OpenGL4.6,显卡为RTX 3050.

当然,这里还有很多别的方法,但是我们的第一要务是要把事情做完,所以别的炫技方法这里就不提了。

状态机(State Machine)

OpenGL本身就是一个大型状态机:一组定义OpenGL当前操作方式的变量。OpenGL的状态通常被称为OpenGL上下文。使用OpenGL时,我们经常通过设置一些选项、操纵一些缓冲区,然后使用当前上下文进行渲染来更改其状态。
例如,每当我们告诉OpenGL我们现在想绘制线条而不是三角形时,我们都会通过更改一些设置OpenGL绘制方式的上下文变量来更改OpenGL的状态。一旦我们通过告诉OpenGL应该绘制线条来更改上下文,接下来的绘图命令现在将绘制线条而不是三角形。
在OpenGL中工作时,我们会遇到几个更改上下文的状态更改函数,以及几个使用基于OpenGL当前状态执行某些操作的状态函数。只要你记住OpenGL基本上是一个大型状态机,它的大部分功能就会更有意义。

对象(Objects)

OpenGL库是用C编写的,允许用其他语言进行许多派生,但在其核心中,它仍然是一个C库。由于许多C语言构造不能很好地翻译成其他高级语言,OpenGL的开发考虑了几个抽象概念。其中一个抽象是OpenGL中的对象。
OpenGL中的对象是表示OpenGL状态子集的选项集合。例如,我们可以有一个对象来表示绘图窗口的设置;然后我们可以设置它的大小、支持多少种颜色等等。人们可以将对象可视化为类C结构:

struct object_name {
    float  option1;
    int    option2;
    char[] name;
};

每当我们想使用对象时,它通常看起来像这样(OpenGL的上下文被可视化为一个大型结构):

// The State of OpenGL
struct OpenGL_Context {
  	...
  	object_name* object_Window_Target;
  	...  	
};
// create object
unsigned int objectId = 0;
glGenObject(1, &objectId);
// bind/assign object to context
glBindObject(GL_WINDOW_TARGET, objectId);
// set options of object currently bound to GL_WINDOW_TARGET
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH,  800);
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
// set context target back to default
glBindObject(GL_WINDOW_TARGET, 0);

这段小代码是您在使用OpenGL时经常看到的工作流。我们首先创建一个对象并将其引用存储为id(真实对象的数据存储在幕后)。然后,我们将对象(使用其id)绑定到上下文的目标位置(示例窗口对象目标的位置定义为GL_window_target)。接下来,我们设置窗口选项,最后通过将窗口目标的当前对象id设置为0来解除对象绑定。我们设置的选项存储在objectId引用的对象中,并在将对象绑定回GL_WINDOW_TARGET后立即恢复。

到目前为止提供的代码示例只是OpenGL操作方式的大概。在之后的学习过程中,我们会不断的梳理整个过程。

使用这些对象的好处是,我们可以在应用程序中定义多个对象,设置它们的选项,每当我们开始使用OpenGL状态的操作时,我们都会将对象与首选设置绑定。例如,有些对象充当3D模型数据(房子或角色)的容器对象,每当我们想绘制其中一个对象时,我们都会绑定包含要绘制的模型数据的对象(我们首先为这些对象创建并设置选项)。拥有多个对象允许我们指定许多模型,每当我们想绘制特定模型时,我们只需在绘制之前绑定相应的对象,而无需再次设置它们的所有选项。

好了我们已经初步认识了OpenGL,上节课我们也已经介绍了如何在VS2022中配置glfw以及glad库,下面,我们就要开始介绍,如何用一段段代码,让GPU做出我们希望看到的图像了。

创作不易,希望大家多多支持,老夫也会笔耕不辍的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金沙阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值