如何制作图形/绘图方法?

时间:2013-05-01 20:41:14

标签: graphics drawing

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

2 个答案:

答案 0 :(得分:0)

一些想法:

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

  2. 即使是在软件中运行的绘图基元也经过高度优化,通常采用不易从高级语言访问的方式。例如,现代CPU中的SIMD instructions允许一次触摸多个像素位置。

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

答案 1 :(得分:0)

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

考虑如何实施GetPixel和SetPixel:

  1. 确定每个坐标是否在边界内。
  2. 计算该像素在内存中的位置。
  3. 根据像素格式,隔离该像素的数据可能涉及拆包。
  4. 现在考虑像轴对齐的矩形基元。实现它的简单方法是在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发送单个draw-primitive命令(只有几个字节)将比发送许多设置像素命令快得多。

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

相关问题