与软件渲染相比,OpenGL,SFML和SDL有什么优势?


24

我开始观看Handmade Hero系列视频,其中Casey Muratori在不使用框架等的情况下创建了一个游戏引擎。昨天我到了那儿,他展示了如何在屏幕上绘制图像。据我了解,他只是分配了一些内存,该内存与他要绘制的屏幕大小一样大。然后,他创建了一个位图,然后将其传递到分配的缓冲存储器中,并使用特定于操作系统的功能将其绘制到屏幕上。

这似乎很简单。我曾经使用GameMaker,后来改为Love2D,并与Sprite Kit一起工作了一些,但我一直想知道在有时令人困惑的图层下到底发生了什么。

既然如此,为什么当您只需要分配一些缓冲区,传递位图并将其绘制到屏幕上时,为什么还要使用图形库(OpenGL,SFML,SDL等)呢?

如果要在屏幕上绘制不同的内容,只需将它们写入位图,然后将其传递到缓冲区中。我对编程很陌生,但这对我来说似乎很简单。如果我错了,请纠正我。


11
在其系列的稍后部分(大约第220集),他将使用opengl。他这样做的原因是速度。
棘轮怪胎

5
诀窍是确定在屏幕上绘制什么。首先需要完成所有GPU纹理/阴影,三角形,相机投影等操作,以确定每个像素应为哪种颜色。将像素颜色推送到屏幕是容易的部分。
user14146

2
根据记录,SDL和OpenGL并不互斥。SDL是一个“硬件抽象层”,它不仅可以处理图形库,还可以处理窗口,事件和输入。SDL还具有与OpenGL结合使用的支持,因此SDL可以在OpenGL处理​​图形时执行所有非图形的工作。另请注意,大多数情况下OpenGL可直接与GPU配合使用,而SDL可能会或可能不会取决于所编译的版本和系统。
法拉普

SFML使用OpenGL进行渲染,因此SFML实际上所做的就是为使用OpenGL提供更简单的界面。
Cornstalks

2
Techcnailyl Casey的工作仍在使用图形库。该库称为GDI,尽管它是操作系统主要API的一部分,但从技术上来说,它仍然是图形库。
法拉普

Answers:


41

这不仅与执行速度有关,还与简单性有关。尽管此示例中使用的软件渲染比使用硬件加速(即GPU)要慢得多,但是在屏幕上绘制一些位图却是一件微不足道的任务,您不会注意到性能下降。

但是,诸如三角形栅格化,深度排序之类的底层活动是众所周知的概念,GPU可以使用一些命令隐式处理这些活动。在软件模式下重新实现这些功能实质上就是在重新发明轮子。如果您想对渲染的方式有一个低级的了解,那很好,我自己编写了3D软件渲染器只是为了对其进行一些探索,但是在大多数情况下,OpenGL可以更快地完成渲染就浪费了时间。盒子。

您提供的示例听起来非常基础,只需在屏幕上绘制单个图像即可,因此实现起来很容易。但是,一旦开始对复杂性进行分层,您会发现,正确呈现所有内容变得越来越复杂。在3D软件渲染的Quake时代,人们不得不做的事情是疯狂的,尽管我很高兴您还没有走那么远。


12
OpenGL知道点,线和三角形等术语。大多数时候,您将使用三角形。要学习如何使用OpenGL,我可以推荐opengl-tutorial.org。要了解OpenGL的功能,请查看官方Wiki:opengl.org/wiki/Rendering_Pipeline_Overview
tkausl

1
我本来打算+1,但我不喜欢“重新发明轮子”,因为我觉得它在计算历史上给人以错误的印象。位图渲染是第一位的,因此OpenGL是“重新发明轮子”的工具。他们这样做有两个很好的理由:1)标准化和2)GPU加速。如果新版本有所改进,重塑车轮并不总是一件坏事(例如,带轮胎的车轮与木制货车车轮)。这里的关键点不应该是软件渲染正在彻底改变方向,而应该是它不如GPU渲染。
法拉普

4
@Pharap除外,现在,编写软件渲染器绝对是在重新发明轮子,而不管它是否在历史上。
porglezomp '16

1
这只是答案的一半。下一个答案是另一半,但是完整的答案(包括对OpenGL与他提到的其他事物之间的区别的一些解释)将是该问题的正确答案。
贾斯珀(Jasper)

1
@ user148013“ opengl知道点,线,三角形等术语吗?” 现代OpenGL 处理这些原语。除了它们,您不能光栅化任何东西。
Nax'vi-vim-nvim'16年

25

我的问题是:为什么当您要做的只是分配一些缓冲区,传递位图并将其绘制到屏幕上时,为什么还要使用诸如open gl,sfml,sdl之类的东西呢?

短:因为它的速度快(OpenGL,DirectX)。

长:

您可能认为自己可以自己做。在屏幕上绘制像素。您可能会编写一个小型库来绘制形状,例如方形或三角形。当然可以。有很多库可以做到这一点。其中一些甚至实现了OpenGL规范(因此就像opengl的软件端一样),可以完全执行Casey Muratori的工作。他们在软件侧计算所有内容,在软件侧设置像素,然后将结果写入屏幕。

但是,这很。在这种情况下,并未设计出最终将执行所有这些操作的CPU。那就是GPU的用途。OpenGL的工作(当然,除非是软件实现)是将您告诉它的所有事情都做,然后将所有数据,所有绘图调用,几乎所有内容推送到图形卡,并告诉GPU进行工作。GPU专为此类工作而制作。乘以浮点数(这就是绘制3D场景时要做的事情)并执行着色器。这与此并行。只是为了让您了解GPU的速度,请考虑一个3D全屏1920x1080像素的简单场景。这些像素相乘后得出2,073,600像素。对于每一个像素,GPU将至少运行一次片段着色器,大多数情况下会多次运行。现在,可以说我们以每秒60帧的速度运行。这意味着,GPU每秒运行片段着色器2,073,600 * 60 = 124,416,000次。您认为您可以在CPU上执行类似的操作吗?(这是一个非常简单的解释,还有很多事情要考虑,例如被较近的物体覆盖了多少像素,使用了多少MSAA等,但是每秒124,416,000次可能是您可以获得的最低值,您在一个简单的场景中很容易超过60fps)

那就是OpenGL和Direct3D的功能,有关引擎的功能,请参见@Uri Popovs的答案。


8
他正在创建2D游戏,这是3D的另一个主题。而且,当我说时,并不一定意味着它的速度低于60 fps,而是意味着图形卡将在CPU所需时间的一小部分内完成相同的工作,至少在3D空间方面。
tkausl

4
GPU之所以更好,是因为它们被设置为并行化着色器调用。
棘轮怪胎

4
@ user148013根据我从这个人那里看到的内容,我会说他与“非常明智”完全相反。
Bartek Banachewicz '16

4
不仅仅是渲染速度较慢(Casey的软件渲染器出奇地快)。保持从普通RAM到视频RAM的数据量也很大。根据总线的类型,将巨大的位图推送到视频卡可能会占用大量的帧时间。使用GPU时,您有时会推送纹理,然后将其用于逐帧。
阿德里安·麦卡锡

2
@ user148013浮华和良好的编程之间是有区别的。它们可以重叠,但经常会发生冲突。我会说“我可以在软件中渲染(就像MESA可以...一样)”在浮华之下,而且肯定不是很好

11

他所做的称为软件渲染,而OpenGL所做的称为GPU渲染

它们之间有什么区别?速度和内存。

栅格化(在屏幕上填写三角形)需要一些时间。如果您在CPU上执行此操作,则实际上会浪费时间来避免游戏逻辑,尤其是在优化不佳的情况下。

而且,不管图像有多小,他都需要为其分配一定数量的内存。GPU为此具有视频存储器。


OS X上也可以进行软件渲染吗?因为看起来与图形有关的所有事情现在都是由OpenGl完成的。
user148013 '16

2
@ user148013您有一些误会。OpenGL是一种多平台API,因此它可以在OS X上运行,实际上,它可以在带有“现代”(2000年后)GPU的所有设备上运行。Metal是仅适用于Apple设备的单独API。软件渲染也是与它们两者分开的事情,是的,它也可以在OS X上完成。基本上,这只是使用CPU在屏幕上手动设置像素。
Bálint)

这正是我问的原因,因为据我所知,无法在OS X上完成软件渲染。Cocoa接触到了OpenGl,Quarz使用OpenGl,Core Framework使用OpenGl。他们现在都更快地使用Metal。但是我还没有找到一个不使用GPU(OpenGl,Metal)在屏幕上绘制缓冲区的函数。
user148013 '16

1
@ user148013,因为它不仅特定于操作系统,也不特定于实现。假设您要在Java中实现它,因为这是多平台开发的一个著名选择。使用java,您可以先创建一个窗口(JFrame),然后在图像上进行绘制,然后再将此图像放在框架上,而不是直接在其上进行绘制,以完成此操作。但是,它将不知道术语“三角形”或“线”。只有颜色。您需要自己使用光栅化算法来实现。这就是为什么我们更喜欢OpenGL的原因,它速度更快,并且使用起来更简单。它基本上是一个栅格化API。
巴林特

2
@ user148013为什么不呢?如果他们可以打开一个窗口,并且可以在没有API的情况下在其上绘制1张图像,那么他们可以。
巴林特

8

尽管来自他人的答案比我给出的任何答案都更正确,但我想指出关于软件开发如何工作的根本误解,我认为这是您提出问题的基础。尽管总是可以在没有框架的情况下“自己做”事情,并且这样做通常会带来很大的教育收益,但事实是,这不是现代软件的创建方式。

