Houdini 18.5 マテリアル

GLSLでカスタムビューポートシェーダを記述する方法

On this page

概要

OpenGLシェーダは、GLSL(OpenGLシェーダ言語)を使って記述します。OpenGLシェーダを作成するためには、GLSLとそれに関連する概念(例えば、頂点シェーダとフラグメントシェーダ)を理解する必要があります。

ビルトインのビューポートシェーダと色々なOpenGLプロパティとしてマテリアルのタグパラメータを使用する方が簡単です。 しかしながら、代わりに独自のGLSLシェーダを記述したい場合には、以下の情報が役に立ちます。

GLSLのプログラミングに関する詳細は、OpenGL GLSLドキュメントを参照してください。

新しいGLSLシェーダノードの作成

GLSLシェーダの作成には、新しいSHOPタイプの作成が必要です。現在のところ、VOPsを使ってGLSLシェーダを作成することはできません。

Tip

別の方法として、GLSLシェーダソースをテキストファイルに保存して、ogl_glsl_shaderプロパティを使用することで、あなたのマテリアルからそのファイル名を参照することができます。

  1. File ▸ New operator type を選択します。

  2. VOP Type をクリックします。

  3. Network Type メニューから GLSL Shader を選択します。

  4. シェーダの内部名となる Name と人が解読できる Label を入力します。

  5. Accept をクリックします。その新しいシェーダタイプのType Propertiesウィンドウが表示されます。

  6. Code タブをクリックします。このノードでは、何かしらのデフォルトのシェーダコードが初めから記述されています。このコードをシェーダ作成の起点として使用することができます。

    Code タブには、GLSLコードを扱うための単純なエディタが備わっています。このエディタには4つのテキストボタンがあります: 頂点シェーダ用、オプションのジオメトリシェーダ用、フラグメントシェーダ用、コンパイラ出力用。 3つのペイン間の分割線をドラッグすることで、それらのペインのサイズを変更したり、単一ペインを最大化することができます。

  7. デフォルトのコードをコンパイルしてみたいので、 Test compile をクリックします。コンパイラの出力が3番目のペインに表示されます。

OpenGLシェーダの適用

To...Do this

ビューポートにのみGLSLシェーダを割り当てる

オブジェクトのサーフェスシェーダをGLSLシェーダのインスタンスに設定するか、または、GLSLシェーダのインスタンスをマテリアル内部のサーフェスカラー出力に接続します。

ビューポートにGLSLシェーダ、レンダリングにシェーダを割り当てる

  • GLSLシェーダタイプにはGLSLシェーダコード、VEX/RenderManコードを両方とも定義することができます。Houdiniは、ビューポートにGLSLコードを、レンダリングにVEX/RenderManコードを使用します。

    Code タブ上のギアメニューをクリックして、 VEX/RenderMan shader を有効にします。これは、VEXまたはRenderManシェーダコードを記述可能なもう1つのタブを作成します。

  • Selectシェーダノードを使用することで、OpenGLシェーダとVEXサーフェスシェーダの両方ともマテリアルのサーフェスカラー出力に接続することもできます。

独自のGLSLシェーダを既存マテリアルに割り当てる

  • マテリアルのパラメータダイアログのギアメニューの Edit Rendering Parameters からGLSL Shaderパラメータを追加します。このパラメータは、SHOP/OGLサブフォルダの中にあります。

  • プログラム記述ファイル(.prog)のファイル名またはスペース区切りでシェーダファイルのリストを入力します。プログラムファイルの書式は、下記で説明しています。シェーダファイルのファイル拡張子がシェーダステージを定義しています:

    • .vert: 頂点シェーダ

    • .frag: フラグメントシェーダ

    • .geom: ジオメトリシェーダ

    • .tcs: Tessellation Control Shader (GL4.0+)

    • .tes: Tessellation Evaluation Shader (GL4.0+)

Houdiniビルトイン関数

フラグメントシェーダ関数

void HOUassignLitOutput(vec3 point_color,vec3 emit,vec3 amb,vec3 diff,vec3 spec,vec4 wire,float alpha,float selected)

