Fu-Ken's Room

POV-Ray でイロイロやってみよう!

第九回 地形を作ってみよう(後編)

前回は Traggen の地形を POV-Ray に持っていくところまでを解説しました。
しかし、持っていっただけでは Terragen のような美しい仕上がりにはなりません。
そこで POV-Ray でいろいろ設定しなおす必要がでてきます。
今回は修正の参考例を見ながら説明していきます。

1. 前回のファイルの修正

前回のソースでは地形を Terrain Units にあわせた大きさにしていましたが、今後、木を植えたり他のオブジェクトを導入するときに大きさのイメージをしやすいようにメートルに直しておきます。
あと、復習の意味も含めて、下に今回のもとになるソースを示します。

#version 3.5;

camera {
location <4050,74.7,1770>
look_at <4110,348.4,3900>
angle 70
}

sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.7,0.8,1.0>]
[0.7 rgb <0.1,0.2,0.8>]
}
}
}

light_source {
<0, 0, 0>
color rgb <1, 1, 1>
translate <100000, 0, 0>
rotate y*90 rotate x*30
}

#declare Terra = object {
height_field {
png "semiL1.png"
smooth
texture {
pigment {
image_map { png "semiC1.png" map_type 0 interpolate 2 once }
rotate x*90
}
finish { ambient 0.60 }
}
}
scale <257,52,257>*30
}

object { Terra }

plane { y,60
texture {
pigment {
color rgb <0.1,0.2,0.8>
}
finish {
reflection 0.5
}
}
}

赤色の部分が前回と異なる行です。
これをレンダリングしても前回と同じ画像になります。

2. 地表

地表部分のテクスチャの仕上げについて考えてみます。

texture {
pigment {
image_map { png "semiC1.png" map_type 0 interpolate 2 once }
rotate x*90
}
finish { ambient 0.60 }
}

pigment { 〜 } の部分は色の設定で、イメージマップを貼っているので、ここは変更しません。
finish { 〜 } の部分、つまり反射に関する部分で調整してみます。

finish {
diffuse 0.6
crand 0.5
ambient 0.60
}

まず diffuse (拡散反射)ですが、ここはとりあえずデフォルトの 0.6 としています。
この値を大きくすると、直接光が当っている部分がより明るくなります。
crand (粗さ)については 0.3 としています。
デフォルトは 0 のため、滑らかな表面になっていたので、ここの値を上げたのです。
あまりあげすぎると全体的に黒く汚くなってしまうので注意しましょう。
ambient (環境光) は、間接光により陰の部分でもいくらか明るく見えるという状態を簡易的に表現するための値です。
この値を大きくすることで全体的に明るい表面となります。
デフォルトは 0.1 ですが、今回は 0.8 まであげています。
これらの修正を加えてレンダリングしたのがこちら。

表面がざらついた感じになりました。
finish { 〜 } は反射に関する部分の修正ですが、表面の凹凸に関する部分については texture{ 〜 } の中にさらに normal { 〜 } という要素を追加します。

normal {
agate scale 0.0002
}

agate は「めのう」を表現しているパターンを作り出すもので、normal の中に指定すると表面にめのう模様の凹凸ができます。
scale 0.0002 としているのは、あとでこのハイトフィールド自体を平面方向に 7710倍(275x30)しているため、あらかじめ小さくしているのです。
実際は自分で微調整しながら大きさを決めましょう。
normal の指定を加えたものはこちら。

画像が小さいと効果がよく分かりませんね。(^-^;
とりあえず地表にについてはこの程度にしておきます。

3. 水面

水面の表現ほど難しいものはないと思いますが、出来る範囲でやってみましょう。
今のところは以下のように無限平面を設定しています。

plane { y,60
texture {
pigment {
color rgb <0.1,0.2,0.8>
}
finish {
reflection 0.5
}
}
}

青色で鏡面反射(reflection)の値を大きくしています。
これを次のように変更します。

plane { y,60
texture {
pigment {
color rgbf <0.6,0.7,0.9,0.3>
}
finish {
diffuse 0.3
ambient 0.3
reflection 0.5
specular 0.6
roughness 0.05
metallic
}
normal { bozo 0.5 bump_size 1 scale 2 }
}
interior {
ior 1.3
}
}

色の指定の部分で少し白っぽくし、さらに透明度も追加指定しています。(color rgbf <0.6,0.7,0.9,0.3>)
finish { 〜 } の中で、拡散反射を少しおさえ(diffuse 0.3)、環境光を少し大きく(ambient 0.3)しました。
鏡面反射をかなりする(reflection 0.5)ようにし、鏡面ハイライトも強め(specular 0.6)で、その大きさは小さく(roughness 0.05)しました。
metallic を追加することで、金属のような仕上がりになるようにしています。
normal { 〜 } では、bozo という滑らかなランダムノイズを発生するパターンを追加しています。
これで穏やかな波を表現できればと考えたわけですが、波紋を発生する模様を使用してもいいかもしれません。
まあ、近い水面ではないので、反射が乱れる程度でいいのかなとも・・・
bump_size と scale は各自で調節しましょう。
透明にしているので、interior { 〜 } で屈折率(ior 1.3)も設定しています。
かなり設定が多いですが、なくてもそれほど違いが見られないようなものもあるので、そこは各自で試してみてください。
この水面だけをレンダリングしたのがこちら。

さきほどの地形にこの水面を加えるとこうなります。

4. 空

そらはY軸方向にグラデーションをかけているだけです。

sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.7,0.8,1.0>]
[0.7 rgb <0.1,0.2,0.8>]
}
}
}

ここに雲の模様を追加してみます。
sky_sphere { 〜 } の中にもう一つ pigment{ 〜 } を追加するのです。

sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.7,0.8,1.0>]
[0.7 rgb <0.1,0.2,0.8>]
}
}
pigment{
wrinkles
color_map{
[ 0.3 color rgbf 1 ]
[ 0.9 color rgb 1 ]
}
scale <0.5, 0.1, 0.1>
}
}

追加された pigment の中には wrinkles という、皺の模様を作成するパターンを指定しています。
皺模様の2色のうち一方を白に(color rgb 1)、一方を完全に透明にします。color rgbf 1
すると白い雲の模様ができ、透明な部分はY軸方向のグラデーションが見えることになります。
scale の部分はまた各自で微調整してください。
この空を加えてレンダリングしたのがこちら。

5. 大気

実際の空間では、大気の影響で遠くになるほど霞んで見えるようになっています。
Terragen でも大気の設定で霧のかかったような感じにすることができます。
POV-Ray でも複雑な設定をすれば大気の効果を精密に表現できますが、もっと簡単な方法で効果を得ましょう。
それは fog を設定するのです。

fog {
fog_type 2
distance 10000
color rgb 1
fog_offset 1000
fog_alt 0.5
up y
}

fog_type には 1 と 2 があります。
1 は全体に均等に霧がかかり、2 では地表面に霧がかかります。
distance は霧の透明度で、今回の場合、距離にして 5000 離れたところくらいから先が見えなくなります。
color は霧の色で、今回は白にしています。
fog_offset は、type 2 の霧で地表からどれだけの距離から霧が薄くなるかを決めています。
この値を山の高さより低くしておけば、地表面のみ霧がかかることになります。
fog_alt は type 2 の霧の減衰率ですが、計算は難しいので、大きくなるとなかなか薄くならないというくらいに考えて調節していきましょう。
up は霧の方向で、y 、つまり<0,1,0>としているので上に向かって薄くなっていきます。
これでレンダリングしたのがこちら。

地表、水面、空、大気の修正はとりあえずこれで終わりとします。
まだまだ修正したい人もいると思いますが、ここまでに説明した部分の微調整でももっとよくなると思いますので頑張ってみてください。

6. 植樹

さてここからは Terragen ではできない植物や他のオブジェクトの配置です。
今回配置するのは、POV-Tree のサンプル“Linden”を Export Mesh で出力したものです。

この木を配置するとき問題となるのが地表の高さです。
ハイトフィールドで作成した地面の高さを正確に求め、その位置に木の下端を配置しなければならないのです。
その植樹部分のソースがこちら。

#include "treeP1.inc"

