この最小限のメタル シェーダー ペアは、頂点の色属性に基づいて、補間されたシンプルなグラデーションを画面にレンダリングします (頂点の四角形/三角形が指定されている場合)。
#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);
}
…次の頂点を持つ:
{
// x, y, z, w, r, g, b, a
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
}
ここまでは順調ですね。よく知られているグラデーションの三角形/四角形をレンダリングします。
ほとんどすべての GPU HelloWorld チュートリアルで見られるものです。
ただし、補間された頂点の色を取得する代わりに、画面上のフラグメントの位置に基づいて色を計算するフラグメント シェーダーが必要です。画面いっぱいの頂点のクワッドを受け取り、フラグメント シェーダーのみを使用して実際の色を計算します。
私の理解では、頂点の位置はfloat4
、最初の 3 つの要素が 3d ベクトルで、4 番目の要素が に設定されてい1.0
ます。
では、頂点の位置をフラグメント シェーダーの色として単純に再解釈するように上記を変更するのは簡単だと思いました。
#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 from range -1..1 to 0..2
color *= 0.5; // scale from range 0..2 to 0..1
return half4(color);
}
…次の頂点を持つ:
{
// 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,
}
しかし、x 軸と x 軸のグラデーションred=0.0
ではなく、均一な色 (黄色) の画面がレンダリングされていることに非常に驚きました。red=1.0
green=0.0
green=1.0
はinterpolated.position
、各フラグメントに対して同じ値を生成しているようです。
ここで何が間違っていますか?
Ps: (このダミー フラグメント ロジックは、頂点補間を使用して簡単に実現できましたが、実際のフラグメント ロジックでは実現できませんでした。)