来自文档: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,希望如果浮点数具有不同的精度(并且更高和更低的数字将工作,只要它们等于256 像素长渐变内的像素之一),但我的希望没有得到返回。
然后我尝试了将常量存储为整数的解决方法,并在着色器内部将值乘以 255 并删除小数,令我惊讶的是,当它在 GPU 上工作时,它在软件渲染上失败:mul ft0.x, ft0.x, fc0.y
通过将 ft0.x (红色 channel )乘以常数 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,并将其添加到另一个临时寄存器(计数器),以便通过检查计数器我可以看到值在哪个范围内。
最佳答案
这是最终为我解决问题的解决方法。
我在红色 alpha channel 上有 4 种颜色,它们通知着色器要做什么。如果红色值为 50,着色器将采用左侧像素作为源,如果为 100,则采用顶部像素,依此类推。因此,我所要做的就是将 0 或 1 个偏移设置为寄存器的 4 个组件的 4 个 seq
命令,稍后我可以使用采样器的位置从寄存器中添加或删除这些组件。
因为 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,如上面代码中的注释所示)1
用于 49
和 98
之间的红色2
用于 98
和 147
之间的红色3
用于 147
和 196
之间的红色4
为 196
上方的红色然后,我将
ft2.x
计数器状态与常量进行比较,而不是将像素颜色与常量进行比较(常量将是 1,2,3,4 而不是 50,100,150,200)。不幸的是,这意味着上面的整个代码是一个额外的开销,我可以节省 GPU,但无法避免在 CPU 上,除非我能找到解决
seq
操作码在比较像素颜色和常量时总是在 CPU 上返回 0 的解决方案。关于shader - AGAL seq 操作码适用于硬件,但不适用于软件仿真(两者的浮点数比较不同?),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41953220/