プログラムの整理と拡張(中編)
材質に関する整理
「課題2-5. 複数の物体を表示する」では複数の物体を表示させたが, 全ての物体が同じ色で描画されていた.
図1. HalfRayTracing_MultiShapesの生成画像
これは反射係数などの値を全ての物体で共有していたためである.物体ごとにその表面の材質は異なるため, 反射係数などは個々の物体に紐付くデータと考えるのが自然である.そこでこの部分もクラスとして整理しよう.
反射係数などのパラメータは,前回までのスケッチだと以下のように定義していた.以下はスケッチの冒頭部分である.
PVector eyePos; // 視点位置 ArrayList<Shape> shapes; // 物体 LightSource lightSource; // 光源 FColor ambientIntensity; // 環境光の強さ FColor kAmb; // 環境光反射係数 FColor kDif; // 拡散反射係数 FColor kSpe; // 鏡面反射係数 float shininess; // 光沢度
kAmb
(環境光反射係数),kDif
(拡散反射係数),kSpe
(鏡面反射係数),shininess
(光沢度)である.
前回までのスケッチではこれらはグローバル変数として管理していた.今回はこれらを4つのFColor
と一つのfloat
型を含む
Material
(材質)クラスに整理する.
ambientFactor
が環境光反射係数,diffuseFactor
が拡散反射係数,specularFactor
が鏡面反射係数,
shininess
が光沢度である.この情報を物体を表すクラスShape
に関連づけるため,Shape
クラスにこのMaterial
クラスの属性を追加する.
以下のように使用する.
Shape hoge = /* 何らかの物体オブジェクトを生成 */; // 材質の情報を設定する. hoge.material.ambientFactor.set(0.01, 0.01, 0.01); // 環境光反射係数 hoge.material.diffuseFactor.set(0.69, 0.69, 0.69); // 拡散反射係数 hoge.material.specularFactor.set(0.30, 0.30, 0.30); // 鏡面反射係数 hoge.material.shininess = 8.0; // 光沢度
複数の光源に対応する
前回までのスケッチでは,光源を一つに限定していた.
Phongの反射モデルでは,物体表面の反射光の輝度を以下のように表現すると述べた.
- $$R_{a}$$:環境光の反射光の輝度
- $$R_{d}$$:直接光の拡散反射光の輝度
- $$R_{s}$$:直接光の鏡面反射光の輝度
Phongの反射モデルは本来複数の光源を考慮している.本来の式は以下である.
- $$R_{a}$$:環境光の反射光の輝度
- $$R_{di}$$:i番目の光源からの直接光の拡散反射光の輝度
- $$R_{si}$$:i番目の光源からの直接光の鏡面反射光の輝度
物体表面の輝度は,シーンの環境光と,シーンに存在する全ての光源からの光の反射光の総和となっている(図2).
放射輝度の計算は以下のようになる.
if(視線レイと物体が交点を持つ場合) { 環境光の反射光の放射輝度を計算して【放射輝度】に代入する. for(全ての光源について繰り返す) { 光源iからの光の拡散反射光の放射輝度を計算して【放射輝度】に加算する. 光源iからの光の鏡面反射光の放射輝度を計算して【放射輝度】に加算する. } 【放射輝度】を色に変換して描画色に設定する. }
課題
課題2-6 物体ごとに色を変更する
「課題2-5. 複数の物体を表示する」を改造して,物体ごとに物体表面の色を変更できるようにせよ.
このスケッチはHalfRayTracing_Material
という名前で保存すること(手順は後述する).
表示すべき物体は課題2-5と同じであるが,色の設定は以下のようにせよ.デフォルト値ではない部分は赤字にしてある.
- 球1
- 中心$$(3,0,25)$$,半径$$1$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.69, 0.00, 0.00)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
- 球2
- 中心$$(2,0,20)$$,半径$$1$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.00, 0.69, 0.00)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
- 球3
- 中心$$(1,0,15)$$,半径$$1$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.00, 0.00, 0.69)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
- 球4
- 中心$$(0,0,10)$$,半径$$1$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.00, 0.69, 0.69)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
- 球5
- 中心$$(-1,0,5)$$,半径$$1$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.69, 0.00, 0.69)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
- 平面
- 法線方向$$(0,1,0)$$, 位置$$(0,-1,0)$$
- 材質
- 環境光反射係数:$$(0.01, 0.01, 0.01)$$
- 拡散反射係数:$$(0.69, 0.69, 0.69)$$
- 鏡面反射係数:$$(0.30, 0.30, 0.30)$$
- 光沢度:$$8$$
生成結果は以下のようになる.
この課題ではMaterial
クラスを追加する必要がある.以下の手順に従え.
F.1) 「課題2-5. 複数の物体を表示する」のスケッチをHalfRayTracing_Material
という名前で保存する.
F.2) 以下をクリックすると必要なソースコードがコピーされるので,GeometryUtils
タブの末尾にペーストする.
F.3) GeometryUtils
の84行目付近にShape
クラスの定義がある.このクラスにMeterial
クラスのパブリックな属性material
を追加する.
abstract class Shape { public abstract IntersectionPoint testIntersection(Ray ray); }
abstract class Shape { public Material material = new Material(); // <- 追加 public abstract IntersectionPoint testIntersection(Ray ray); }
F.4) シーン中の各物体が上述の設定になるようにプログラム全体を修正する.
ヒント
課題2-7 光源を複数にする
「課題2-6 物体ごとに色を変更する」を改造して,光源を複数設定できるようにせよ.
課題2-6のスケッチをHalfRayTracing_MultiLights
という名前で別名保存(ファイル
メニューの名前を付けて保存
をクリックして保存)してからとりくむこと.
設定するべき光源は以下の通りである.
- 点光源1
- 位置$$(-5, 5, -5)$$
- 光の強度$$(0.5, 0.5, 0.5)$$
- 点光源2
- 位置$$(5, 0, -5)$$
- 光の強度$$(0.5, 0.5, 0.5)$$
- 点光源3
- 位置$$(5, 20, -5)$$
- 光の強度$$(0.5, 0.5, 0.5)$$
複数の光源を保持するには,「課題2-5. 複数の物体を表示する」と同様に
ArrayList<E>
を用いる.以下のように使用する.
ArrayList<LightSource> lightSources; // 光源のリスト // ..中略.. void setup() { // ..中略.. lightSources = new ArrayList<LightSource>(); // 光源のリストを生成 LightSource piyo = /* 何らかの光源オブジェクト */ ; lightSources.add(piyo); // 光源のリストに追加 }
リスト内の要素を反復するには以下のようにする.
// リスト内の各要素を処理する for(int i = 0; i < lightSources.size(); ++i) { LightSource light = lightSources.get(i); // 何かの処理 }//for // 以下でも同じ(こちらの方が簡潔) for(LightSources light : lightSources) { // 何かの処理 }//for
生成結果は以下のようになる.
0 Comments.