チュートリアル > MonoChrome RenderEffect の作成 |
MAXScript によって、Max SDK を使用して MSVC++ でコーディングされたプラグインと機能の点で類似するスクリプト プラグインを作成することができます。スクリプト可能なプラグイン クラスの 1 つは、RenderEffect クラスです。ここでは、レンダリングからカラーを削除するだけの非常に単純なプラグインを作成します。
全体の流れ: |
スクリプト RenderEffect を作成して、レンダリング後にレンダリングされたイメージを変更します。 |
イメージ内のすべてのラインおよび各ライン内のすべてのピクセルを巡回します。 |
各ピクセル内のカラー情報をモノクロ値に置き換え、アルファを維持します。 |
現在のラインとライン総数に基づいて、レンダラーの進行状況バーを更新します。 |
スクリプト プラグインは、コンストラクタの plugin で始まり、その後にスクリプト プラグインのスーパークラス( renderEffect )、プラグインのクラス名( MonoChrome )が続きます。 さらに、効果リスト内で表示される name と固有の classID を指定する必要があります。
シーンをロードするときにプラグインを識別するために、 classID が 3ds Max によって使用されます。新しい固有の ID を生成するには、リスナー内で GenclassID() メソッドを使用し、結果をスクリプト内にコピーすることができます。
ただし、このプラグインのすべてのバージョンが常に互換性を保つようにするには、この classID をコピーすることをお勧めします。
このプラグインにはコントロールがありません。ユーザに何をロード中かを示す、1 行のテキストだけを含んだ非常に単純なロールアウトを作成します。
renderEffect プラグインには、効果がイメージに適用されるたびに実行されるメイン ハンドラがあります。レンダラーのイメージ バッファが、唯一のパラメータとしてハンドラに渡されます。 r_image という名前のユーザ変数を使いますが、これに作業対象のイメージが含まれます。また、イメージの処理中にメイン レンダラーの進行状況バーを更新するために、進行状況のコールバック オブジェクトを定義します。
setTitle メソッドを progressCB オブジェクトで使用することで、[レンダリング効果](Rendering Effect)進行状況ウィンドウに表示される名前をそれぞれ定義します。[レンダリング プログレス](Renderer Progress)ウィンドウにそれぞれ表示される名前を定義します。前者の例では、「Currently Updating:MonoChrome Effect」という行が表示されます。後者の例では、「Current Task:MonoChrome Effect」という行が表示されます。
効果のメイン ループ中に[Esc]キーを押す操作を実際にスクリプトを中断しないで捕捉して処理できるようにするために、MAXScript のエスケープ キー処理を無効にする必要があります。この目的のために一時的なユーザ変数内にエスケープ処理の現在の状態( true または false )を格納し、次に false をエスケープ処理をコントロールしている MAXScript システムのグローバル変数に代入します。後で、メイン ループの終了後に、 oldEscapeEnable ユーザ変数内に元の状態を設定します。
レンダリングされたイメージの width が必要です。イメージの .width プロパティをユーザ変数の bmp_w に格納します。
レンダリングされたイメージの height も必要です。イメージの .height プロパティをユーザ変数の bmp_h に格納します。
イメージ内のすべてのラインをループで巡回します。イメージ ピクセルへのアクセスでは、0 を基点としたインデックス処理が必要です。 つまり、640x480 のイメージの左上の座標は[0,0]であり、右下の座標は[639,479]です。変数 y には、ループが繰り返されるごとに、0 からイメージの高さから 1 を引いた値が代入されます。
ユーザが[Esc]キーを押したときに進行状況コールバック オブジェクトの . progress メソッドが true を返し、それ以外の場合は false を返すので、戻り値をチェックして、 true が返された場合はループを終了させます。これで、 y ループの後の行に進みます。
同じメソッドが、進行状況の割合を計算するために必要な 2 つの引数、つまり現在の値と最大の値を受け入れます。この例では、現在の行と行の総数を指定します。たとえば、現在の行が 300 で、ビットマップには 600 行ある場合は、進行状況バーに 50% 終了と表示されます。
getpixels 関数は、指定されたファイルの Point2 の値で示された位置からピクセルを読み始め、最後の値で指定されたピクセル数を読み取ります。結果は、配列としてユーザ変数の pixel_line に代入されます。最初のピクセルから開始して左へ読み取り、すべての bmp_w ピクセルを読みます。 スキャンライン全体にイメージの幅に入るだけの数のピクセルが含まれています。
これで、ピクセル値の配列内ですべての値を巡回して調べることができます。MAXScript 内の配列は 1 を基点としているため、1 からイメージの幅まで数えます。
これが実際の中核となるコードです。 カラーの .Value プロパティ (グレースケール強度) を取得して、元のピクセルの .Value と等しい赤、緑、および青の値で新しいカラー値を生成します。アルファ チャネルに触れないように、元のアルファ値を RGBA カラーに追加するだけです。結果は配列内の同じ位置に格納するので、カラー情報がグレースケール バージョンで上書きされます。
スキャンラインのすべてのピクセルを処理した後に、 setpixels 関数で、新しいグレースケール値を含んだ配列の pixel_line を同じ位置から始まるイメージに書き戻します。これで、現在の行 y 内のカラーが上書きされます。
ループによる準備が完了し、ビットマップ全体が変更されました。 on apply ハンドラによって結果のビットマップがシステムに返され、仮想フレーム バッファ内に表示されます。
前に説明したように、レンダリング効果のループ前に MAXScript のエスケープ キーの処理を元の状態に設定する必要があります。
スクリプトを評価した後に、新しいプラグイン効果の 「MonoChrome」が、[レンダラー](Renderer) > [効果...](Effects...) > [追加...](Add...)に表示されます。それを効果のキューに追加して、シーンをレンダリングします。その結果、モノクロ バージョンでレンダリングされます。スクリプト renderEffects は、SDK を使用して作成された本物のプラグインと比較して低速ですが、非常に柔軟性があり、すばやくプロトタイプ化できます。
仮想フレーム バッファ内で、イメージのアルファ バージョンとモノクロ バージョンを調べることができます。アルファ バージョンは変更されておらず、モノクロ バージョンは renderEffect によって生成された RGB イメージと同じです。
この基本スクリプトの比較的簡単な変更は、ビットマップの N 番目の行だけを常に変更することです。for y ループに by 2 オプションを追加すると、常に 2 番目の行のみに影響を与えることになります。
x ループに by 2 を追加すると、ピクセルのグリッドのみに影響を与えることになります。2 よりも大きい値を使用することもできますし、ユーザ定義の行やピクセル ステップ用の UI コントロールを追加することもできます。
このスクリプトに対するもっと複雑な変更は、R、G、および B チャネル内のモノクロ値の異なるプロパティを使用した、モノクロ イメージへの着色です。そのためには、ロールアウトと 3 つの浮動小数点値を定義する paramBlock を追加し、ユーザが使用する各チャネル量を指定できるようにします。次に、p_v 値に 3 つの値を乗算し、それらの値をイメージの R、G および B の値に代入します。