我试图从顶点着色器中理解片段着色器输入位置。每个片段是否从顶点着色器接收其位置?
这是我的 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;
}
在片段着色器
中计算的颜色fragment float4 basic_fragment(VertexOut vertexOut [[stage_in]]) {
return (vertexOut.position+1)/2;
}
为什么它们呈现不同?传递给每个片段的顶点位置的值是多少?似乎三角形的所有碎片都接收到三角形的质心。如何计算片段缓冲区中每个片段的位置?
- 编辑 -
片段着色器中窗口大小的分割位置;三角形仍然是黄色。
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
}
答案 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除以帧缓冲区高度。