チュートリアル - MonoChrome RenderEffect の作成

チュートリアル > MonoChrome RenderEffect の作成

MAXScript によって、Max SDK を使用して MSVC++ でコーディングされたプラグインと機能の点で類似するスクリプト プラグインを作成することができます。スクリプト可能なプラグイン クラスの 1 つは、RenderEffect クラスです。ここでは、レンダリングからカラーを削除するだけの非常に単純なプラグインを作成します。

関連トピック:

スクリプト プラグインおよび RenderEffect

ピクセル値の取得/設定

RenderEffect 進行状況コールバック機能

全体の流れ:

スクリプト RenderEffect を作成して、レンダリング後にレンダリングされたイメージを変更します。

イメージ内のすべてのラインおよび各ライン内のすべてのピクセルを巡回します。

各ピクセル内のカラー情報をモノクロ値に置き換え、アルファを維持します。

現在のラインとライン総数に基づいて、レンダラーの進行状況バーを更新します。

MAXScript

plugin RenderEffect MonoChrome
name:"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(
rollout about_rollout "About..."
(
  label about_label "MonoChrome Filter"
)
on apply r_image progressCB: do
(
  progressCB.setTitle "MonoChrome Effect"
  local oldEscapeEnable = escapeEnable
  escapeEnable = false
  bmp_w = r_image.width
  bmp_h = r_image.height
  for y = 0 to bmp_h-1 do
  (
    if progressCB.progress y (bmp_h-1) then exit
    pixel_line = getPixels r_image [0,y] bmp_w
    for x = 1 to bmp_w do
    (
      p_v = pixel_line[x].value
      pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
    )--end x loop
    setPixels r_image [0,y] pixel_line
  )--end y loop
  escapeEnable = oldEscapeEnable
)--end on apply
)--end plugin

ステップごとの解説:

plugin RenderEffect MonoChrome
name:"MonoChrome"
classID:#(0x9e6e9e77, 0xbe815df4)
(

スクリプト プラグインは、コンストラクタの plugin で始まり、その後にスクリプト プラグインのスーパークラス( renderEffect )、プラグインのクラス名( MonoChrome )が続きます。 さらに、効果リスト内で表示される name と固有の classID を指定する必要があります。

シーンをロードするときにプラグインを識別するために、 classID 3ds Max によって使用されます。新しい固有の ID を生成するには、リスナー内で GenclassID() メソッドを使用し、結果をスクリプト内にコピーすることができます。

ただし、このプラグインのすべてのバージョンが常に互換性を保つようにするには、この classID をコピーすることをお勧めします。

スクリプト化されたプラグイン

スクリプト RenderEffect プラグイン

classID

rollout about_rollout "About..."
(
label about_label "MonoChrome Filter"
)

このプラグインにはコントロールがありません。ユーザに何をロード中かを示す、1 行のテキストだけを含んだ非常に単純なロールアウトを作成します。

ロールアウト句

Label

on apply r_image progressCB: do
(

renderEffect プラグインには、効果がイメージに適用されるたびに実行されるメイン ハンドラがあります。レンダラーのイメージ バッファが、唯一のパラメータとしてハンドラに渡されます。 r_image という名前のユーザ変数を使いますが、これに作業対象のイメージが含まれます。また、イメージの処理中にメイン レンダラーの進行状況バーを更新するために、進行状況のコールバック オブジェクトを定義します。

スクリプト RenderEffect プラグイン

RenderEffect 進行状況コールバック機能

progressCB.setTitle "MonoChrome Effect"

setTitle メソッドを progressCB オブジェクトで使用することで、[レンダリング効果](Rendering Effect)進行状況ウィンドウに表示される名前をそれぞれ定義します。[レンダリング プログレス](Renderer Progress)ウィンドウにそれぞれ表示される名前を定義します。前者の例では、「Currently Updating:MonoChrome Effect」という行が表示されます。後者の例では、「Current Task:MonoChrome Effect」という行が表示されます。

RenderEffect 進行状況コールバック機能

local oldEscapeEnable = escapeEnable
escapeEnable = false

効果のメイン ループ中に[Esc]キーを押す操作を実際にスクリプトを中断しないで捕捉して処理できるようにするために、MAXScript のエスケープ キー処理を無効にする必要があります。この目的のために一時的なユーザ変数内にエスケープ処理の現在の状態( true または false )を格納し、次に false をエスケープ処理をコントロールしている MAXScript システムのグローバル変数に代入します。後で、メイン ループの終了後に、 oldEscapeEnable ユーザ変数内に元の状態を設定します。

bmp_w = r_image.width

レンダリングされたイメージの width が必要です。イメージの .width プロパティをユーザ変数の bmp_w に格納します。

bmp_h = r_image.height

レンダリングされたイメージの height も必要です。イメージの .height プロパティをユーザ変数の bmp_h に格納します。

bitmap.height

for y = 0 to bmp_h-1 do
(

イメージ内のすべてのラインをループで巡回します。イメージ ピクセルへのアクセスでは、0 を基点としたインデックス処理が必要です。 つまり、640x480 のイメージの左上の座標は[0,0]であり、右下の座標は[639,479]です。変数 y には、ループが繰り返されるごとに、0 からイメージの高さから 1 を引いた値が代入されます。

for ループ

if progressCB.progress y (bmp_h-1) then exit

この行では 2 つの動作が行われます。

ユーザが[Esc]キーを押したときに進行状況コールバック オブジェクトの . progress メソッドが true を返し、それ以外の場合は false を返すので、戻り値をチェックして、 true が返された場合はループを終了させます。これで、 y ループの後の行に進みます。

同じメソッドが、進行状況の割合を計算するために必要な 2 つの引数、つまり現在の値と最大の値を受け入れます。この例では、現在の行と行の総数を指定します。たとえば、現在の行が 300 で、ビットマップには 600 行ある場合は、進行状況バーに 50% 終了と表示されます。

RenderEffect 進行状況コールバック機能

ループ終了

pixel_line = getPixels r_image [0,y] bmp_w

getpixels 関数は、指定されたファイルの Point2 の値で示された位置からピクセルを読み始め、最後の値で指定されたピクセル数を読み取ります。結果は、配列としてユーザ変数の pixel_line に代入されます。最初のピクセルから開始して左へ読み取り、すべての bmp_w ピクセルを読みます。 スキャンライン全体にイメージの幅に入るだけの数のピクセルが含まれています。

getPixels

for x = 1 to bmp_w do
(

これで、ピクセル値の配列内ですべての値を巡回して調べることができます。MAXScript 内の配列は 1 を基点としているため、1 からイメージの幅まで数えます。

for ループ

p_v = pixel_line[x].value
pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha

これが実際の中核となるコードです。 カラーの .Value プロパティ (グレースケール強度) を取得して、元のピクセルの .Value と等しい赤、緑、および青の値で新しいカラー値を生成します。アルファ チャネルに触れないように、元のアルファ値を RGBA カラーに追加するだけです。結果は配列内の同じ位置に格納するので、カラー情報がグレースケール バージョンで上書きされます。

カラー値

)--end x loop
setPixels r_image [0,y] pixel_line

スキャンラインのすべてのピクセルを処理した後に、 setpixels 関数で、新しいグレースケール値を含んだ配列の pixel_line を同じ位置から始まるイメージに書き戻します。これで、現在の行 y 内のカラーが上書きされます。

setPixels

)--end y loop

ループによる準備が完了し、ビットマップ全体が変更されました。 on apply ハンドラによって結果のビットマップがシステムに返され、仮想フレーム バッファ内に表示されます。

escapeEnable = oldEscapeEnable

前に説明したように、レンダリング効果のループ前に MAXScript のエスケープ キーの処理を元の状態に設定する必要があります。

)--end on apply
)--end plugin

スクリプトの使い方

スクリプトを評価した後に、新しいプラグイン効果の 「MonoChrome」が、[レンダラー](Renderer) > [効果...](Effects...) > [追加...](Add...)に表示されます。それを効果のキューに追加して、シーンをレンダリングします。その結果、モノクロ バージョンでレンダリングされます。スクリプト renderEffects は、SDK を使用して作成された本物のプラグインと比較して低速ですが、非常に柔軟性があり、すばやくプロトタイプ化できます。

仮想フレーム バッファ内で、イメージのアルファ バージョンとモノクロ バージョンを調べることができます。アルファ バージョンは変更されておらず、モノクロ バージョンは renderEffect によって生成された RGB イメージと同じです。

関連項目

この基本スクリプトの比較的簡単な変更は、ビットマップの N 番目の行だけを常に変更することです。for y ループに by 2 オプションを追加すると、常に 2 番目の行のみに影響を与えることになります。

for y = 0 to bmp_h-1 by 2 do

x ループに by 2 を追加すると、ピクセルのグリッドのみに影響を与えることになります。2 よりも大きい値を使用することもできますし、ユーザ定義の行やピクセル ステップ用の UI コントロールを追加することもできます。

このスクリプトに対するもっと複雑な変更は、R、G、および B チャネル内のモノクロ値の異なるプロパティを使用した、モノクロ イメージへの着色です。そのためには、ロールアウトと 3 つの浮動小数点値を定義する paramBlock を追加し、ユーザが使用する各チャネル量を指定できるようにします。次に、p_v 値に 3 つの値を乗算し、それらの値をイメージの R、G および B の値に代入します。

戻る

「チュートリアル」のインデックス ページ