2014年09月

2014年09月30日

2015の新機能を調べてみた その41 3dsmax 2015

前回作ったジオメトリシェーダーのコードをHLSL5で書き出して調べてみると、パスにジオメトリシェーダーが追加されているのが確認できる。

technique11 T0
<
 bool overridesDrawState = false;
 int isTransparent = 0;
>
{
 pass P0
 <
  string drawContext = "colorPass";
 >
 {
  SetVertexShader(
   CompileShader(vs_5_0, ShaderVertex()));
  SetGeometryShader(
   CompileShader(gs_5_0, ShaderGeometry()));
  SetPixelShader(
   CompileShader(ps_5_0, ShaderPixel()));
  SetHullShader(NULL);
  SetDomainShader(NULL);
 }

}

そしてジオメトリシェーダーがヴァーテクスシェーダーの後ろに入った事で、ヴァーテクスシェーダーの出力する頂点座標の座標系がワールド座標系になっている。

SHADERDATA ShaderVertex(APPDATA IN)
{
 SHADERDATA OUT;

        :

 float4 WorldPos = mul(OUT.Position, world);
 OUT.WorldPosition = WorldPos;
 OUT.Position = OUT.WorldPosition;

 return OUT;
}

これはヴァーテクスシェーダーのグラフの中の下の図の部分で切り替えている。ジオメトリシェーダーを加えたことで自動的に切り替わったことが確認できた。

fig01

そして以下がジオメトリシェーダー部分だ。

[maxvertexcount(3)]
void ShaderGeometry(
 triangle SHADERDATA INARRAY[3],
 inout TriangleStream<SHADERDATA> TriStream
)
{
 SHADERDATA OUT;

 for( int v = 0; v < 3; ++v )
 {
  OUT = INARRAY[v];
  float3 NormOp =
   normalize(OUT.Normal.xyz);
  float3 MulOp = (Offset * NormOp);
  float3 AddOp =
   (MulOp + OUT.Position.xyz);
  float4 VectorConstruct =
    float4(AddOp.x, AddOp.y, AddOp.z, 1.0);
  float4 MulOp1202 =
    mul(VectorConstruct, viewPrj);

  OUT.Position = MulOp1202;
  TriStream.Append( OUT );
 }
 TriStream.RestartStrip();
}

最初の行の「[maxvertexcount(3)]」でジオメトリシェーダには3つの頂点が渡されることになってるけど、前回使った「ジオメトリシェーダー」ノードにはこれを設定できるようなソケットもプロパティも何も無かった。だからこの辺は固定でやるしか無いみたいだね。さらにその3つの頂点についても、for文を使った形で順に処理されて「TriStream」ストリームに追加される部分は固定で、その中の処理部分だけがグラフから変更出来るようになっているようだ(上のコードの太字の部分)。前回作ったジオメトリシェーダーのグラフはこのfor文の中の処理になったわけだね。

fig10

でもこれじゃあせっかくのジオメトリシェーダーも活かしきれない感じだ。テッセレーションのところでも複数の頂点を組み合わせて処理するような部分は1つのノードにまとめられていて外からいじれなくなっていたよね。

例えば今回作ったジオメトリシェーダーは頂点を法線方向に移動させるものだけど、ポリゴンの法線方向に移動させる事が出来ればポリゴンのサイズを変える事無く広げる事が出来る。下の画像はその例で、球体がポリゴンごと分離して広がっている。

fig02

残念ながら今回作ったシェーダーでは頂点ごとの法線方向に移動するだけで、その法線は全て球体中心からの放射方向を向いているので球が膨張するだけになってしまう。

fig03

あえてやるなら「法線を編集」で

fig04

各頂点の法線をブレイクして面ごとに分けてやれば

fig05

このようにポリゴンサイズを変えずに広げる事が出来るようになるけど、法線がポリゴンごとになっちゃうからポリゴン内のスムージングが失われてしまう。

fig06

頂点の法線を変えずにポリゴンの法線方向に広げられたらこのようにスムージングは保ちながら広げる事が出来るわけだ。

fig07

それではまた次回。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2014年09月29日

modo801の新機能を調べてみた その39 modo801

今回はmodo801の新機能の次の「Poisson Cellular Texture: New cellular type procedural texture produces more regular pattern that can be seamlessly tiled.」を調べてみたい。

fig01

このアイテムは「テクスチャ」メニューに追加された項目で、