有人创建了在其上运行的硬件和机器语言。其他人会创建高级语言以及编译器,驱动程序和操作系统,图形库等等。我们每个人都以我们前任的工作为基础。这不仅是“好”,而且是一项要求。

您正在工具链中的任意点画出“可接受的”或“不可接受的”线。您可以轻松地说出“为什么在组装中可以做同样的事情时为什么使用C ++?”,或者“为什么在轻松读取其电线上的电压并自己计算时为什么要依靠键盘驱动器呢?” 一天中没有足够的时间,或者一生中没有足够的时间让每个人自己做所有事情。

这不仅适用于软件开发,而且通常适用于现代生活。您是否听说过从头开始自己烤面包机的那个人?http://www.thomasthwaites.com/the-toaster-project/。这花费了很长时间,并且付出了很多努力。对于烤面包机。尝试自行构建以太坊实现视频游戏所需的一切


2
我认为这是一个很好的答案,因为它说明了为什么使用框架是好的,而不会迷惑出于教育目的而重新发明轮子的想法。
法拉普

3

引擎要做的更多,仅仅是在屏幕上绘制图片。他们处理照明,阴影,输入,碰撞检测。甚至只是渲染部分比将缓冲区推入屏幕还要复杂得多。特别是对于3d场景,您需要对比位图复杂得多的数据进行大量计算。让我给您一个汽车的类比:您所描述的简单是汽车的排气。您只需要制造尺寸合适的管道,然后将气体从一端推到另一端即可。但是,这绝不是汽车机械中唯一发生的事情。


3

上面的答案很好,但是没有一个真正的最重要的原因可以解释为什么首选OpenGL之类的东西。主要原因是要利用专门设计专用硬件来处理诸如在屏幕上渲染数百万个像素(GPU)之类的事情。

在使用CPU进行软件渲染的情况下,渲染器将在位图上的所有像素上逐一循环,并发出命令以在屏幕上显示每个像素。因此,如果您要渲染1000x1000尺寸的图像,则该1,000,000循环将使您的CPU通过。毕竟,在设计时要牢记控制。许多if条件,从一组指令跳到另一组指令以及严格的控制流向。但是,GPU的设计知识是它将在屏幕上的像素上进行很多类似的循环。一个GPU会进行一次具有1000000次迭代的for循环,然后将工作划分为大量内核,以使每个内核并行工作**,并且彼此独立**。因此,与CPU不同,每当GPU遇到if-else条件时,它将处理两个代码分支到其自身的两个内核,然后,最后,它将查看条件的计算结果并丢弃该条件。不需要分支的结果(这就是为什么GPU着色器中的许多if-else条件不被重视;它们总是造成浪费的原因)。

是的,GPU是围绕并行性构建的。与CPU相比,这使得处理像素更快。


0

请参阅我是否真的需要使用图形API?

当然,您可以要求一个缓冲区,在其中设置一些位,然后将其写入屏幕。基本上,这是在90年代中期3DFX推出图形加速器之前在PC上进行图形编程的唯一方法。即使在Windows中,DirectX也可以直接访问视频内存。

但是在非PC硬件,专用游戏机上,一直存在通过从处理器分担工作来加速图形的技术。甚至Atari 2600都有“硬件精灵”,部分原因是它没有足够的RAM用于帧缓冲区。

后来(80年代中期),游戏机针对平台游戏进行了优化。同样,没有帧缓冲区;相反,程序员可以指定图块网格

Genesis图形硬件由2个可滚动平面组成。每个平面都由瓷砖组成。每个图块是一个8x8像素的正方形,每个像素4位。每个像素因此可以具有16种颜色。每个图块可以使用4个颜色表中的1个,因此在屏幕上可以一次获得64种颜色,但是在任何特定图块中只能获得16种颜色。磁贴需要32个字节。有64K图形内存。如果没有其他用途,那么这将允许2048个唯一图块。


-2

现代的CPU足够快,可以在软件中进行任何2D游戏,因此对于2D图形,OpenGL / DirectX不会提供任何优势,除了会给项目增加其他依赖性和复杂性外,例如设置3D投影矩阵以绘制一堆精灵并将数据上传到GPU。

OpenGL还将迫使您将所有子画面打包在512x512纹理内(旧控制台的人工产物,如PSX,将图形打包到视频内存页面中),这要求您编写相当复杂的子画面打包代码。

另一方面,如果您正在执行3d,使用复杂的阴影渲染数百万个三角形,那么GPU是不可避免的。很久以前,Direct3d只有2d的简单版本,称为DirectDraw,它可以GPU加速子画面绘制,但是现在Microsoft不再支持它,可能是因为CPU足够快,可以在没有任何加速的情况下执行2d,如果您不关心节能的话。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.