#declare Target = object { Terra }
#declare Norm = <0, 0, 0>;
#declare Start = <4070,0,1815>;
#declare End = <4070,1,1815>;
#declare Inter = trace ( Target , Start, End-Start, Norm );

#if (vlength(Norm)!=0)

object { TREE scale 20 translate Inter }

#end

まず、POV-Tree で出力した木のインクルードファイルを読み込みます。
次に trace という関数で地表の高さを求めます。
trace という関数は次のような計算をするものです。

Inter = trace ( Target , Start, End-Start, Norm )

trace の()の中は、ターゲットとなるオブジェクト、衝突判定する直線の開始座標、直線の方向(ベクトル)、直線がターゲットオブジェクトに衝突した位置のターゲットオブジェクト表面の法線となります。
分かりやすく言えば、Start から End に向けてのばした直線がターゲットに衝突した位置を Inter に代入し、Inter の位置の法線ベクトルを Norm に代入します。
衝突しない場合は Norm は <0,0,0> になります。
今回は、ターゲットにハイトフィールドで作った地形(Terra)、開始位置は <4070,0,1815>、そこから真上に直線をのばします。
なお、最初に Norm を <0,0,0> に初期化しておきます。
これらの値を trace で計算して、直線が地表と交差した座標が Inter に入ります。
もし衝突していれば Norm のベクトルの大きさが 0 ではなくなるので、それを判定します。(#if (vlength(Norm)!=0))
衝突していれば、木のオブジェクトを 20倍し、Trace で判定した座標(Inter)に移動します。
衝突していなければなにもしません。
これでレンダリングしたのがこちら。

trace は理解するまでちょっと時間がかかるかもしれませんが、わかれば複雑な地形にオブジェクトを配置する非常に便利な機能です。
頑張ってみましょう。

7. 最後に

それでは、ここまで変更したソースを下に示します。

#version 3.5;

//----- カメラの設定 -----//

camera {
location <4050,74.7,1770>
look_at <4110,348.4,3900>
angle 70
}

//----- 空と雲の設定 -----//

sky_sphere {
pigment {
gradient y
color_map {
[0.0 rgb <0.7,0.8,1.0>]
[0.7 rgb <0.1,0.2,0.8>]
}
}
pigment{
wrinkles
color_map{
[ 0.3 color rgbf 1 ]
[ 0.9 color rgb 1 ]
}
scale <0.5, 0.1, 0.1>
}
}

//----- 霧の設定 -----//

fog {
fog_type 2
distance 10000
color rgb 1
fog_offset 1000
fog_alt 0.5
up y
}

//----- 太陽の設定 -----//

light_source {
<0, 0, 0>
color rgb <1, 1, 1>
translate <100000, 0, 0>
rotate y*90 rotate x*30
}

//----- 地形の定義 -----//

#declare Terra = object {
height_field {
png "semiL1.png"
smooth
texture {
pigment {
image_map { png "semiC1.png" map_type 0 interpolate 2 once }
rotate x*90
}
finish {
diffuse 0.6
crand 0.5
ambient 0.80
}
normal {
agate scale 0.0002
}
}
}
scale <257,52,257>*30
}

//----- 地形 -----//

object { Terra }

//----- 水面 -----//

plane { y,60
texture {
pigment {
color rgbf <0.6,0.7,0.9,0.3>
}
finish {
diffuse 0.3
ambient 0.3
reflection 0.5
specular 0.6
roughness 0.05
metallic
}
normal { bozo 0.5 bump_size 1 scale 2 }
}
interior {
ior 1.3
}
}

//----- 樹木 -----//

#include "treeP1.inc"

#declare Target = object { Terra }
#declare Norm = <0, 0, 0>;
#declare Start = <4070,0,1815>;
#declare End = <4070,1,1815>;
#declare Inter = trace ( Target , Start, End-Start, Norm );

#if (vlength(Norm)!=0)

object { TREE scale 20 translate Inter }

#end

ということで、今回はこれで終わりです。
Terragen から POV-Ray への連携というのも非常に面白いので、また何か気がついたら解説してみようと思います。
では、また。

◆ PREVIOUS ◆

◆ BACK TO SEMINAR ◆