Understanding Fragment Shader Input from a Vertex Shader

I am trying to understand the shader input position of an element from a vertex shader. Does each fragment get its position from the vertex shader?

Here is my shaders.metal

struct VertexOut{
    float4 position [[position]];
    float4 color;
};

vertex VertexOut basic_vertex(     
                           const device packed_float3* vertex_array [[ buffer(0) ]],
                           unsigned int vid [[ vertex_id ]]) {                 
    VertexOut vertexOut;
    vertexOut.position = float4(vertex_array[vid], 1.0);
    vertexOut.color = (vertexOut.position+1)/2;
    return vertexOut;      
}

      

color computed in vertex shader

fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
    return vertexOut.color;             
}

      

color computed in vertex shader

the color computed in the fragment shader

fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
    return (vertexOut.position+1)/2;       
}

      

the color computed in the fragment shader

why do they look different? what is the value of the vertex position passed to each chunk? It seems that all the pieces of the triangle get the centroid of the triangle. how to calculate the position of each chunk in the chunk buffer?

- EDIT -

Split position with window size in fragment shader; yet the triangle is yellow.

ViewController.swift

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let window = view.window
        if(window == nil) {return}
        let scale = view.window?.screen.nativeScale
        let layerSize = view.bounds.size
        //[640, 1136]
        frameSize = [UInt(layerSize.width * scale!), UInt(layerSize.height * scale!)]
        uniformBuffer = device.makeBuffer(bytes: frameSize, length: 2*MemoryLayout<UInt>.size, options: [])

    }
func render() {
    ...
    renderEncoder.setFragmentBuffer(uniformBuffer, offset: 0, index: 0)
    ...
}

      

shaders.metal

struct FrameSize{
    unsigned int x;
    unsigned int y;
};
fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]],
                               const device FrameSize* frameSize [[ buffer(0) ]]
                               ) { // 1
    return float4(vertexOut.position.x/frameSize->x, vertexOut.position.y/frameSize->y, vertexOut.position.z, 1.0);              // 2
}

      

+3


source to share


1 answer


Vertex positions go through perspective transform and viewport transform after they leave the vertex shader. This converts them from clip coordinates (-1.1 to x, y, 0..1 to z) to framebuffer coordinates (x = 0..width-1, y = 0..height-1, z = 0. 0, 1). The fragment shader gets interpolated positions in the framebuffer coordinate space.



Since the slice's position coordinates are in frame space, almost all xy values ​​will be greater than 1.0, so your color will be as red as possible, as green as possible, and then whatever z value you have. You probably want to normalize them, that is, divide the x position value by the width of the framebuffer and the y position along the height of the buffer frame.

+3


source







All Articles