ios - How to get fragment coordinate in fragment shader in Metal? -
this minimal metal shader pair renders simple interpolated gradient onto screen (when provided vertex quad/triangle) based on vertices' color attributes:
#include <metal_stdlib> using namespace metal; typedef struct { float4 position [[position]]; float4 color; } vertex_t; vertex vertex_t vertex_function(const device vertex_t *vertices [[buffer(0)]], uint vid [[vertex_id]]) { return vertices[vid]; } fragment half4 fragment_function(vertex_t interpolated [[stage_in]]) { return half4(interpolated.color); }
…with following vertices:
{ // x, y, z, w, r, g, b, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0 }
so far good. renders well-known gradient triangle/quad.
1 find in pretty every single gpu helloworld tutorial.
i need have fragment shader instead of taking interpolated vertex color computes color based on fragments position on screen. receives screen-filling quad of vertices , uses fragment shader calculate actual colors.
from understanding position of vertex float4
first 3 elements being 3d vector , 4th element set 1.0
.
so—i thought—it should easy modify above have reinterpret vertex' position color in fragment shader, right?
#include <metal_stdlib> using namespace metal; typedef struct { float4 position [[position]]; } vertex_t; vertex vertex_t vertex_function(const device vertex_t *vertices [[buffer(0)]], uint vid [[vertex_id]]) { return vertices[vid]; } fragment half4 fragment_function(vertex_t interpolated [[stage_in]]) { float4 color = interpolated.position; color += 1.0; // move range -1..1 0..2 color *= 0.5; // scale range 0..2 0..1 return half4(color); }
…with following vertices:
{ // x, y, z, w, 1.0, -1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, }
i quite surprised find uniformly colored (yellow) screen being rendered, instead of gradient going red=0.0
red=1.0
in x-axis , green=0.0
green=1.0
in x-axis:
(expected render output vs. actual render output)
the interpolated.position
appears yielding same value each fragment.
what doing wrong here?
ps: (while dummy fragment logic have been accomplished using vertex interpolation, actual fragment logic cannot.)
the interpolated.position appears yielding same value each fragment.
no, values large. variable [[position]] qualifier, in fragment shader, in pixel coordinates. divide render target dimensions, , you'll see want, except having invert green value, because metal's convention define upper-left origin this, not bottom-left.
Comments
Post a Comment