そんなことをする必要があるかどうかはさておき、やりたくなったのでメモしておきます。
前提環境は以下の通り :
- Unity 2018.4.20f1 Personal
- DirectX 11+
- 板ポリ (Quad) を分割する
Vertex Shader は頂点をそのまま渡すだけのものを、 Hull Shader は下のような感じ。
// #define TESSELLATION 16 h2d_const hs_const() { h2d_const o = (h2d_const) 0; const float tess = TESSELLATION; o.edges[0] = tess; o.edges[1] = tess; o.edges[2] = tess; o.edges[3] = tess; o.inside[0] = tess; o.inside[1] = tess; return o; } [domain("quad")] [partitioning("pow2")] [outputtopology("point")] [outputcontrolpoints(4)] [patchconstantfunc("hs_const")] h2d hs(const InputPatch<v2h, 4> input, const uint id : SV_OUTPUTCONTROLPOINTID) { h2d o = (h2d) 0; o.position = input[id].position.xyz; return o; }
この状態で、 Domain Shader で一意な ID を割り振っていきたい。
ただ、参考にした Qiita 記事の割り振り方だと、 ID の重複がいくつか見られました。
ID: 15 までの描画
ID: 16 までの描画、見ての通り若干描画されている数が多い
そこで、改良したのがこちらです。
[domain("quad")] d2g ds(const h2d_const data, const OutputPatch<h2d, 4> i, const float2 uv : SV_DOMAINLOCATION) { d2g o = (d2g) 0; // position 計算はなくても良いよ! const float3 x = lerp(i[0].position, i[1].position, uv.x); const float3 y = lerp(i[3].position, i[2].position, uv.x); const float3 z = lerp(x, y, uv.y); o.position = float4(z, 1.0f); o.id = (uint) (uv.x * TESSELLATION) + ((uint) ((uv.y * TESSELLATION) * TESSELLATION)) + (uint) (uv.y * TESSELLATION); return o; }
全ての値を Geometry Shader から出力して、 Analyzer でダンプした感じだと、
ID: 0 から連番で出力されていました。
ということで、 ID の生成方法でした。