Nic*_*ari 5 xcode alphablending metal
我在Metal中渲染半透明精灵时遇到麻烦。我已经阅读了这个问题,而这个问题,而这一次,和这个线程在苹果的论坛上,还有几个,但不能完全得到它的工作,所以请标志着这个问题作为一个重复之前阅读。
我的参考纹理有四行四列。这些行分别是完全饱和的红色,绿色,蓝色和黑色。列的不透明度从100%不透明到25%不透明(依次为1、0.75、0.5、0.25 alpha)。
在Pixelmator(我创建它的地方)上,它看起来像这样:
如果在导出之前插入完全不透明的白色背景,它将看起来像这样:
... 但是,当我将其纹理映射到Metal中的四边形上,并在将背景清除为不透明的白色(255、255、255、255)后进行渲染时,我得到了:
...显然比不透明的碎片要暗(后面的亮白色应“渗出”)。
我将png文件作为纹理资产导入到Xcode中,作为我应用程序资产目录中的纹理资产,并在运行时使用加载了该文件MTKTextureLoader。该.SRGB选项似乎没有什么不同。
就我所知,着色器代码没有做任何花哨的事情,但仅供参考:
#include <metal_stdlib>
using namespace metal;
struct Constants {
float4x4 modelViewProjection;
};
struct VertexIn {
float4 position [[ attribute(0) ]];
float2 texCoords [[ attribute(1) ]];
};
struct VertexOut {
float4 position [[position]];
float2 texCoords;
};
vertex VertexOut sprite_vertex_transform(device VertexIn *vertices [[buffer(0)]],
constant Constants &uniforms [[buffer(1)]],
uint vertexId [[vertex_id]]) {
float4 modelPosition = vertices[vertexId].position;
VertexOut out;
out.position = uniforms.modelViewProjection * modelPosition;
out.texCoords = vertices[vertexId].texCoords;
return out;
}
fragment float4 sprite_fragment_textured(VertexOut fragmentIn [[stage_in]],
texture2d<float, access::sample> tex2d [[texture(0)]],
constant Constants &uniforms [[buffer(1)]],
sampler sampler2d [[sampler(0)]]) {
float4 surfaceColor = tex2d.sample(sampler2d, fragmentIn.texCoords);
return surfaceColor;
}
Run Code Online (Sandbox Code Playgroud)
在应用程序方面,我在渲染过程描述符上使用以下(相当标准的)混合因子和操作:
descriptor.colorAttachments[0].rgbBlendOperation = .add
descriptor.colorAttachments[0].alphaBlendOperation = .add
descriptor.colorAttachments[0].sourceRGBBlendFactor = .one
descriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
descriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
descriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
Run Code Online (Sandbox Code Playgroud)
(我试图改变sourceRGBBlendFactor,从.one以.sourceAlpha使得它有点暗。)
如果我将图像渲染为红色背景(255、0、0、255),则会得到以下信息:
请注意,第一行向右逐渐变暗。一直以来,它应该是相同的颜色,因为它会混合具有相同RGB分量(255,0,0)的两种颜色。
我已经将我的应用程序剥离到最低限度,并在Github上放置了一个演示项目;完整的Metal设置可以在存储库的源代码中看到。也许有一些我没有提到的原因导致了这种情况,但是我无法完全弄清楚是什么原因...
编辑:
正如在评论@KenThomases建议,我改变了的价值MTKView属性colorPixelFormat从默认.bgra8Unorm到bgra8Unorm_srgb,并设置colorSpace属性一样view.window?.colorSpace?.cgColorSpace。现在,半透明的片段看起来暗了很多,但仍然不是预期的颜色:
(第一行应在红色背景上从左到右完全“不可见”。)
附录
我遇到了有关使用Shader Debugger的Apple文档,因此我决定看看当我的应用程序绘制精灵右上角的片段之一时片段着色器中发生了什么(该片段应该是完全饱和的红色)。不透明度为25%)。
有趣的是,片段着色器返回的值(基于颜色缓冲区的当前颜色和混合因子/函数,将对其应用alpha混合)是[0.314, 0.0, 0.0, 0.596]:
此RGBA值似乎是是否完全不受影响MTKTextureLoader.Option.SRGB是true,false或缺席。
请注意,红色分量(0.314)和alpha分量(0.596)不相等,尽管(如果我没记错的话)它们应该是相等的,但对于完全饱和的红色且预乘有alpha。
我想这意味着我已将问题缩小到纹理加载阶段...?
也许我应该放弃便利MTKTextureLoader,弄脏我的手...?
嗯,事实证明,问题确实在纹理加载阶段,但没有在我可能会进行调整的任何代码中进行(至少坚持不下来 MTKTextureLoader)。
似乎我需要在Xcode中对资产目录的Attributes Inspector进行一些更改(但至少现在我要用Xcode以下标签来标记我的原始问题:离青铜徽章更近一步!)。
具体来说,我必须将纹理集的“ 解释”属性从默认选项“ Colors”更改为“ Colors(未预乘)”:
显然,这些资产目录纹理集在设计时考虑了更传统的纹理图像格式,例如TGA,而非 PNG(根据规范,这是官方未预乘的)。
我以某种方式期望这MTKTextureLoader足以在加载时为我做到这一点。显然,这不是一条可以从(例如)PNG文件的元数据/标题中可靠读取的信息。
现在,我的参考纹理呈现出其所有的辉煌:
作为最终的更严格的测试,我可以确认所有4种颜色在等效的RGB背景下都会“消失”,而不管纹理像素的不透明度如何:
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |