3

来自文档:seq set-if-equal destination = source1 == source2 ?1 : 0,按组件

我还没有彻底测试它,但到目前为止,我的片段着色器在两台机器(台式电脑)上都工作,其中 context3D 初始化成功作为 DirectX,但不适用于闪存回退到软件渲染的机器。

seq ft2.x, ft0.x, fc0.x

ft.x在硬件上设置为1,当当前像素红色值,存储在ft0.x等于常量fc0.x时,存储50/255. 所以我想要发生的事情确实发生#32????在硬件上的 (50 == 0x32) 彩色像素上,但不会发生在软件上。

我已经测试了一种解决方法,我可以用seq更复杂的算法替换操作码,包括slt(如果小于则设置)或sge(如果大于或等于则设置)。

因此,问题似乎在于我提供给 GPU 的常数(50/255)和实际红色值(纹理中为 50)的比较。如果它是其他任何东西(例如 RGBA 值有不同的顺序),slt也会sge失败。

我在这里做错了吗?我是否应该以某种方式舍入比较值(例如乘以 255 然后删除小数)以确保它可以在所有设备和模式下工作?

更新: 其中一台具有软件渲染后备功能的机器设置为 16 位图形,但将其更改为 32 位并不能解决问题。我还盲目尝试将颜色值除以 256、128 和 127 而不是 255,希望如果浮点数具有不同的精度(并且更高和更低的数字只要它们等于256px 长渐变内的像素之一),但我的希望没有得到回报。

然后我尝试了将常量存储为整数的解决方法,并在着色器内部将值乘以 255 并删除小数,令我惊讶的是,当它在 GPU 上工作时,它在软件渲染上失败了:

mul ft0.x, ft0.x, fc0.y通过将ft0.x(红色通道)乘以常数255将其转换为整数

frc ft4.x, ft0.x得到一个分数

sub ft0.x, ft0.x, ft4.x删除小数,截断整数

现在进行比较,例如seq ft2.x, ft0.x, fc0.x

add ft0.x, ft0.x, ft4.x添加小数,这一步可能没有必要

div ft0.x, ft0.x, fc0.y将整数值除以 255 以将其转换回浮点数(我的意思是 0..1 范围内的数字)

接下来我要尝试的解决方法是简单地进行一系列小于比较,将临时寄存器设置为 1,将其添加到另一个临时寄存器(计数器),以便通过检查计数器我可以看到值在哪个范围内。

4

1 回答 1

2

这是最终对我有用的解决方法。

我在红色 alpha 通道上有 4 种颜色,它们告诉着色器要做什么。如果红色值为 50,着色器将左像素作为源,如果为 100,它将采用顶部像素,依此类推。所以我所要做的就是用 4 个seq命令为寄存器的 4 个组件设置 0 或 1 个偏移量,以后我可以在寄存器中添加或删除采样器的位置。

因为seq未能将第一次采样的像素的红色值与提供的常量进行比较,所以我制作了一个 set-if-greater-or-equal 操作码的“阶梯”:

"mov ft3.x, fc0.x \n" + //ft3 = 49/0xFF

"sge ft2.x, ft0.x, ft3.x \n" + //if red > 49/0xFF, set 1 to ft2.x

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 98/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 98/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //if 49 < red < 98, ft2.x = 1, if red > 98, ft2.x = 2

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 147/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 147/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //if 49 < red < 98, ft2.x = 1, if 98 < red < 147, ft2.x = 2, if red > 147, ft2.x = 3

"add ft3.x, ft3.x, fc0.x \n" + //ft3 = 196/0xFF
"sge ft4.x, ft0.x, ft3.x \n" + //if red > 196/0xFF, set 1 to ft4.x
"add ft2.x, ft2.x, ft4.x \n" + //ft2.x is between 0 and 4 including, where 0 means no control color

现在我有一个寄存器 ft2 存储:

0对于下面的红色49(实际上所有这些红色值都除以 255,如上面代码中的注释所示)

149和之间的红色98

298和之间的红色147

3147和之间的红色196

4对于上面的红色196

然后,我不会将像素颜色与常数进行比较,而是将ft2.x计数器状态与常数进行比较(常数将是 1、2、3、4 而不是 50、100、150、200)。

不幸的是,这意味着上面的整个代码是我可以节省 GPU 的额外开销,但在 CPU 上无法避免,除非我能找到seq在比较像素颜色和常量时,操作码总是在 CPU 上返回 0 的解决方案。

于 2017-01-31T14:49:44.200 回答