fig02

「Cellular」に似たパターンを生成するプロシージャルテクスチャーだ。パターンはこちらも「Cellular」同様に「鋭角」と「丸み」の2種類ある。

fig03

fig04

このテクスチャをUVマップにマッピングした場合、1X1の境界でパターンが連続するように調整され、継ぎ目が段差になったりしないようになる。もちろんラップパラメータを整数以外にしたらズレちゃうけどね。

fig05

こっちはパターンを「丸み」にした時のUVマップの境界付近。円のパターンが綺麗に繋がっている。

fig06

どうやらこのテクスチャはサーフェス上にポイントをランダムに生成し、その点を使って丸で塗りつぶしたり、そのポイントを使ったボロノイ図を描く方式をとっていて、それを描く時にマッピング座標を使っている感じみたいだ。だからUVマップを割り当てていればUVマップ上でペイントしてるから境界をまたいでペイントされるからズレないって感じなのかな。

パラメータも「Cellular」と大半は同じだ。パターンの値と地(フィラー)の値は「セル値」「セルの色」「アルファ」に対して「フィラー値」「フィラーの色」「アルファ」で設定する。

fig07

ディフューズカラーのように値がカラー値の時は「セルの色」と「フィラーの色」が使われ、

fig08

ディスプレイスメントマップのように値がグレースケールの場合は「セル値」と「フィラー値」が使われる。

fig09

さらにセル部分、フィラー部分のアルファ値が設定できる。

例えば下に画像マップを貼っておいて、

fig10

フィラー側のアルファを0%にするとフィラー部分が透明になって下地の画像が出てくる。

fig11

「タイプ」はセルの生成方法を切り替える。「セルの幅」はセルと地(フィラー)の割合を調整する。「遷移の幅」はセルと地(フィラー)の切り替わり部分のグラデーションを調整する。

fig12

下のGIFアニメは「タイプ」パラメータを「鋭角」と「丸み」で切り替えてみたもの。セルの中心位置はどちらも共通で、最初に中心点が生成されて、そこから丸が塗られるのか、ボロノイ図が描かれるのかが変わるだけなのがわかる。

fig13

下のGIFアニメは「遷移の幅」を0%にして「セルの幅」を0、50、100%に切り替えてみたものだ。セルと地(フィラー)の割合が変わるのがわかる。

fig14

今度は「セル幅」を50%にして「遷移の幅」を0、25,50,75,100%に切り替えてみた。数値が増えるにしたがってセルのまわりにグラデーションが広がるのがわかる。

fig15

わかりにくいのでディスプレイスメントマップでやってみた。

fig16

上のように「セル幅」50%でセルとセルの間が狭いと、遷移幅が広がるにしたがってグラデーションが互いに重なりあって0%の地(フィラー)が無くなって来る感じだ。下のGIFアニメは「遷移の幅」を100%にしておいて「セル幅」を0から100%まで切り替えてみたものだ。グラデーションが重なって地(フィラー)の部分が無くなっていくのがわかる。

fig17

「セル密度」は基準となるポイントの密度を調整する。「レベル」は生成したポイント間を分割してさらにその間にポイントを再帰的に作るステップ数を設定する。「ソリッド3Dセル」はONにするとテクスチャが三次元的に刻まれる。

fig20

下のGIFアニメは「セルの密度」を0、50、100%で変えてみたものだ。

fig18

同様に下のGIFアニメは「レベル」を0〜5まで変えてみたものだ。「セル密度」と違ってレベルが上がるたびにセルの大きさも分割されて小さくなっているのがわかる。また既存のポイントの間に新しいポイントが生成されて追加されていくのがわかる。レベルは0〜5まででそれより多くても少なくても変化しないようだ。

fig19

下の画像は「プロジェクションタイプ」を「ソリッド」にしてマッピングしてみたもの。ソリッドであっても平面投影になるのでパターンが間延びしたりしてしまう。

fig21

同条件で「ソリッド3Dセル」をONにするとパターンが三次元で生成されるので間延びしなくなった。

fig22

ただし部分的にセルとポリゴンの交差状態によっておかしなパターンが出てきてしまうようだ。頂点を動かしたりテクスチャロケータの位置を変えると部分的に解消したりはするようだ。

fig23

