PCSX2的impossible blend释疑

原文在此:

Explanation of impossible blend

http://pcsx2.net/developer-blog/268-explanation-impossible-blend.htmlhttp://pcsx2.net/developer-blog/268-explanation-impossible-blend.html

译者:我们很多人都用过PCSX2来玩PS2游戏,但可能很多人未必知道,PS2的模拟其实比很多其他硬件都要艰难。CPU方面由于EE/VU0/VU1自然不用多说,而GS方面,功能强大但和现代硬件不兼容的情况很多,偏偏很多游戏开发者(尤其是日系PS2游戏开发者)都喜欢摆弄一些稀奇古怪的效果,对模拟器开发人员来说就成为了一个大难题。老版本的PCSX2很多效果都不能在硬件模式下正确模拟,但新版解决了不少相关的问题。链接里就是PCSX2对PS2颜色混合模拟的官方解释。

---

颜色混合的目标是把两个颜色混合起来得到新的颜色。在现代的GPU上,混合公式一般是这么写的:


系数1 * 颜色1 +/- 系数2 * 颜色2


颜色1/颜色2 可能是源(fragment shader的计算结果)或者目标的颜色(帧缓冲里的保存数值)两者之一。

系数1/系数2可能是源或者目标的alpha值,1 - alpha,或者是一个常量。GPU会把系数clamp到0和1之间。

然而在PS2上,混合公式是这么写的:


(颜色1 - 颜色2) * 系数 + 颜色3


颜色1/2/3可能是源或者目标颜色,或者是0。

系数是源或者目标的alpha,或者是常量。

这给模拟器编写带来了两个问题:

1. PS2的系数值是被clamp到0和2之间的。还好这只在少数情境下出现。

(译注:最有名的例子之一,是FFX的重力魔法。当我了解了这个特效是如何实现之后,我深深崇拜想出这么用颜色混合的家伙。

这是个很普通的alpha blend,但由于alpha > 1,因此结果就从

SrcColor * SrcAlpha + DstColor * (1 - SrcAlpha)

变成了背景反色

SrcColor * SrcAlpha - DstColor * (SrcAlpha - 1)

错误的渲染结果是普通的alpha混合


正确的渲染结果,注意背景反色!



2. 如果颜色1/3是同一个源,那么公式就被转化为

颜色1 * (1 + 系数) - 颜色2 * 系数

看上去似乎能套在现代GPU的公式,然而1 + 系数意味着系数会大于1。在现代GPU下这个系数会被限制到1,无法正确模拟。(译注:这里的例子有很多,不过很多例子一般的玩家不一定能察觉。因为结果就是颜色比PS2要暗,但不至于很大的差别。)

PCSX2最近的更新把第二种情况给修正了。它使用的是在把混合公式直接塞到fragment shader里的方法。不过会有一个变数:fragment shader的执行比较慢(毕竟它相当于是在小CPU上执行的代码),所以现代GPU里都是并行乱序执行的。如果你一个draw call里塞入两个三角形,在计算的时候,第二个三角形的fragment shader可能会在第一个之前运算。然而颜色混合是按序执行的,如果乱序的话,渲染结果很可能就乱套了。不过,只要一次draw call渲染的物体本身没有自我覆盖,那么每个像素点只会被算一次fragment shader,那就不需要考虑执行顺序的问题了。

这就意味着,我们需要把一个n个三角面的draw call拆开成n个draw call。这么做的话性能损失就很大了,但在某些情形下这么干还是合理的。

另外一个要解决的问题就是如何访问目标像素的值。GPU是有纹理缓存(texture cache)的。纹理缓存是只读的,这样才不会有缓存一致性的问题。目标值可以被写入,但是下次读取的时候读取出来的值是错误的,这是因为缓存一致性被破坏。在进行fragment shader里混合的时候,纹理是只读的,但下一次draw call就被改变了。必须要有一个办法去invalidate 纹理缓存,而这在OpenGL 4.5里终于有函数去实现这个了。这样我们就能在fragment shader里进行颜色混合,而不会被GPU内核所限制住。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值