コンポジション
初級 プログラマー
継承システムに加えて、SDSL はコンポジション(composition) の概念を導入しています。コンポジションとは、別のシェーダークラスを型とするメンバーのことです。変数と同じように定義されます。
希望するシェーダークラスのインスタンス、または希望するシェーダークラスを継承したシェーダークラスのインスタンスを使って、構成することができます。
サンプルコード
shader CompositionBase
{
float4 Compute()
{
return float4(0.0);
}
};
shader CompositionShaderA : CompositionBase
{
float4 myColor;
override float4 Compute()
{
return myColor;
}
};
shader CompositionShaderB : CompositionBase
{
float4 myColor;
override float4 Compute()
{
return 0.5 * myColor;
}
};
shader BaseShader
{
CompositionBase Comp0;
CompositionBase Comp1;
float4 GetColor()
{
return Comp0.Compute() + Comp1.Compute();
}
};
コンポジションは、それ自身のコンテキストでコンパイルされます。これは、非ステージ変数はコンポジションの内部でのみアクセス可能であることを意味しています。コンポジションの中にコンポジションを持つことも可能です。
サンプルコード:ルートコンテキストにアクセスする
ルートのコンパイルコンテキストにアクセスしたい場合は、次の形式を使用します。
shader CompositionShaderC : CompositionBase
{
BaseShader rootShader = stage;
float4 GetColor()
{
return rootShader.GetColor();
}
};
これは、CompositionShaderC
で BaseShader
がルートコンテキストで利用可能であることを期待しているため、エラーになりやすい書き方です。
サンプルコード:コンポジションの配列
値の配列と同じ方法で、コンポジションの配列を作成することもできます。コンポジションがいくつあるかを事前に知る方法がないので、foreach
文を使って反復処理を行う必要があります。
shader BaseShaderArray
{
CompositionBase Comps[];
float4 GetColor()
{
float4 resultColor = float4(0.0);
foreach (var comp in Comps)
{
resultColor += comp.Compute();
}
return resultColor;
}
};
サンプルコード:ステージ(stage)の振る舞い
stage
キーワードの動作は単純です。変数やメソッドのインスタンスは1つだけ生成されます。
shader BaseShader
{
stage float BaseStageValue;
float NonStageValue;
};
shader TestShader : BaseShader
{
BaseShader comp0;
BaseShader comp1;
};
// resulting shader (representation)
shader TestShader
{
float BaseStageValue;
float NonStageValue;
float comp0_NonStageValue;
float comp1_NonStageValue;
};
サンプルコード:ステージメンバーの振るまい
shader BaseShader
{
stage float BaseStageMethod()
{
return 1.0;
}
float NonStageMethod()
{
return 2.0;
}
};
shader TestShader : BaseShader
{
BaseShader comp0;
BaseShader comp1;
};
// 結果のシェーダー(表現)
// resulting shader (representation)
shader TestClass
{
float BaseStageMethod()
{
return 1.0;
}
float NonStageMethod()
{
return 2.0;
}
float comp0_NonStageMethod()
{
return 2.0;
}
float comp1_NonStageMethod()
{
return 2.0;
}
};
コンポジションでも、ベースとなるメソッドを呼び出したり、オーバーライドしたりすることができることを覚えておいてください。オーバーライドは、コンポジションと同じ順番で行われます。
この動作は、複数のコンポジションで使われるけれども計算は一度だけでいい場合(例えば、ビュー空間の法線)に便利です。
クローン(clone)の振る舞い
clone
キーワードには、それほど些細な仕様はありません。これは、stage
キーワードが一意のメソッドを生成することを防ぎます。
shader BaseShader
{
stage float BaseStageMethod()
{
return 1.0;
}
stage float BaseStageMethodNotCloned()
{
return 1.0;
}
};
shader CompShader : BaseShader
{
override clone float BaseStageMethod()
{
return 1.0 + base.BaseStageMethod();
}
override float BaseStageMethodNotCloned()
{
return 1.0f + base.BaseStageMethodNotCloned();
}
};
shader TestShader : BaseShader
{
CompShader comp0;
CompShadercomp1;
};
// 結果のシェーダー(表現)
// resulting shader (representation)
shader TestShader
{
// cloned method
float base_BaseStageMethod()
{
return 1.0;
}
float comp0_BaseStageMethod()
{
return 1.0 + base_BaseStageMethod();
}
float BaseStageMethod() // in fact comp1_BaseStageMethod
{
return 1.0 + comp0_BaseStageMethod; // 3.0f
}
// not cloned method
float base_BaseStageMethodNotCloned()
{
return 1.0f;
}
float BaseStageMethodNotCloned()
{
return 1.0f + base_BaseStageMethodNotCloned(); // 2.0f
}
};
この動作は、単純な関数を異なるパラメーターで繰り返したい場合に便利です(例えば、別の関数の上に色を追加するなど)。