Ios 具有属性';颜色';马科斯

Ios 具有属性';颜色';马科斯,ios,macos,metal,Ios,Macos,Metal,我正在尝试将简单的应用程序移植到macOS。金属编译器说 Fragment shader parameter with attribute 'color' is supported only on iOS (requires -std=ios-metal1.[0|1|2]). 如何克服这个错误?我在哪里可以找到指出macOS和iOS之间金属API差异的文档 是带有macOS目标的Xcode项目。上述错误是由Light.metal引发的 macOS 10.13 “英特尔i5-5257u Iris

我正在尝试将简单的应用程序移植到macOS。金属编译器说

Fragment shader parameter with attribute 'color' is supported only on iOS (requires -std=ios-metal1.[0|1|2]).
如何克服这个错误?我在哪里可以找到指出macOS和iOS之间金属API差异的文档

是带有
macOS
目标的Xcode项目。上述错误是由
Light.metal
引发的

macOS 10.13
“英特尔i5-5257u Iris 6100”将在将来显示该示例应用程序中的哪个特定文件产生了错误以及确切的行。或者,由于您正在移植(修改)示例,请显示项目中的片段着色器代码。此外,请指出您正在使用的macOS版本

从理论上讲,应该显示平台之间的差异。这可能并不明显,但我相信这一特性属于该表中的“可编程混合”。基本上,从渲染目标获取现有颜色主要有助于在计算新值时使用原始值,即执行新值与旧颜色的自定义混合

在第4.3.4.4节中,片段函数输入的属性限定符:

[[color(m)]]
属性限定符仅在iOS中受支持

如果出现错误的着色器为,则它实际上只输出到
灯光
渲染目标(附件3)。它只是保存了其他数据(并将读取数据作为计算的输入)。对于
纹理,它(有效地)对其进行读取和写入

因此,在macOS 10.13+上,您可能能够使用纹理读写功能,具体取决于灯光纹理的像素格式和GPU的功能。这部分的渲染过程与在iOS上不同。您不会指定任何渲染目标。片段着色器将返回
void
。它的所有输出都将通过纹理写入。与其将纹理用作渲染目标(颜色附件),不如将其传递到纹理表中。您不会将
FragOutput
类型与其
[[color(n)]]
字段一起使用,而是使用
[[texture(n)]]
属性接收纹理作为输入参数。您可以从碎片位置(
uint2(in.position)
)的纹理中
read()
(而不是
sample()

比如说:

fragment void lightFrag(VertexOutput in [[stage_in]],
                        constant LightFragmentInputs *lightData [[buffer(0)]],
                        texture2d<float, access::read> normal [[texture(0)]],
                        depth2d<float, access::read> depth [[texture(1)]],
                        texture2d<float, access::read_write> light_tex [[texture(2), raster_order_group(0)]])
{
    uint2 pos = uint2(in.position);
    float3 n_s = normal.read(pos).rgb;

    float scene_z = depth.read(pos);

    float3 n = n_s * 2.0 - 1.0;

    // Derive the view-space position of the scene fragment in the G-buffer
    // Since the light primitive and the G-buffer were rendered with the same view-projection matrix,
    // we can treat the view-space position of the current light primitive fragment as a ray from the origin,
    // and derive the view-space position of the scene by projecting along the ray with (scene_z / v_view.z).
    // Our scene view-space position is also the view-vector to the scene fragment.
    float3 v = in.v_view * (scene_z / in.v_view.z);

    // Now, we have everything we need to calculate our view-space lighting vectors.
    float3 l = (lightData->view_light_position.xyz - v);
    float n_ls = dot(n, n);
    float v_ls = dot(v, v);
    float l_ls = dot(l, l);
    float3 h = (l * rsqrt(l_ls / v_ls) - v);
    float h_ls = dot(h, h);
    float nl = dot(n, l) * rsqrt(n_ls * l_ls);
    float nh = dot(n, h) * rsqrt(n_ls * h_ls);
    float d_atten = sqrt(l_ls);
    float atten = fmax(1.0 - d_atten / lightData->light_color_radius.w, 0.0);
    float diffuse = fmax(nl, 0.0) * atten;

    float4 light = light_tex.read(pos);
    light.rgb += lightData->light_color_radius.xyz * diffuse;
    light.a += pow(fmax(nh, 0.0), 32.0) * step(0.0, nl) * atten * 1.0001;
    light_tex.write(light, pos);
}    
fragment void lightFrag(VertexOutput in[[stage_in]],
常量LightFragmentInputs*lightData[[缓冲区(0)],
纹理2D法线[[纹理(0)],
深度2D深度[[纹理(1)]],
纹理2D灯光纹理[[纹理(2),光栅顺序(0)])
{
uint2位置=uint2(处于位置);
float3 n_s=正常读取(位置).rgb;
浮动场景_z=深度读取(pos);
浮动3 n=n_*2.0-1.0;
//导出场景片段在G缓冲区中的视图空间位置
//由于灯光基本体和G缓冲区使用相同的视图投影矩阵进行渲染,
//我们可以将当前灯光基本体片段的视图空间位置视为来自原点的光线,
//并通过使用(scene_z/v_view.z)沿光线投影来导出场景的视图空间位置。
//我们的场景视图空间位置也是场景片段的视图向量。
float3 v=in.v_视图*(场景z/in.v_视图.z);
//现在,我们有了计算视图空间光矢量所需的一切。
float3 l=(lightData->view\u light\u position.xyz-v);
浮点数n_ls=点(n,n);
浮点数v_ls=点(v,v);
浮点数l_ls=点(l,l);
浮动3 h=(l*rsqrt(l_ls/v_ls)-v);
浮点数h_ls=点(h,h);
浮点nl=点(n,l)*rsqrt(n_-ls*l_-ls);
浮动nh=点(n,h)*rsqrt(n_ls*h_ls);
浮点数d_atten=sqrt(l_ls);
float atten=fmax(1.0-d_atten/lightData->light_color_radius.w,0.0);
浮动扩散=fmax(nl,0.0)*注意力;
float4灯=灯号读数(位置);
light.rgb+=lightData->light\u color\u radius.xyz*漫反射;
光a+=功率(fmax(nh,0.0),32.0)*阶跃(0.0,nl)*衰减*1.0001;
灯光文字书写(灯光、位置);
}    
如果不能使用纹理读写,则可能需要使用两种纹理。将旧灯光纹理作为只读参数传递,并让片段着色器将新值(作为
float4
返回类型)返回到新灯光纹理中。您可以在原始代码使用旧灯光纹理的帧渲染的其余部分使用新灯光纹理,也可以将新灯光纹理中的结果复制回旧灯光纹理