ライティングコンポーネントを合成し、Houdiniシェーディング(例えば、ゴースト)を適用し、その結果をNormalライティングモード(glH_MaterialPassが0)でフラグメントシェーダに割り当てます。 Normalライティングレンダラーは、フォワードレンダラー(すべてのシェーディングピクセルに対してすべてのライティングが計算されます)です。

void HOUassignMaterialOutput(vec3 point_color,vec3 emit_color,vec3 amb_color,vec3 diff_color,vec3 spec_color,float alpha,float emit_alpha,float shiny,vec4 wire,vec3 nN,float z,float selected)

High Qualityライティングモード(glH_MaterialPassが1)用にライティングコンポーネントをg-buffer出力に割り当てます。 High Qualityライティングレンダラーは、デファードシェーディングレンダラー(ライティングとシェーディングに必要なすべてのパラメータが複数バッファに格納され、すべてのジオメトリがレンダリングされた後にライトが処理されます)です。

void HOUapplyLightMaps(inout vec3 nN, inout vec3 mspec, inout float shiny,bool has_bump_map, bool has_spec_map, vec2 bumpCoords, vec2 specCoords, float bumpScale, int bumpComps, bool bumpBias, bool bumpInvert, vec2 bumpMapSize, bool specularShinyAdjust, vec2 shinyRange)

スペキュラー、バンプ、法線のマップから法線(nN)、マテリアルスペキュラーカラーコンポーネント(mspec)、マテリアルの輝かしさ(shiny)を計算します。

void HOUfastLightingModel(in vec3 P,in vec3 nN,inout vec3 lAmb,inout vec3 lDiff,inout vec3 lSpec,in float sh)

最初の3個のシーンライト(またはヘッドライト)を使って、aAmblDifflSpec(アンビエント、ディフューズ、スペキュラー)のライティングコンポーネントを計算します。 これは、Normalライティング(glH_MaterialPassが0)のレンダリングでのみ使用してください。

void HOUlightingModel(in vec3 P,in vec3 nN,inout vec3 lAmb,inout vec3 lDiff,inout vec3 lSpec,in float sh)

HOUfastLightingModelと同じ方法でライティングコンポーネントを計算しますが、これは最初の9個のシーンライト(またはヘッドライト)を使用します。 これは、Normalライティング(glH_MaterialPassが0)のレンダリングでのみ使用してください。

float HOUwireAlpha(vec3 edgedist, int edgeflag, float cut)

3つの三角形エッジ(x,y,z)すべてに対してエッジ距離とフラグを、その直線の内側(非アンチエイリアス)部分に対してカットオフ許容値を指定すると、 レンダリングされる三角形内側のピクセルのアルファを計算します。 これは、glH_WireThicknessに基づいてアウトライン化された三角形を作成します。

vec4 HOUwireColor(vec3 edgedist, int edgeflag, float selected)

HOUwireAlpha()と同様に、これは、三角形をアウトライン化するためのワイヤーカラーとアンチエイリアスを計算します。 選択したパラメータは、glH_SelectionColorglH_WireColorを混ぜることができます。

ジオメトリシェーダ関数

vec3 HOUedgeDistance(vec4 v0, vec4 v1, vec4 v2, out int edges))

テセレーションされたポリゴン内の三角形のクリップ空間に3つの頂点を指定すると、 フラグメントシェーダでHOUwireColor()またはHOUwireAlpha()を使用するためのエッジフラグ(edges)とエッジ距離(戻り値)を計算します。 エッジ距離の単位はスクリーンピクセルです。エッジフラグは、エッジが内側エッジ(0。ポリゴンと交差する)なのか外側エッジ(1。ポリゴンエッジ上)なのかを示す整数のビットです。 エッジビットは、1 (v1-v2), 2 (v0-v2), 4 (v0-v1)です。

int HOUedges(vec4 v0, vec4 v1, vec4 v2)

HOUedgeDistance()の簡易版。これは、テセレーションされたポリゴン内の三角形のエッジフラグのみを返します。

bool HOUfrustumCull(vec4 v0, vec4 v1, vec4 v2)

