2

关于编程,我注意到的一件事是,每当有一种方法可以绘制单个像素或从单个像素获取数据时,它总是比绘制基元或预制图形的方法慢得多。我只是想知道为什么会这样。制作这些方法是否不需要(在某些时候)使用单像素绘图方法?如果有更快的方法来做到这一点,他们为什么不让单像素方法也这样做呢?

4

2 回答 2

0

一些想法:

  1. 许多现代计算环境包括用于绘制图形基元的硬件加速。图形加速硬件不是让 CPU 一次访问一个像素的视频内存,而是一次接触相当于多个像素的视频内存。绘图图元可以以软件像素操作无法利用的方式利用这种加速。 http://en.wikipedia.org/wiki/Hardware_acceleration有一些有用的指示。

  2. 即使是在软件中运行的绘图原语也经过了高度优化,通常采用高级语言无法(轻松)访问的方式。例如,现代 CPU 中的SIMD 指令允许同时触摸多个像素位置。

  3. 最后,与编译语言相比,解释语言可能会引入显着的像素到像素延迟。这取决于您最常尝试的编程语言。

于 2013-05-02T02:46:53.483 回答
0

GetPixel/SetPixel 操作中存在开销,通常可以在绘制触及许多相邻像素的图元时进行优化。

考虑必须如何实现 GetPixel 和 SetPixel:

  1. 确定每个坐标是否在范围内。
  2. 计算该像素在内存中的位置。
  3. 根据像素格式,隔离该像素的数据可能涉及拆包。

现在考虑类似轴对齐的矩形图元。实现它的简单方法是对 x 和 y 进行双循环并调用 SetPixel:

void DrawRect(RGB color, int left, int top, int right, int bottom) {
  for (int y = top; y < bottom; ++y) {
    for (int x = left; x < right; ++x) {
      SetPixel(x, y, color);
    }
  }
}

SetPixel 将检查每个调用的两个坐标是否都在边界内,这是一种浪费。如果 y 坐标对同一行中的前一个像素有效,那么它对下一个像素仍然有效。

address = base + (y * stride) + x此外,在大多数光栅格式中,您设置的大部分像素在内存中都是相邻的,因此通用公式(甚至像

这说明了与使用 SetPixel 的简单实现相比,可以使用更少的边界检查和计算来绘制多少(大多数?)图元。原始绘图操作往往会被优化,因为它们非常常见。

在现代机器上,优化的机会更多。一些图元实际上可能是由 GPU 而不是 CPU 绘制的。这很重要,因为 GPU 可以直接访问视频内存。CPU 通常可以间接访问视频内存,并且像素访问必须在图形总线上来回穿梭。一些图形总线非常快,但通常不如访问本地内存快。通过总线向 GPU 发送一个只有几个字节的绘制图元命令将比发送许多设置像素命令快得多。

此外,GPU 旨在并行执行此类工作。它们通常有许多可以同时工作的简单内核。因此,如果它正在绘制一个矩形,GPU 可能(例如)将每个扫描线分配到一个单独的核心,并且整个矩形的绘制速度将与单个核心可以绘制一条水平线一样快。

于 2013-05-02T13:18:06.123 回答