title: Metal shaders: converting non-position fragment shader arguments to windows/pixel coords?
body: <p>In my Metal app I need to do some distance comparisons between the fragment position and a baseline, which I pass in from the vertex shader.  The fragment position comes to the fragment shader in window, or pixel, coordinates.  I guess this is because the argument is marked [[stage-in]], or maybe because it is marked [[position]]?  I'm unclear on what causes the transformation to window coords on position arguments.</p>
  
  <p>How would I pass my baseline coordinates so that they also receive the same transformation to windows/pixel coordinates?  Right now I am getting my baseline coordinates as NDC and then manually converting them to windows coordinates using the screen resolution, but that is causing havoc when my viewport is not exactly screen aligned.  </p>
  
  <p>Rather than pass in more arguments to fix the manual conversion, it would be a lot simpler if the baseline coordinates could just arrive pre-transformed the way that the position coordinates do, so that I can just compare them and not worry about the screen size or viewport.</p>
  
  <p>How do I do that?  I've looked at the interpolation qualifiers, and I am actually using [[center_no_perspective]] on my baseline arguments.  But they are still NDC.  How do I get them to be in the same coordinate system as the position coordinates?</p>
  
  <p>For reference here are my structures and arguments:</p>
  
  <pre><code>struct VertexIn {
      float4 position [[position]];
      float4 baseline [[center_no_perspective]];
  };
  
  fragment void stroke_abuffer_fragment(VertexIn interpolated [[stage_in]],
       constant ColorScale&amp;  colorScale[[ buffer(9) ]],
       constant Globals&amp;  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);
  </code></pre>
  
  <p>Thanks!</p>
  
  <p>Bob</p>