(クリップ空間内の)v0, v1, v2の頂点を持つ三角形が現在のビューイングフラスタムの外側にあればtrueを返します。 これは高速チェックで、実際にビューイングフラスタムの外側にある場合でもfalseを返すことがあります。 ビューイングフラスタムの内側にある三角形はどのような場合でも決してtrueを返しません。

int HOUprimitiveID(out ivec3 vertices)

現在の三角形、直線、ポイントのプリミティブIDを返します。 verticesパラメータは、テクスチャまたはテクスチャバッファのオブジェクト内に格納されているVertexアトリビュートにアクセスするための頂点インデックスを返します。

int HOUprimitiveIDEdges(out ivec3 vertices, out int edgeflags)

これは、HOUprimitiveID()HOUedges()の組み合わせです。 プリミティブインデックス、HOUprimitiveID()と同じ頂点インデックス、HOUedges()と同じエッジフラグを返します。 これは、両方の関数をコールするよりも若干高速です。

int HOUvertexID(out ivec3 vertices)

現在の三角形に関するいくつかの情報が入ったビットフィールドを返し、verticesをポリゴンのローカル頂点番号(常に0からポリゴン頂点数-1の範囲)に設定します。 これは、アトリビュート内の頂点オフセット(0からDetail頂点数-1の範囲)を返すHOUprimitiveID()verticesとは異なります。 戻り値のビットフィールドには、現在の三角形の以下のポリゴンテセレーション情報が入っています:

  • 0×01: ポリゴン内の最初の三角形

  • 0×02: ポリゴン内の中間の三角形

  • 0×04: ポリゴン内の最後の三角形

  • 0×08: ポリゴンに奇数個の三角形が入っています。

  • 0×10: このポリゴン内でvertex 1がまだ使用されていません。

  • 0×20: このポリゴン内でvertex 2がまだ使用されていません。

  • 0×40: このポリゴン内でvertex 3がまだ使用されていません。

このビットフィールドを使用することで、プリミティブと頂点のデコレーションの位置を決めたり、ポリゴンの重心を評価することができます。

Houdini自動ユニフォーム

Houdiniは、すべてのシェーダステージで使用可能な以下の(すべてglH_から始まる)ユニフォームの値を自動的に生成します。

glH_MaterialPass

レンダリングされている現在のパスを格納している整数。これらのパスは以下のとおりです:

  • 0 - Normalライティングパス

  • 1 - High Qualityライティングパス

  • 3 - Shadow Mapパス

ライティング計算は、glH_MaterialPassが0の場合にのみ実行してください。 基本マテリアルプロパティ(ディフューズ、アンビエント、スペキュラー、エミッション)のみがPass #1に対して用意する必要があります。 Pass #3はアルファとデプスのみを必要とします。 Pass #2は、古いH11ビューポートと共に廃止されました。

glH_ViewMatrix

ビューマトリックス(OpenGLのmodelviewマトリックスと混同しないでください)。 ビューマトリックスは、オブジェクトがglH_ObjectMatrixになっている時にのみビューポートタンブルトランスフォームになります。

glH_InvViewMatrix

ビューマトリックスの逆行列(OpenGLのmodelviewマトリックスと混同しないでください)。

glH_ObjectMatrix

ジオメトリのオブジェクトトランスフォーム。

glH_ProjectMatrix

カメラ空間座標をクリップ空間座標に変換する時に使用するトランスフォーム(これは、X,Y,Zに対して[-1,1]です)。

glH_InvProjectMatrix

投影マトリックスの逆行列。これは、クリップ座標をカメラ空間に戻すのに使用します。

glH_NumSamples

マルチサンプル(2x, 4x, 8× AA)バッファ内のサンプル数。

glH_LightingEnabled

ライティングが有効なら1、無効なら0の整数。

glH_LightMask

有効なライトのint32ビットマスク。1番目のシーンライトが1ビット目、2番目のシーンライトが2ビット目(0×2)、3番目のシーンライトが3ビット目(0×4)など。

glH_ScreenSize

レンダリングされているビューポートの現在の寸法を含んだvec2。

glH_WireOver

ワイヤーフレームがモデルに対して描画されている時は1、描画されていない時は0に設定される整数。

glH_WireColor

