TOP

ABOUT

PROGRAM

DIALY







リムライティング

 1.はじめに…
 "Illustrative Rendering In Team Fortress2"の資料を見ていたら,資料の中に"Rim Lighting"という言葉があり気になったので,調べみました。




 2.概要
 リムライティングがわからなかったので,少し調べてみましたが,結局あんましよくわかりませんでした。とりあえずバックライトみたいに,いい感じリム(輪郭)が出るようにすればいいんですかね?
リムライトですが,なぜ使うのかというと,主に暗い物が暗い背景に沈み込まないようにするためだそうです。わかりやすい例は次です。



上の写真は皆さんご存知のTVドラマ「古畑任三郎」のシーンの一部です。古畑さんが黒い服を着ているので,そのままだと暗い背景に沈み込んでしまうのですが,それを避けるために後ろからライトを当てて,輪郭が出るようにしているのだと思います。

で,プログラムで実装するやり方です。
後ろからライトを当てるので,まずこれを考えます。
視線ベクトルと面の法線ベクトルの内積を取ることによって,カメラの方を向いているか向いていないかがわかります。カメラの方を向いていない場合,後ろになるので,ライトは明るくなるはずです。逆にカメラの方を向いている場合,ライトを後ろから当てるので,暗くならないとおかしい気がします。単位ベクトル化してあれば,カメラの方向を向いている場合,内積の値は1になり,カメラの方向を向いていない場合は内積の値は0になります。今は後ろ側を明るくしたいので,1 - dot(N, E)を使ってあげればよさそうです。
そんでもって,明るさですが,Team Fortress2の資料の中で指数関数を使っているようなので,指数関数を使ってみることにしました。
ピクセルシェーダのコードは下のような感じです。

00081:  float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
00082:  {
00083:      // TODO: add your pixel shader code here.
00084:  	float3 N = normalize( input.Normal );
00085:  	float3 E = normalize( CameraPosition - input.WorldPosition );
00086:  	float3 L = normalize( - LightDirection );
00087:  
00088:  	float3 Ambient = input.Color * 0.3;
00089:  	float3 Diffuse = input.Color * ( max( dot( N, L ), 0 ) * 0.5 + 0.5 );
00090:  	float3 Rim = RimColor * Kr * pow( 1 - dot( N, E ), Power );
00091:  
00092:  	float4 color = float4( Ambient + Diffuse + Rim, 1.0f );
00093:  
00094:      return color;
00095:  }

ちなみにリムライトを切った状態と比較してみると下のような感じです



左の方がリムライトを切った状態で,右の方がリムライトを使っている状態です。
それなりにちゃんとした結果になっているんですかね?


 Download
本ソースコードおよびプログラムを使用したことによる如何なる損害も製作者は責任を負いません。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2008 Professional, NVIDIA Cg Toolkit 2.0 May 2008を用いています。