「輝度」はセルと地(フィラー)の明るさの差を調整するパラメータ。「コントラスト」はセルと地(フィラー)の間のグラデーションの変化を調整する。「色相のばらつき」「彩度のばらつき」「明度のばらつき」は各セルごとに色相、彩度、明度をランダムに変化させる変動値を設定する。

fig24

「輝度」はプラスの値の場合は地(フィラー)の値をセルの値に近づけるように働き、100%で地(フィラー)の値がセルの値に等しくなる。マイナスの値の場合は値が小さくなるほどセルの値が地(フィラー)の値に近づくように減少し、−100%でセルの値が地(フィラー)と等しくなる。下のGIFアニメは「輝度」を−100〜100%まで変化させてみたものだ。0%を挟んで変化する部分がセルと地(フィラー)で切り替わるのがわかる。

fig25

「コントラスト」も−100〜100%で変更してみた。

fig26

「色相のばらつき」や「彩度のばらつき」はもとの色に色がついていないとダメなので下のようにセルに色を設定して試してみた。

fig32

これが「色相のばらつき」を100%にしてみたもの。セルごとに色がランダムに変化しているのがわかる。

fig27

同じ条件でた「彩度のばらつき」を100%にしてみた。

fig28

同様には「明度のばらつき」を100%にしてみた。

fig29

最後は「プロファイルグラディエントを使用」だ。これはグラデーション部分をグラフで設定出来るようにするものだ。

こんな感じにグラフを変更してみると、

fig30

グラデーションの斜面がこのように変形した。

fig31

それではまた次回。

modo801ブログ目次



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)modo | CG

2014年09月26日

2015の新機能を調べてみた その40 3dsmax 2015

今回は簡単なジオメトリシェーダーを作ってみたい。

こんな感じで各頂点を法線方向に移動させる単純なものだ。

fig01

これを実現するには各頂点のワールド座標系に変換された法線ベクトルにオフセット量をかけて移動ベクトルを作って、各頂点のワールド座標系位置に加算してそれを新しい頂点の位置にしてやればいいね。

そこでまずShaderFXで「ツール」→「詳細モードを切り替え」で詳細モードに切り替えてから「Material」ノードグループを展開して、さらにその中の「ColorPass」ノードグループを展開する。ジオメトリシェーダーはこのグループ内に作成して「ColorPass」の「Geometry Shader」ソケットに接続する。

fig03

計算部分から作っていく。以下のノードを作成する。

「Hw Shader Nodes」→「Values」→「Float」

「Hw Shader Nodes」→「Inputs Common」→「Vertex World Normal」

「Hw Shader Nodes」→「Inputs Common」→「Vertex World Position」

「Hw Shader Nodes」→「Math」→「Multiply」

「Hw Shader Nodes」→「Math」→「Add」

そして下のように繋ぐ。

fig02

これで法線ベクトルを実数倍して位置ベクトルに加算する式が出来た。

「Float」ノードの名前を適当に設定して「Expose as Material Input」をONにして

fig04

DirectXShaderのパラメータロールアウトにこのパラメータが表示されるようにする。

fig05

さらに次のノードを作成して先に作った式のグラフに以下のように繋ぐ。

「Hw Shader Nodes」→「Values」→「Vector Construct」

「Hw Shader Nodes」→「Matrices」→「View Prj」

「Hw Shader Nodes」→「Math」→「Multiply」

fig08

ジオメトリシェーダーの出力はラスタライザに渡される。ラスタライザの入力は射影空間座標になってる必要があるのでここで変換するわけだ。変換はfloat4と4X4のマトリクスの乗算になる。入力がワールド座標だからそこからView変換Projection変換をすれば射影空間になるのでViewとProjectionの合わさった「View Prj」変換行列をかけてやるわけだ。

最後にこれらのグラフをジオメトリシェーダーにまとめ上げるために以下のノードを作成して接続する。

「Hw Shader Nodes」→「Core」→「TexCoord Output」

「Hw Shader Nodes」→「Core」→「Geometry Shader」

fig09

「TexCoord Output」ノードは以下のように設定する。

fig07

「Tweak texcoord」は1度定義されているTexCoordを使うための設定で、「SV_Position」はすでに定義されているのでこれに書き出すためにはこれを忘れずONにしておかないとならない。そして一連のグラフはジオメトリシェーダー内で行われてセマンティックが「SV_Position」でコード上のメンバ名「Position」に出力される。

全部出来たらグループ化しちゃうとスッキリするかもね。

fig10