ワイヤーフレームオーバーレイの単色カラー。これは、選択、テンプレート描画、ゴーストに基づいてカラーが変わります。

glH_WireThickness

Display Optionsの設定に基づいた現在のワイヤーの太さ。これは、選択状態に応じて変わります。

glH_ConstColor

Hidden Line InvisibleやGhostなどの描画モードの単色カラー。

glH_IsOrtho

ビューポートがパースペクティブなら0、正射投影なら1に設定される整数。

glH_SelectMode

現在のコンポーネント選択表示モード:

  • 0: 何も選択されていません

  • 1: プリミティブがいくつか選択されています

  • 2: プリミティブがすべて選択されています

  • 3: ポイントがいくつか選択されています

  • 4: ポイントがすべて選択されています

  • 5: 頂点がいくつか選択されています

  • 6: 頂点がすべて選択されています

ポイント、プリミティブ、頂点のグループ選択は、それぞれポイント、プリミティブ、頂点が選択されているものと見なされます。

以下のユニフォームが利用可能ですが、一般的には、ビルトインのHoudini関数のHOUassign()ファミリーでのみ使用します。 それらの関数を使用しない場合(推奨しません)、それらのコンポーネントを乗算して、ゴーストカラーを適用し、選択ハイライトを処理し、透明度に対して両面ライティングを処理する必要があります。

glH_Emission

エミッションがこのパスで使用されていれば1.0、使用されていなければ0.0の浮動小数点。

glH_Specular

スペキュラーがこのパスで使用されていれば1.0、使用されていなければ0.0の浮動小数点。

glH_Diffuse

ディフューズがこのパスで使用されていれば1.0、使用されていなければ0.0の浮動小数点。

glH_Ambient

アンビエントがこのパスで使用されていれば1.0、使用されていなければ0.0の浮動小数点。

glH_GhostColor

'ghost other objects'表示モードのゴーストカラーを表現したvec4。 これは、現在のオブジェクトがゴーストかどうかに関係なく設定されますが、 オブジェクトがゴーストでない場合には、そのカラーは(0,0,0,0)になります。

glH_SelectColor

現在の選択カラー。これは、選択タイプ(オブジェクト、コンポーネント、クロージャ、セカンダリ)に応じて変わります。

glH_AlphaPass

透明度パスがアクティブな時は1、そうでない時は0の整数。 透明度パスは常にライトの方を向いたポリゴンフェースをライティングします。 これは、HOUlightingModel()HOUdiffuse()HOUlightDiffSpec()のライティングメソッドで使用されます。

コードディングのガイドライン

Houdiniのビューポートレンダラーは、ユーザが変更可能な膨大な数の表示設定を持っています。 いくつかのケースでは、ビューポートレンダラーは特定の視覚的効果を作成できるように複数パスをレンダリングします。 例えば、射影テクスチャとシャドウはどちらとも複数パスを必要とします。

Houdiniの色々なレンダリングモードと互換性を持たせるために、GLSLシェーダを以下のガイドラインに沿わせてください:

  • フラグメントシェーダのカラー出力を割り当てる時は、HOUassign...()メソッドのどれかを使用してください。

  • HOUlightingModel()HOUdiffuse()HOUlightDiffSpec()を使用してGLライティングを行なってください。 そうしない場合は、有効な光源からのライト寄与のみを追加してください。 どのライトが有効になっているのかを確認する時は、glH_LightEnabledまたはglH_LightMaskのユニフォームを使用してください。

マルチパスビューポートレンダー

HoudiniでGLSLシェーダを記述する時は、そのシェーダが実行されるコンテキストを理解しておくと役に立ちます。 glH_MaterialPassユニフォームを使用することで、そのパスを照会することができます。

Normal Lighting Pass (0)

アンビエント、ディフューズ、エミッションのコンポーネントすべてをフルライティングで計算することができます。 これは、Houdiniのライティング機能またはシェーダによって行なうことができます。

High Quality Lighting Pass (1)

マテリアルのRawのアンビエント、ディフューズ、スペキュラー、エミッションのコンポーネントが定義されますが、何のライティング計算も適用されません。 シェーダをHigh Qualityライティングに関わらせたくない場合、ライティング計算を実行して、それをエミッションコンポーネントに割り当ててください。

