本质上,我想做的(在 DirectX 中)是拍摄两个部分透明的图像并将它们混合在一起。这适用于默认混合,只要它们都显示为重叠等。但是,问题是不透明度在两者相交处显着上升。随着更多精灵重叠,这会导致越来越多的问题。我想做的是保持混合不变,除了为所有这些混合的精灵保持全局不透明度,不管它们如何重叠。
似乎会有一个渲染设置(所有这些精灵在他们的精灵批次中都是单独的,这使得这部分很容易),但如果是这样我不知道。现在我有点在黑暗中拍摄,我尝试了很多不同的东西,但没有一个看起来完全正确。我知道我可能需要某种 D3DBLENDOP 变体,但我只是不知道我真正需要什么样的设置(我已经尝试了很多东西,但现阶段都是猜测)。
这是标准混合实际发生的情况的屏幕截图(我能得到的最好的):http ://arcengames.com/share/FFActual.png这是一个屏幕截图,其中包含我希望如何混合的样机输出(在 Photoshop 中将力场添加到同一层,然后给定一个共享的 alpha 值):http ://arcengames.com/share/FFMockup.png
这就是我在 Photoshop 中的做法: 1. 拍摄两张图像,并移除所有透明度(完全透明的像素除外)。2. 将它们组合成一层,混合颜色但完全没有部分 alpha。3. 现在将该层的全局透明度设置为(比如说)40%。
结果是看起来有点混合在一起的颜色,但重叠部分的不透明度没有增加。
更新:好的,非常感谢下面的 Goz,他建议使用 Z-Buffer。这样可行!总的来说,混合是完美的,正是我想要的。唯一剩下的问题?使用这种新方法,在最后渲染的力场图像边缘周围会出现巨大的伪影。看到这个: http ://www.arcengames.com/share/FFZBuffer.png
更新:以下是 C# (SlimDX) 中的最终解决方案
- 每帧将 ZBuffer 清除为黑色、透明或白色都具有相同的效果(这是在调用 BeginScene 之前)
Direct3DWrapper.ClearDevice(SlimDX.Direct3D9.ClearFlags.ZBuffer, Color.Transparent, 0);
- 所有其他精灵都在 Z=1 处绘制,并为它们禁用 ZBuffer:
device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
- 力场精灵在 Z=2 处绘制,启用 ZBuffer 并启用 ZWrite,ZFunc 为 Less:
device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer); device.SetRenderState(RenderState.ZWriteEnable, true); device.SetRenderState(RenderState.ZFunc, Compare.Less);
- 这时候还设置了以下标志,以防止我遇到的黑边神器:
device.SetRenderState(RenderState.AlphaTestEnable, true); device.SetRenderState(RenderState.AlphaFunc, Compare.GreaterEqual); device.SetRenderState(RenderState.AlphaRef, 55);
请注意,AlphaRef 为 55,因为在我使用的特定源图像中设置了 alpha 级别。如果我的源图像具有更高的 alpha 值,那么 AlphaRef 也需要更高。