あとはBOXにこのDirectXShaderを適用して、「ShaderFXを使用」をONにしてパラメータロールアウトの「Offset」の値を変えればポリゴンが浮いたりするはずだ。

それではまた来週。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2014年09月25日

modo801の新機能を調べてみた その38 modo801

前回に引き続き「Thin Film and Iridescent Materials: New physically based materials for simulating rainbow like diffraction effects. 」を調べてみたい。

「Iridescent Materials」は光が干渉したり回折したりして出来る虹色の光のにじみを生成する。

fig01

光の干渉は光の波が重なり合う事で光が強くなったり弱くなったりする現象で、光の回折は光がスリットなどを通り抜ける時に直進せずに広がろうとする現象だ。

同じ周波数の波が同じ周期で干渉すれば光は強くなるし、反対の周期で干渉すれば打ち消しあって弱くなる。

これら2つの現象はヤングの実験で確かめられる。

1つの光源がから出た光を2つのスリットに通して、その光をスクリーンに投影すると光源のスペクトルがスクリーンに現れるというものだ。

fig16

スリットを通った光は回折現象によってスリットの出口で広がる。そして出てきた2つの光はスクリーン上で再び重ねあわされる。この時2つの光の波の位相が揃っていれば光は強くなるし、そうじゃなければ打ち消しあって弱まる。2つの光の位相が揃うのは2つの光の行路差が光の波長の整数倍になっている時だ。だから波長によって行路差が整数倍になるスクリーン上の位置は異なり、それが虹色の干渉縞となって現れるわけだ。

この原理を使っているのが回折格子だね。

他にも自然の中には様々な形で光の干渉や回折を起こす状況が満ち満ちている。光の波長は可視光で400〜700nm程度だから行路差と言ってもとんでもなく僅かな距離しかないわけで、我々の眼で見たときの大雑把な距離に比べてとてつもなく小さい。この大雑把な目で見て行路差が僅かに生じるようなものが光の干渉や回折によって虹色の変色を起こすものなわけだ。

例えばシャボンの膜はとても薄くその表面で反射した光とまくの裏側で反射した光は僅かな行路差を生じる。これは膜の厚さにもよるし、視線の角度によっても生じる。

また光ディスクのように表面に細かい凹凸があるようなものも同様だ。

それは乱反射の光かも知れないし、鏡面反射の光かも知れないし、透過屈折光かも知れないわけだ。

このシェーダーは「ディフューズ」「スペキュラ」「反射」「透過」「ルミナンス」に対して回折や干渉の効果を作り出すものだ。

下の画像がこのシェーダーのプロパティだ。ディフューズやスペキュラなど各レイに対して影響する強度を調整することができる。

fig02

効果の特性は「虹色モード」によって「Interference(干渉)」モードと「Diffraction(回折)」モードの2種類が選べる。

これを切り替えると「波長」グラフの縦軸の意味が切り替わるようだ。マニュアルには以下のようにある。

Wavelength (波長) : 「虹色モード」が「回折」のときは、キーフレームの垂直位置が可視スペクトルの色に対応し、高さ方向にスペクトルが繰り返されます。「虹色モード」が「干渉」のときは、キーフレームの高さが 光路差 に対応し、干渉を引き起こします。配色が繰り返されるように見えますが、実際には繰り返しにはなっていません。

たぶん「回折」の時はサーフェスの視線に対する勾配に色をマッピングするだけで「干渉」の時は勾配を行路差に置き換えてそこから干渉を計算する方式なんじゃないかな?行路差が光の波長の整数倍と一致したらその光が強くなって色がでる。なんとなく両者の違いが無いようなあるような・・・w

「干渉」の方がより物理計算っぽい感じなのかな?

波長のグラフがこんな状態で、球体と平面を広角カメラで撮影してみた。

fig03

これが「干渉」モードで、

fig04

こっちが「回折」モードだ。

fig05

「回折」モードはカメラからのレイに対するサーフェスの法線の角度によって色が割り当てられてる感じだ。波長が長いと周波数は低くなるのでグラフの色は上が赤で下が青になる。そしてグラフの横軸はレイと法線の角度で0が平行で右に行くとだんだん角度が付いて来る感じかな。平面では手前の法がレイに対して角度が小さく、球体は真ん中が角度が小さい。周辺に行くほど角度が付いてくる。

グラフをこんな感じで波打たせて見ると

fig06

どちらも同じパターンが繰り返される縞模様になった。