Pass value #2は廃止されました。

Shadow Map Pass (3)

シャドウマップが作成されます。デプスとアルファの値のみが使用されるので、カラーに対するすべての計算を回避することができます。

シェーディングをする時、透明度パスがレンダリングされていればglH_AlphaPass変数には1が設定されます。 マテリアルに透明度を使用していてglH_AlphaPassが0である場合、または、マテリアルが不透明でglH_AlphaPassが1である場合、フラグメントを破棄することができます。

透明度

OpenGLビューポートレンダラーは、透明マテリアルと不透明マテリアルを区別します。 ディフューズまたは不透明のテクスチャ、ogl_alphaまたはogl_alpha_perpのパラメータ、Alphaジオメトリアトリビュートから透明度が生じていない場合には、 適切に透明オブジェクトをレンダリングできるように、レンダラーへのヒントをシェーダ側で用意しなければなりません。 マテリアルがアルファパスを必ず受信できるようにするために、ogl_alpha_shaderパラメータ(Edit Rendering Parameters,SHOP / OGL)をマテリアルまたはSHOPに追加してください。

OpenGL GL 3.3 Core Principals

ビューポートは、ジオメトリの更新パフォーマンスを良くするために、たくさんの役割をGPUに押し付けます。 これをすると、ジオメトリシェーダなどのシャーダの一部が若干複雑になります。 ジオメトリシェーダは、プリミティブと頂点のアトリビュートを検索するのに必要です(頂点シェーダは、頂点アトリビュートしか検索できません)。

