金属着色器:将非位置片段着色器参数转换为窗口/像素坐标?

时间:2018-03-22 22:41:39

标签: fragment-shader metal vertex-shader

在我的Metal应用程序中,我需要在片段位置和基线之间进行一些距离比较,我从顶点着色器传入。片段位置在窗口或像素坐标中到达片段着色器。我想这是因为参数被标记为[[stage-in]],或者因为它被标记为[[position]]?我不清楚是什么原因导致了对位置参数的窗口坐标的转换。

如何传递我的基线坐标,以便它们也能获得与窗口/像素坐标相同的变换?现在我将我的基线坐标作为NDC,然后使用屏幕分辨率手动将它们转换为窗口坐标,但是当我的视口不完全是屏幕对齐时,这会造成严重破坏。

如果基线坐标刚刚以位置坐标的方式预先变换到达,而不是传递更多参数来修复手动转换,那么我可以比较它们而不用担心屏幕大小或视口。

我该怎么做?我查看了插值限定符,实际上我在基线参数上使用[[center_no_perspective]]。但它们仍然是NDC。如何让它们与位置坐标位于同一坐标系中?

这里有参考我的结构和论点:

struct VertexIn {
    float4 position [[position]];
    float4 baseline [[center_no_perspective]];
};

fragment void stroke_abuffer_fragment(VertexIn interpolated [[stage_in]],
     constant ColorScale&  colorScale[[ buffer(9) ]],
     constant Globals&  globals    [[ buffer(11) ]],
) {
    float scale = colorScale.scale;
    float2 worldPos = float2(interpolated.position.xy);  // these are in pixel coords -- points * 2 for retina
    float2 worldCenterFlip = float2(interpolated.baseline.x,-interpolated.baseline.y); // flip y while still in NDC, these will range from -1 to 1
    float2 worldCenter = worldCenterFlip*globals.displaySize + globals.displaySize;  // these are NDC so multiply by displaySize * screenscale
    worldCenter.x *= scale/2.0; // metal ndc is +/- 1
    worldCenter.y *= scale/2.0;

    float alpha;
    float width = interpolated.baseline.w*scale;  // scale is nativeScale ie 2 for retina?
    float edge = widthCountEdge.edge * width;  
    float d = distance(worldPos, worldCenter);

谢谢!

鲍勃

0 个答案:

没有答案