在片段着色器

时间:2018-06-11 20:34:39

标签: opengl shader vulkan

我正在创建一个NES模拟器,我正在试验将功能(如果适用)卸载到GPU的想法。令我印象深刻的一个想法是以自定义格式将屏幕像素输出到缓冲区,其方式是对每个像素的属性进行编码,以便着色器可以确定如何显示它们。这将从模拟器中最热门的功能之一卸载相当多的逻辑/分支。

以下是使用每个像素2个字节对​​单个像素进行编码的示例:

字节1(调色板索引)bbbb ssss

  • b:背景像素调色板索引
  • s:精灵像素调色板索引

字节2(像素属性)bbss rgbp

  • b:2位背景像素值
  • s:2位精灵像素值
  • r:强调红色
  • g:强调绿色
  • b:强调蓝色
  • p:精灵像素优先级

我对编写着色器比较新,所以我的第一个问题是:这甚至可能吗?在我已经完成的研究中,似乎纹理需要采用特定格式才能从每个像素读取颜色信息,以及我自定义的2字节"颜色"格式甚至不代表其自身的颜色。如果可能的话,可以采取什么样的高级方法来实现这一目标?我计划使用vulkan,但任何更普遍适用的方法(与着色器有关)都是受欢迎的。

1 个答案:

答案 0 :(得分:5)

图形自2000年以来发生了变化。着色器(大多数)是计算值的任意程序。这些值有时可能被解释为颜色是无关紧要的。着色器是程序;他们做你想要的。

同样,除非着色器选择将它们解释为颜色,否则纹理不包含颜色。纹理只不过是值的查找表。同样,这些值可能是颜色,但它们可能不是。这完全取决于着色器如何使用这些值。

您可以创建使用整数格式的纹理(与标准化整数相对)。然后,您可以在着色器中执行任何您喜欢的位操作。上面描述的任何内容对于着色器来说都不是特别困难。

在您的情况下,纹理可能是2通道格式,每通道8位,使用无符号整数值。在OpenGL中,此格式拼写为GL_RG8UI:红色/绿色(两个通道的名称),每个通道8位,以及无符号整数值。 OpenGL可以将这些频道称为“红色”和“绿色”,但重要的是你的着色器对它们的作用,而不是它们所谓的。

在Vulkan中,此格式拼写为VK_FORMAT_R8G8_UINT:两个无符号整数值的8位通道。

您将要遇到的主要问题不是图像格式或着色器。它以高效的方式将数据传输到GPU。

在OpenGL中,您别无选择,只能不断地将CPU数据从CPU可访问的内存DMA转换为GPU可访问的纹理。在Vulkan中,您可能不必这样做。

Vulkan实现可以说线性纹理可以存储在CPU GPU可访问的内存中。他们不需要提供这个,但许多人可以这样做。在这样的实现中,不需要DMA; GPU可以直接读取CPU写的内容。你仍然需要对这些图像进行双重缓冲(以最小化GPU / CPU同步。你在GPU读取前一帧的数据时写入一个),但这应该提高DMA版本的性能。

当然,对于无法实现的实现,您仍然需要一个代码路径。