fig07

fig08

今度は上下の範囲を超えるようなグラフにしてみた。

fig12

繰り返しのパターンはマイナスからプラスになるところで逆転している。そして「干渉」は波紋のようにパターンが減衰する感じのパターンになっているのに対して

fig13

「回折」の方は同じパターンが単純に繰り返されている感じだ。

fig14

このシェーダーもカスタムマテリアルのせいなのかレイヤーマスクやグループマスクがうまく働かないようだ。ただ、エフェクト側で0%にすると影響を0%に出来るので、エフェクト側でマスクすることは可能なようだ。

うまく使うと玉虫色の光沢が手軽に再現できそうだ。下の画像はベースマテリアルに反射を入れてそれに「Iridescent Materials」を作用されたもの。

fig15

それではまた次回。

modo801ブログ目次



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)modo | CG

2014年09月24日

2015の新機能を調べてみた その39 3dsmax 2015

「ShaderFX」の「Material」ノードの「Tessellation」ノードの働きとそれが出力するコードはだいたいわかってきた。でも結果として今のところ3dsmaxの「DirectXShader」からは「Tessellation」ノードは使えないみたいだな。

とにかくマニュアルくらいは何とかして欲しいな。

さて、DirectXではグラフィックの処理はパイプラインになっていて、今までやって来たヴァーテクスシェーダーとかハルシェーダーとかテッセレータとかをデータが流れて最終的にビューポートに出てくる。そのパイプラインを定義しているのがHLSLでは「パス」という概念で、そのパスを複数まとめたものが「テクニック」なわけだ。「Material」には3つのパスが定義されているんだけどこれもコードに書き出してみるとなぜか「ColorPass」しか出てこないんだよねぇ。で、この「ColorPass」の中に、

fig01

「Pass」ノードがあって、ここでパスが定義されている。そしてよーくこれを見ると「Geometry Shader」のソケットがある。

fig02

だから「Material」ノードにもジオメトリシェーダーを定義して追加する事が出来るようだ。

ジオメトリシェーダーはパイプラインの中ではテッセレーションとラスタライズの間に来る処理で、プリミティブ単位で処理が実行されて、頂点を加工したり頂点の数を増減させたり出来る。

ジオメトリシェーダの基本的な形はこんな感じだ。

[maxvertexcount(3)]
void ShaderGeometry(
 triangle SHADERDATA INARRAY[3],
 inout TriangleStream<SHADERDATA> TriStream)
{
 SHADERDATA OUT;

 for( int v = 0; v < 3; ++v )
 {
  OUT = INARRAY[v];

       :

  頂点の加工処理

       :

  OUT.Position = mul(OUT.Position, viewPrj);
  TriStream.Append( OUT );
 }
 TriStream.RestartStrip();
}

最初の行の「[maxvertexcount(3)]」はこのジオメトリシェーダーが出力する頂点の最大数の設定。

次の行はジオメトリシェーダーのファンクション名で名前の命名規則に従えばなんでも構わない。

ファンクションの引数は処理するプリミティブによって変わってくる。上のコードでは三角ポリゴンプ(triangle)リミティブを受け取って、三角形ストリーム(TriangleStream)を出力する設定だ。

三角形は頂点が3つだから入力引数の「INARRAY(名前は任意)」の配列の要素数は3だ。この頂点はヴァーテックスシェーダーかドメインシェーダーからワールド座標系で渡される。

あとは渡された3つの頂点から必要な三角形ストリームの頂点を生成して、順番に「TriStream(名前は任意)」ストリームに「Append()」で追加し、全部終わったら「RestartStrip()」でストリームを呼び出して現在のストリームに対する追加を終了させて、新たなストリームを作成する。これで次にAppendしても追加されるのは新しいストリームになるらしい。

また、パイプラインのジオメトリシェーダーの次はのラスタライザで、ラスタライザは射影空間の頂点座標(SV_POSITION)が必要なので、頂点座標は最後にワールド座標を射影空間に変換する行列をかけて射影空間座標として三角形ストリームにアペンドする必要があるよ。下の式の「viewPrj」がワールド座標を射影空間座標に変換する行列だ。

OUT.Position = mul(OUT.Position, viewPrj);

だから上のコードは「頂点の加工処理」が無ければ単に3つの頂点を順に射影空間に変換してストリームに出力する処理をすることになるね。

それではまた次回。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG
Archives