我一直在学习OpenGL,当我坐下来尝试编写我的VBO、PBO、VAO、纹理、四边形、绑定、片段着色器、顶点着色器和其他一整套经过几十年发展的抽象的现代抽象时,我在想:显示器不就是一个很大的内存块吗?
我听说过这样的故事,在“好日子”(比如Commodore 64)中,你所要做的就是给内存中的任意一个字节赋值,屏幕就会改变一个像素。非常简单和优雅。在现代,这种情况已经随着一层又一层的抽象和保障而改变,比如改变显示器上的一个像素需要几百英尺的距离。
这就引出了一个问题,在现代社会,仅仅“更新屏幕的一个像素”是可能的吗?是否有可能编写我自己的图形驱动程序或其他东西,在那里我可以发送命令到一些与GPU接口的C包装器来更改这些像素?这是一个非常广泛的问题,但我很好奇。我正在寻找的这个问题的答案将提供一个粗略的轮廓,你必须能够做什么,以便能够任意地让一些C代码在屏幕上设置一个像素,以及为什么OpenGL取得了今天的进展-VBO,PBO,VAO,绑定,着色器等解决了什么问题,以及我们是如何走到今天的位置的。
发布于 2020-05-19 20:48:21
您可以创建自己的帧缓冲区--这只是一个整数数组--并对其进行光栅化,然后使用例如Windows GDI函数SetBitmapBits()
将其一次性绘制到显示器上。最终的绘图到显示命令取决于操作系统。
如何在帧缓冲区上进行光栅化完全由您决定。您可以使用CPU来绘制单独的像素或光栅化线条和三角形,例如,请参阅我的使用Windows GDI的旧CPU图形引擎的演示:https://youtu.be/GFzisvhtRS4。只要不栅格化大型数据集,使用CPU就可以。根据我的经验,在CPU上实时60fps渲染的限制是每帧约50k行。
如果你想栅格化非常大的数据集,你必须以某种方式使用GPU。由于帧缓冲区只是一个整数数组,您可以使用OpenCL或CUDA将其传输到GPU或从GPU传输它,并且在GPU上-如果您的数据集恰好已经在视频内存中-并行地执行所有光栅化。为此,您将需要一个额外的z缓冲区来决定哪些像素要通过遮挡几何图形进行透绘。通过这种方式,您可以以60fps的速度栅格化大约每帧3000万行。此演示使用OpenCL:https://youtu.be/lDsz2maaZEo在图形处理器上实时呈现
发布于 2020-05-14 19:26:19
在现代有可能只“更新屏幕的一个像素”吗?
是。例如,在Windows中,您可以使用SetPixel()
绘制像素,也可以使用BitBlt()
批量绘制。请参阅this Q/A
这可以很好地工作,但这意味着你正在使用CPU进行渲染,你会发现GPU对这项任务更有效,特别是当你需要像样的帧率和非平凡的图形时。之所以有这些“一整套基于抽象的其他现代抽象”是为了充当GPU的接口,因为它有一组独立的内存和完全不同的执行模型。其他GPU库(OpenCL、DirectX、Vulkan等)都有相同类型的抽象。
我已经忽略了许多细微差别,但我希望大家都能理解这一点。
发布于 2020-05-14 19:35:15
不就是一个很大的内存块吗?
是的,它被称为帧缓冲区。
我听说过这样的故事:在“美好时光”(good of‘days)中(比如Commodore 64)
当你打开电源时,你现在的电脑就是这样工作的!如果使用CPU写入视频内存,则称为软件渲染器。
在现代,这种情况已经随着一层又一层的抽象和安全措施而改变,比如改变显示器上的一个像素需要几百英尺的距离。
不,它们不是“改变像素”的抽象/保护。如今,不再使用软件渲染器。相反,您必须告诉GPU (这是另一台独立的计算机)如何绘图。这就是API(如OpenGL)为您做的事情。
现在,GPU意味着绘图速度很快,这就需要专门的代码和数据结构。这些都是你提到的东西:VBO,PBO,VAO,着色器,等等(用OpenGL的说法)。这是没有办法的,因为GPU是不同的硬件。
在现代有可能只“更新屏幕的一个像素”吗?
是的,但这最终会被GPU以某种方式绘制出来,即使它看起来像是内存写入。
是否有可能编写我自己的图形驱动程序或其他东西,在那里我可以发送命令到一些C包装器,它与图形处理器接口,以改变这些像素?
是的,但那个"C包装器“就是图形驱动程序。现代GPU的图形驱动程序非常复杂。
为了能够任意获得一些C代码来在屏幕上设置像素而必须做的事情
您不能编写"C程序“来写入图形屏幕,因为C标准本身并不关心图形显示。
所以这取决于你的操作系统,你的硬件,你是否想要2D或3D加速支持,你选择的API…
以及为什么OpenGL取得今天的进展的大致轮廓-VBO、PBO、VAO、绑定、着色器等解决了什么问题,以及我们是如何走到今天的位置的。
请参见上面的。
https://stackoverflow.com/questions/61805409
复制