さらに、GLSLビルトインは廃止されました。これらのビルトインには、GLライティングユニフォーム、トランスフォームマトリックス(gl_ProjectionMatrix, gl_ModelviewMatrix)、 事前定義された頂点シェーダの入力と出力(glVertex, glNormal, glColor, gl_MultiTexCoord#, gl_TexCoord[])が含まれていました。 今では代わりに、すべての情報をユニフォーム、ユニフォームブロック、Houdiniアトリビュート名に相当する名前付き頂点入力(P, Cd, Alpha, N)を介して渡します。

上記にリストされているglH_ Houdiniユニフォームのほかに、ビューポートはユニフォームブロックも認識します。 どのシェーダステージでも利用可能なユニフォームブロックの数に制限があります(COMBINED_VERT_UNIFORM_BLOCKSとその他に関するOpenGLの情報は、 Help ▸ About Houdini とShow Detailsを参照してください)。

マテリアルユニフォームブロック

Houdiniマテリアルの定義。これは、どのシェーダステージでも使用することができます。

layout(std140) uniform material
{
    vec3            ambient_color;
    vec3            diffuse_color;
    vec3            emission_color;
    vec3            specular_color;
    float           material_alpha;
    float           material_alpha_parallel;
    float           shininess;
    bool            has_diffuse_map;

    bool            has_bump_map;
    int             bumpComps;
    vec2            bumpMapSize;
    bool            bumpBias;
    bool            bumpInvert;
    float           bumpScale;

    bool            has_spec_map;
    bool            specularShinyAdjust;
    vec2            shinyRange;

    bool            has_env_map;
    float           envScale;
    mat3            envRotate;
};

uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform sampler2D specularMap;

ライトユニフォームブロック

シーンライトに関する基本情報。複数ライトの名前の最後に0から9の数値を付けることができます。 そのライトが寄与しているかどうかを確認するには、glH_LightMaskをチェックします。

layout(std140) uniform light0
{
    vec3        pos;
    vec3        dir;
    vec3        atten;
    vec3        amb;
    vec3        spec;
    vec3        diff;
    float       coscutoff;
    bool        point;
} lightSource0;

プログラムファイルフォーマット

Houdiniは、.progファイルを使ってカスタムシェーダを読み込むことができます。 .progフォーマットは、命令とファイルを記述したテキストベースのリストです。 以下がその例です:

#name Simple Surface Shader

#version 150
#input P 0
#input N 1
#input Cd 2
#input Alpha 3
#output color 0

surface/simple.vert
surface/simple.frag

#name命令には、シェーダの名前を指定します。これは任意です。指定しなかった場合、.progファイル名がシェーダの名前になります。

#version命令は、このシェーダが使用するGLSLバージョンを定義します。これは、GLSL命令と同じですが、core, compatibility, esの修飾子が許可されていません。 この命令は、読み込むファイルセットを定義した値を変えて何度も定義することができます。 この実装に対応している最も値が高いバージョンのシェーダファイルが読み込まれます。シェーダファイルを指定する前に最低でも1つの#version命令がなければなりません。

#extension命令は、シェーダセットを受け入れるために存在しなければならないOpenGLエクステンションを定義します。 このパラメータには、使用するGLエクステンションの名前を正確に指定しなければなりません。例えば、GL_ARB_sample_shadingまたはGL_EXT_framebuffer_objectです。 同じシェーダセットに対して複数の #extensions を指定しても構いませんが、シェーダセットが読み込めるように、それらのシェーダセットすべてが存在しなければなりません。 新しい#version命令は、必須のエクステンションのリストをクリアします。

#input命令は、一般的な頂点アトリビュートを特定のアトリビュートインデックスにバインドします。 一般的な頂点アトリビュートだけを割り当てることができ(gl_ で始まるGLビルトインをバインドすることはできません)、且つ、有効インデックスのみに割り当てることができます(0からGLがサポートしている最大インデックス。通常では15)。 これは、GL_ARB_explicit_attribute_locationエクステンションと同様の機能を備えています。 これらの命令は、任意で、 #version 命令の後に指定しなければならず、新しい #version 命令に遭遇した時にクリアされます。

#hou_attrib_map命令もあります。この命令は、Houdiniで知られているアトリビュートを標準のバインドロケーションに割り当てます:

P = 0 (vec3)
Cd = 1 (vec3)
Alpha = 2 (float)
N = 3 (vec3)
uv = 4 (vec2)
pointScale = 5 (float)
pointSelection = 6 (int)
pointID = 7 (int)
instIndex = 8 (int)

他の一般的なアトリビュートすべてがアトリビュートロケーション9から割り当てられます。

#output命令は、名前の付いたフラグメントシェーダ出力を特定の描画バッファインデックスにバインドします。 この命令は、任意で、 #version 命令の後に指定しなければならず、新しい #version 命令に遭遇した時にクリアされます。 これは、シェーダが2つ以上の値を異なる描画バッファ/テクスチャに出力するのに役立ちます。

#define命令は、定義した記号をシェーダに渡します。

シェーダファイル自体は、HOUDINI_GLSL_PATH(デフォルトパスの値はHOUDINI_PATH/glsl)から読み込まれます。 これらのファイルは特定の拡張子が付いていなければなりません。 つまり、頂点シェーダなら.vert、ジオメトリシェーダなら.geom、テセレーションコントロールシェーダ(GL4.0+)なら.tcs、テセレーション評価シェーダ(GL4.0+)なら.tes、フラグメントシェーダなら.fragです。

最後に、行の頭を//で始めることで、コメントを指定することができます。命令またはシェーダファイル名と同じ行にコメントを指定することはできません。

トラブルシューティング

ジオメトリが不可視になっている

  • いくつかのGLSLシェーダには、頂点アトリビュートを渡す必要があります(例えば、接線空間法線マップシェーダ)。必ず正しいデータを渡してください。

  • 頂点位置が適切に計算されていない。

ジオメトリが赤い縞々で描画されている

  • 必ずGLSLシェーダをコンパイルしてください。その赤い縞々は、シェーダが適切にリンクできていないことを示しています。

  • シェーダノードを右クリックして、 Type Properties を選択します。 Code タブをクリックします。 Test compile をクリックしてシェーダコードのコンパイルを試みて、エラーがないかチェックしてください。

ジオメトリにシャドウが落ちない

いくつかのシェーダは発光するのでシャドウを反映しません(例えば、デカールシェーダ)。そのようなシェーダは、仕様上、シャドウを受けません。

マテリアル

マテリアルの使い方

テクスチャとUV

マテリアルの作成

導師レベル

他のレンダラー