イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

ShadersLaboratryのサンプルを読んでいく記事-Geometry

Shaders

 

++

Demo 90 - Flat shading

float3 vecA = IN[1].vertex - IN[0].vertex;
float3 vecB = IN[2].vertex - IN[0].vertex;
float3 normal = cross(vecA, vecB);
normal = normalize(mul(normal, (float3x3) unity_WorldToObject));

1点を中心として2辺の外政を求めることでポリゴンの法線方向を取得

 

float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
o.light = max(0., dot(normal, lightDir));

ライティングを計算、通常なら頂点ごとに行うが(多分)これはポリゴン(面)単位で行ってるのがFlat(カクカク?)な見た目になる原因

 

o.uv = (IN[0].uv + IN[1].uv + IN[2].uv) / 3;

 各頂点のUV座標を3頂点の重心に移動

 

++

Demo 82 - Extrude faces

normalFaceにポリゴンの法線ベクトルを取得

頂点を法線方向に伸ばしている。

ただ色変え部分がややこしい。

ジオメトリシェーダの本質ではないのでスルーする。

 

++

Demo 81 - Quads to pyramids

noramFaceにポリゴンの法線ベクトルを取得

  step(a, x) (x >= a) ? 1 : 0 を返します。

float3 centerPos = (IN[0].vertex + IN[1].vertex) / 2;
float2 centerTex = (IN[0].uv + IN[1].uv) / 2;

if((step(edge1, edge2) * step(edge3, edge2)) == 1.0)
{
		centerPos = (IN[2].vertex + IN[0].vertex) / 2;
		centerTex = (IN[2].uv + IN[0].uv) / 2;
}
else if((step(edge2, edge3) * step(edge1, edge3)) == 1.0)
{
		centerPos = (IN[1].vertex + IN[2].vertex) / 2;
		centerTex = (IN[1].uv + IN[2].uv) / 2;
}

この部分は一番長い辺を決定している。

(step(edge1, edge2) * step(edge3, edge2)) == 1.0

はedge2がedge1 3 より長いかどうかのチェック

最初に0-1間のcenterPosを入れてるのはedge1が最も長かった場合

(一番長い辺を取得してるが、それは正方形などの場合、斜辺である.。なので斜辺を取得している、と考えてもいい)

 

centerPos += float4(normalFace, 0) * _Factor;

で最も長い辺をポリゴンの法線方向に伸ばす

 

for(int i = 0; i < 3; i++)

の処理で、三角錐が出来上がる

 

これ以降のtristream.Append(o);は三角錐の底面となる。

 

++

Demo 80 - Triangles to pyramids

Demo81とほぼ同じ。ただこちらは最も長い辺ではなく、重心座標を伸ばしている

 

++

Demo 93 - Wireframe

o.bary = float3(1., 0., 0.);

o.bary = float3(0.,1, 0.);

o.bary = float3(0.,0, 1.);

と頂点ごとに異なるfloat3を入れている。

それがfragに渡されてるので、fragにおける頂点間のbaryは線形補完され各成分は0~1となっている 

1回目のパスで裏面が描写され、2回目のパスで表面が描写されている。

 

if(!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))

 

bool3はfloat3とかのbool版

any(x) x のいずれかの成分が 0 以外の値であるかどうかをテストします。

で、これが!で逆転するから

全てWireframeValより小さい場合:false

全てWireframeValより大きい場合:true

一つでもWireframeValより小さい場合:false

となる。

なので

WireframeValより小さい値があれば_BackColorを返す。

全てwireframeValより大きければdiscard、何も描写しない。

言い換えれば、ポリゴンの重心に近いほど、各成分が大きくなるため、discardされやすい。

 

++

Demo 94 - Wireframe without diagonal

#if _REMOVEDIAG_ON 内にて最も長い辺、つまり斜辺を取得して、その辺によってparamの特定の成分に1を入れている。

これで斜辺が消せる理由だが紙に書くなどすれば分かりやすい。

頂点0,1,2があり、斜辺が1,2間の線となる場合、x成分が加算されるので、0,1,2のbaryは

(2,0,0) (1,0,1) (1,1,0)となる。

斜辺である(1,0,1) (1,1,0)間の全ての成分は線形補完されても0超過(t>0)になる。

全てwireframeValより大きければdiscardされるので、斜辺のbaryの各成分は全て0超過になるので描写されなくなる。

(各頂点に近づいた場合、成分が小さくなるので描写されてしまうと思ったが、多分、斜めに伸びてる分は各頂点から伸びてるラインと被ってるため実際には斜線はいくらか病者されてるが、描写されてないように見えるのだと思う)

あとはDemo93と同じ