理解来自顶点着色器的片段着色器输入

Nec*_*twi 3 shader rendering metal

我试图从顶点着色器了解片段着色器输入位置。每个片段是否从顶点着色器接收其位置?

这是我的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;      
}
Run Code Online (Sandbox Code Playgroud)

顶点着色器中计算的颜色

fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
    return vertexOut.color;             
}
Run Code Online (Sandbox Code Playgroud)

在顶点着色器中计算的颜色

片段着色器中计算的颜色

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

在片段着色器中计算的颜色

为什么它们的呈现方式不同?传递给每个片段的顶点位置值是多少?似乎三角形的所有片段都接收三角形的质心。如何计算每个片段在片段缓冲区中的位置?

- 编辑 -

片段着色器中与窗口大小的分割位置;三角形仍然是黄色的。

视图控制器.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)
    ...
}
Run Code Online (Sandbox Code Playgroud)

着色器金属

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
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*all 5

顶点位置在离开顶点着色器后经过透视分割和视口变换。这会将它们从剪辑坐标(x,y 中的 -1..1,z 中的 0..1)转换为帧缓冲区坐标(x=0..width-1,y=0..height-1,z=0。 .1)。片段着色器接收帧缓冲区坐标空间中的内插位置。

由于片段位置坐标在帧缓冲区空间中,几乎所有的 xy 值都将大于 1.0,因此您的颜色将只是最大的红色,最大的绿色,然后是您获得的任何 z 值。您可能想要重新规范化它们,即将位置 x 值除以帧缓冲区宽度,位置 y 除以帧缓冲区高度。