我正在使用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。
问题:
是否会为每个像素坐标调用片段着色器?或者仅适用于每个屏幕坐标?
如果为每个像素坐标调用它,我如何访问片段着色器内的每个像素?
我在pcoord.y(在上面的代码中)尝试了相同的结果。
答案 0 :(得分:1)
稍作挖掘后,您对问题2的答案似乎是正确的,即使用$src_clone = $source->cloneNode();
$picture->appendChild($src_clone);
$image->parentNode->replaceChild($src_clone, $image);
$picture->appendChild($image);
。
对于问题1,我发现Metal片段着色器似乎可以在本机像素坐标(即物理硬件屏幕的像素尺寸)中工作。
我的问题涉及在片段着色器中剪切(丢弃)像素,由于我剪切到屏幕像素坐标而不是原始像素坐标,所以我得到了意外的结果。在意识到这一点之后,一切都很好。
因此,iOS似乎使用了自己的屏幕坐标(我认为这是点),随后将其缩放到物理硬件。 UI输入似乎也可以在屏幕坐标中工作。金属片段可以使用本机(硬件)屏幕坐标工作。
我发现我可以使用以下方法找出相对信息(在Swift 5中):
static final String STR = "....very long string ...";
对于我的系统,这给出了:
in.position.xy
因此,从系统屏幕尺寸到硬件屏幕尺寸,我们乘以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
。
答案 1 :(得分:0)
这是我自己的答案:
虽然我无法找出为什么一些简单的项目没有在着色器代码中给出精确的像素坐标,但我创建的其他项目确实给了我像素坐标系中的坐标(包括屏幕缩放系数)。也就是在上面的例子中,我确实得到750x1334
坐标,而不是375x667
。
所以,回答我发布的两个问题:
一旦我发现我的项目出现了什么问题,那么应该更新这个,这些问题会给出屏幕坐标中的坐标