理解顶点着色器

时间:2017-07-10 12:31:56

标签: rendering shader 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;      
}

顶点着色器

中计算的颜色
fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
    return vertexOut.color;             
}

color computed in vertex shader

片段着色器

中计算的颜色
fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
    return (vertexOut.position+1)/2;       
}

color computed in fragment shader

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

- 编辑 -

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

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
}

1 个答案:

答案 0 :(得分:4)

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

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