3

我正在使用 Metal 编写一个 3D 应用程序。对于 3D 渲染,我需要控制每个像素。在普通屏幕中,这似乎与传递给着色器的 [[position]] 变量一起工作正常。但是在 Retina 显示器中,有一个缩放因子,每个屏幕坐标代表 2x2(或 3x3)像素。

让我以 iPhone 6 屏幕为例进行详细说明:屏幕坐标为 375x667,像素坐标为 750x1334。这是我的(测试)着色器代码:

fragment half4 myFragShader(vtxOut in [[stage_in]],
                           float4 pcoord [[position]])
{    
    if(pcoord.x >187.5)    //187.5=375/2
         return half4(1.0 , 0.0 , 0.0, 1.0);  // return red
    else return half4(0.0 , 0.0 , 1.0, 1.0);  // return blue 
}

使用上面的测试代码,我(完全)将屏幕的左半部分变为蓝色,将右半部分变为红色。这意味着 pcoord 来自 375x667 坐标系,而不是 750x1334。

问题:

  1. 是否会为每个像素坐标调用片段着色器?还是仅适用于每个屏幕坐标?

  2. 如果每个像素坐标都调用它,我如何访问片段着色器中的每个像素?

我对 pcoord.y (在我上面的代码中)进行了同样的尝试,结果相似。

4

2 回答 2

1

这是我自己的答案:

虽然我不知道为什么一些简单的项目没有在着色器代码中给出确切的像素坐标,但我创建的其他几个项目确实给了我像素坐标中的坐标(包括屏幕缩放因子),即在我上面的示例中,我确实得到了750x1334坐标,而不是375x667

所以,回答我发布的两个问题:

  1. 将为每个像素坐标调用片段着色器,并且
  2. in.position.xy给出着色器代码内的坐标。

一旦我发现在屏幕坐标中给出坐标的项目中出了什么问题,将更新此内容。

于 2015-03-19T12:34:54.610 回答
1

经过一番挖掘,您对问题 2 的回答似乎是正确的,即使用in.position.xy.

对于问题 1,我发现 Metal 片段着色器似乎可以在原生像素坐标中工作,即物理硬件屏幕的像素尺寸。

我的问题涉及在片段着色器中剪裁(丢弃)像素,我得到了意想不到的结果,因为我剪裁到屏幕像素坐标而不是原生像素坐标。在意识到这一点之后,一切都很好。

所以看起来 iOS 使用自己的屏幕坐标(我相信称为点),然后再重新调整到物理硬件。UI 输入似乎也适用于屏幕坐标。而 Metal 片段使用原生(硬件)屏幕坐标。

我发现我可以使用以下方法找到相关信息(在 Swift 5 中):

let systemWidth = UIScreen.main.bounds.size.width
let systemHeight = UIScreen.main.bounds.size.height
let systemScale = UIScreen.main.scale

let metalWidth = UIScreen.main.nativeBounds.size.width
let metalHeight = UIScreen.main.nativeBounds.size.height
let metalScale = UIScreen.main.nativeScale

对于我的系统,这给出了:

System Screen size = 768.0 x 1024.0
      system scale = 2.0
 Metal screen size = 1536.0 x 2048.0
       metal scale = 2.0

所以大概从系统屏幕尺寸到硬件屏幕尺寸我们乘以systemScale,而从金属屏幕尺寸到系统我们除以metalScale

于 2020-10-07T13:16:50.797 回答