TOC: エフェクトとシェーダー
Back: 頂点データ
Next: ジオメトリモーフィング
VVVVはメッシュのサーフェス法線を表示するためのヘルパーモジュールを持っています: Normals (EX9)
法線を持ったメッシュの素敵な見た目を得るためにヘルプパッチを変更することができます:
もしメッシュが法線を持っていなければ、シェーダーにメッシュを渡す前に、パッチの中でそれらを計算するために、Normals (EX9.Geometry Mesh)ノードを使うことができます。頂点位置での法線を平均化するためにSmoothing Angleを使いましょう。
多くのシェーディングモデル(phongの様な)はビュー空間での法線を必要とします。それは頂点位置と連動して変形する必要があります。しかし、法線はfloat3またはfloat4で、法線のw成分は0(位置のための1の代わりに)で、移動ではなく回転だけが得られるということに注意しなければなりません。典型的な頂点シェーダーは次の様な変形を行います:
... //normal in view space Out.NormV = normalize(mul(NormO, tWV)); //position (projected) Out.PosWVP = mul(PosO, tWVP); ...
mr. wiggleや表示するための数式のチュートリアルの様に頂点シェーダーで頂点位置を変更する場合、法線の計算はもっと複雑になります。なぜなら頂点位置の移動は表面曲率を変えるからです。メッシュにあらかじめ保存された法線はもはや正しくありません。それゆえにシェーダーの計算は不適切になります。
だから、もしピクセルシェーダーで照明の計算が必要ならば、法線を再計算する方法を見つけなければなりません。しかしこれはとても明確な問題で、あなたが位置を移動した方法に依存します。
新しい頂点の法線を得るための最も一般的ですがそれほど正確ではない方法はすぐ傍らの追加の2つの位置を計算し、この頂点の接平面での2つのベクトルを得ます。そしてそれらは平行ではありません。2つの接線ベクトルから法線を計算するには外積を用います:
表示するための数式のチュートリアルから円錐の例を使えば次の様になります:
float NeighbourOffset = 0.001; vs2ps VS( float4 PosO : POSITION, float4 TexCd : TEXCOORD0) { //declare output struct vs2ps Out; //calc new position float3 p = Cone(PosO.xy); //calc neighbour pos in u direction float3 n1 = Cone(PosO.xy + float2(NeighbourOffset, 0)); //calc neighbour pos in v direction float3 n2 = Cone(PosO.xy + float2(0, NeighbourOffset)); //get tangent vector 1 float3 t1 = p - n1; //get tangent vector 2 float3 t2 = p - n2; //get normal float3 NormO = cross(t1, t2); //set new pos PosO.xyz = p; ...
では、vvvvのeffectsフォルダーからPhong関数が宣言されたPhongDirectional.fxhファイルを例として用いて、実際に法線を使ってみましょう。そのために、あなたのシェーダーのそばにファイルをコピーしてPhongDirectional.fxシェーダーの中のphongシェーディングを実行するために必要な行を見つけてください。ビュー空間に入る法線と照明とビュー方向を設置する必要があり、そしてそれら全てをvs2ps構造体の中に入れてピクセルシェーダーに渡す必要があります。素敵なシェーダーを設定するためにテクスチャのためのコードもコピーしましょう。'Cone'関数を全てのweb上で見つけることのできるuvパラメトリックサーフェスで単に置き換えることもできます。
// ---------------------------------------------------------------------------- // PARAMETERS: // ---------------------------------------------------------------------------- //transforms float4x4 tW: WORLD; //the models world matrix as via the shader float4x4 tV: VIEW; //view matrix as set via Renderer (EX9) float4x4 tP: PROJECTION; //projection matrix as set via Renderer (EX9) float4x4 tWV : WORLDVIEW; float4x4 tWVP: WORLDVIEWPROJECTION; //all 3 premultiplied //texture transformation marked with semantic TEXTUREMATRIX //to achieve symmetric transformations float4x4 tTex: TEXTUREMATRIX <string uiname="Texture Transform";>; //texture texture Tex <string uiname="Texture";>; sampler Samp = sampler_state //sampler for doing the texture-lookup { Texture = (Tex); //apply a texture to the sampler MipFilter = LINEAR; //sampler states MinFilter = LINEAR; MagFilter = LINEAR; }; //the data structure: "vertexshader to pixelshader" //used as output data of the VS function //and as input data of the PS function struct vs2ps { float4 Pos : POSITION; float2 TexCd : TEXCOORD0; float3 LightDirV: TEXCOORD1; float3 NormV: TEXCOORD2; float3 ViewDirV: TEXCOORD3; }; #include "PhongDirectional.fxh" // ---------------------------------------------------------------------------- // VERTEXSHADERS // ---------------------------------------------------------------------------- #define twopi 6.28318531 float2 Scale = 1; float2 Offset = 0; float3 Cone(float2 uv) { uv *= Scale; uv += Offset; float u = uv.x * twopi; float v = uv.y; float3 newPos; newPos.x = v * cos(u); newPos.y = v * sin(u); newPos.z = v; return newPos; } float NeighbourOffset = 0.001; vs2ps VS( float4 PosO : POSITION, float4 TexCd : TEXCOORD0) { //declare output struct vs2ps Out; //calc new position float3 p = Cone(PosO.xy); //calc neighbour pos in u direction float3 n1 = Cone(PosO.xy + float2(NeighbourOffset, 0)); //calc neighbour pos in v direction float3 n2 = Cone(PosO.xy + float2(0, NeighbourOffset)); //get tangent vector 1 float3 t1 = p - n1; //get tangent vector 2 float3 t2 = p - n2; //get normal float3 NormO = cross(t1, t2); //set new pos PosO.xyz = p; //put normal in view space and normalize it Out.NormV = normalize(mul(NormO, tWV)); //inverse light direction in view space Out.LightDirV = normalize(-mul(lDir, tV)); //inverse view dir in view space Out.ViewDirV = -normalize(mul(PosO, tWV)); //transform position (projected) Out.Pos = mul(PosO, tWVP); //transform texturecoordinates Out.TexCd = mul(TexCd, tTex); return Out; } // ---------------------------------------------------------------------------- // PIXELSHADERS // ---------------------------------------------------------------------------- float Alpha <float uimin=0.0; float uimax=1.0;> = 1; float4 PS(vs2ps In) : COLOR { float4 col = tex2D(Samp, In.TexCd); col.rgb *= PhongDirectional(In.NormV, In.ViewDirV, In.LightDirV); col.a *= Alpha; return col; } // ---------------------------------------------------------------------------- // TECHNIQUES: // ---------------------------------------------------------------------------- technique TFunctionWithPhong { pass P0 { VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_2_0 PS(); } }
TOC: エフェクトとシェーダー
Back: 頂点データ
Next: ジオメトリモーフィング
anonymous user login
~5h ago
~7d ago
~7d ago
~7d ago
~21d ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago