前へ | 上へ

一章

はじめに光ありき



概要

This chapter tries to introduce the reader to the actual use of the Lightflow Rendering Tools. The best way to do this is by giving a tutorial and commenting it accurately.

この章は Lightflow Rendering Tools を実際に使用して読者に紹介しようとするものです。これをする最も良い方法は、チュートリアルとその正確なコメントを与えることです。


チュートリアル

The following example is one of the simplest possible scenes that can be rendered: a sphere in the empty space.
Now start your preferred text editor and type the following text. When you have finished save it in a file, and then start python from a console passing the file name as an input (for example, if you have saved the file as example.py, just type: python example.py).

下のサンプルはレンダリングすることができる最も簡単なシーンの一つ、何もない空間の中の球体です。
それではさっそくお気に入りのテキストエディタを起動して、下記のテキストを入力して下さい。ファイルに保存し終わったら、入力としてファイル名を渡してコンソールから Python を起動して下さい (例えば、example.py としてファイルを保存したのであれば、python example.py と入力するだけです)。


from lightflowPM import *

s = scene()

s.lightOn( s.newLight( "point", [ "position", vector3( 5.0, -5.0, 4.0 ), "color", vector3( 300.0, 300.0, 300.0 ) ] ) )


plastic = s.newMaterial( "standard", [ "ka", vector3( 0, 0, 0.5 ), "kc", vector3( 1, 0.5, 0.5 ), "kd", 0.5, "km", 0.1 ] )


s.materialBegin( plastic )

s.addObject( s.newObject( "sphere", [ "radius", 1.0 ] ) )

s.materialEnd()


saver = s.newImager( "tga-saver", [ "file", "ball1.tga" ] )

s.imagerBegin( saver )

camera = s.newCamera( "pinhole", [ "eye", vector3( 0, -4, 0 ), "aim", vector3( 0, 0, 0 ) ] )

s.imagerEnd()

s.render( camera, 300, 300 )
(画像の表示)
The first line of the program introduces a variable that contains a scene object. This line creates a new scene, the main block of a Lightflow program.

プログラムの最初の行は scene オブジェクトを含む変数を導入しています。この行は Lightflow プログラムのメインブロックである、新しいシーンを作成します。

The second line calls the two scene methods named lightOn and newLight.

二行目は lightOnnewLight と名前を付けた二つの scene メソッドを呼び出します。

newLight is the first to be executed: it specifies the construction of a new light object belonging to the scene, and it takes two arguments, a string indicating the type of light to be created, in this case a "point" light, and a list containing the parameters that will be used in the construction process. Here the parameters are "position", which specifies that the next token should be interpreted as the position of the point-light, and "color", which says that the color of the light follows. Both the position and the color are specified with a three-dimensional vector, namely vector3, that in the first case represents a point in space, while in the second represents a RGB triple. Note that this string-value pairing is a peculiarity of all the parameter lists that are passed to scene methods that start with "new", such as newLight, newObject, newMaterial, etc. This mechanism in fact provides a method to distinguish between the meaning of the different parameters. Also it allows to specify only a subset of all the possible parameters that each type accepts, while the others will mantain their default value. For example "point" lights have also a field named "shadows" that accepts a boolean value specifying if shadows are projected or not, and its default is true.

newLight が最初に実行されます: これはシーンに属する新しいライトオブジェクトの構造を指定し、作成されるライトの種類を示す文字列、この場合は "point" ライトと、構成プロセスで使われるパラメータを含むリスト、の二つの引数をとります。ここでのパラメータは、隣が形ばかりの点光源の位置として解釈されるものであるとして指定する "posiion" と、ライトが放射する色を示す "color" です。位置と色の両方は三次元のベクトル、通常は vector3 で指定されます。最初の場合は空間上の点を表し、二番目は RGB の三組を表しています。この文字の値の組み合わせは newLight, newObject, newMaterial, etc のように、"new" で始まる scene メソッドに渡す全てのパラメータリストの特殊形です。このメカニズムは実際に異なるパラメータの意味を区別するための方法を提供しています。さらにこれはそれ以外がデフォルトの値を保持するのに対して、それぞれのタイプを受け入れる全ての可能なパラメータのサブセットだけを指定することができます。例えば "point" ライトはシャドウが投影されるかどうか、そのデフォルトが真であるかによって、指定しているブール値を受け入れる "shadow" と名前の付いたフィールドも持ちます。

The second method call, lightOn, is very simple: it accepts a single argument, the handle to a light source that has been created using newLight. This handle is an integer, and it could also be assigned to a variable for future uses, but we will see that here there was no need to do this. The purpose of this method is to turn on the light source that is passed to it, that otherwise would not illuminate anything. This serves because we may want a light to illuminate only some parts of the scene. Note that this on/off mechanism has not any temporal significance, since we are rendering a single image at a time: it has only a geographical meaning.
The next method call is to newMaterial, a procedure that creates materials in the same way used for ligths. The first argument is still the type, in this case the "standard" material, and the second is the usual parameter list. This is composed by "ka", the ambient color, "kc", the surface color, "kd" the amount of diffusion, and "km" a smoothness coefficient for the specular highlights. Here we won't give a detailed explanation of these coefficients, which is given in the "standard" material documentation, but you may have noticed that they are similar to the ones used by common RenderMan shaders, thus the name "standard".

二番目のメソッドコール、lightOn は非常にシンプルです: 一つの引数を受け入れ、newLight を使用して作成されている光源を扱います。このハンドルは整数で、将来の用途のために変数を割り当てることもできますが、ここではこれをする必要が無かったことが分かるでしょう。このメソッドの目的は、それに渡される光源を点灯することです。さもなければ、何も照らすことはありません。これはシーンのある部分だけを照らすライトが欲しい時にサービスします。一度に一つの画像をレンダリングしているので、このオン/オフメカニズムが全く一時的な重要性を持っていないことに注意して下さい: これは地理的な意味だけを持つのです。
次のメソッドコール、newMaterial はライトを使うためと同じ方法でマテリアルを作成するプロシージャです。最初のパラメータはタイプで、この場合、"standard" マテリアルです。次の引数は通常のパラメータリストです。これは周囲の色 "ka" と、表面色 "kc" と、拡散の量 "kd" と、スペクトルハイライトの平滑係数 "km" で合成されます。ここれには "standerd' マテリアルドキュメントで与えられている係数の詳細な説明をしませんが、よくある RenderManシェーダによって使われるものと似ていることに気付いたかもしれません。だから名前が "standard" なのです。

After registering the material handle into a variable named plastic, this is passed to the method materialBegin. This method performs a complex stacking operation, but for now you should only know that its purpose is to declare the passed material as the current one, from which the following objects will be made.
The next operation involves two methods, addObject and newObject. Again the first to be executed is the second to appear, and so we will explain it before the other. newObject creates an object, that is to say a geometrical entity, that here is a sphere with radius 1. As we said before this sphere will inherit the current material, and so it will be made of plastic. addObject adds this object to the scene, putting it into the rendering set. You may ask yourself why this operation is not automatic, and the answer is simple, even if not immediate: objects can be compounded before use, for example with a boolean operation, and so only the final result needs to be really added to the set, while the intermediate objects should be left apart.

plastic と名前の付いた変数へマテリアルハンドルを登録した後、これはメソッド materialBegin に渡されます。このメソッドは複雑なスタック操作を行うのですが、今のところ、続いているオブジェクトが作られるものから、渡したマテリアルを現在のものとして宣言するための目的であることだけは知っておくべきです。
次の操作は二つのメソッド、addObjectnewObject を含んでいます。前者が実行されるたびに後者が現れます。そのため他を説明する前にこれの説明をします。newObject はオブジェクトを作成します。これは半径 1 の球体がある、ジオメトリな実体であると言えます。以前言ったように、この球体は現在のマテリアルを継承するので、plastic で作られます。addObject はオブジェクトをレンダリングセットに配置し、シーンに追加します。この操作がなぜ自動ではないのかとあなたは尋ねるかもしれません。一瞬ではなくても、答えは簡単です: オブジェクトは使う前に合成することができます。例えば、ブール演算です。中間オブジェクトを個別に残さなければならない一方、最終結果だけが実際に集合に追加する必要があります。

The call to materialEnd marks the end of the previously declared material block. This means that if we declare another object after here it will no longer be made of plastic. This simple concept has some complex drawbacks you should know, since they are extensively used throughout the rendering interface. The two methods materialBegin and materialEnd define a block, which is opened by the first and closed by the latter. Note that these methods should always come in couple, that is to say you cannot call materialBegin without calling materialEnd after it, and you cannot even call materialEnd without having already opened a block with materialBegin. Also these methods mantain a stack, and so material blocks may be nested, provided that coupling rules are not ever broken. An example of this feature could be the following:

materialEnd の呼び出しは以前に宣言したマテリアルブロックの終りを示します。これはつまり、ここより後に別のマテリアルを宣言しても、もはやplastic は作られないという意味です。レンダリングインターフェイスのいたるところで広範囲に使われるので、このシンプルな概念はあなたが知るべきいくつかの複雑な欠点を持っています。二つのメソッド、materialBeginmaterialEnd は、前者によって開かれて後者によって閉じられるブロックです。それらのメソッドは常に一組にならなくてはなりません。つまり、materialEnd を呼び出さずに materialBegin を呼び出したり、materialBegin でブロックを開くことなく materialEnd を呼び出すことはできないということです。さらにそれらのメソッドはスタックを保守するので、マテリアルブロックは入れ子であったり破綻無きカップリングルールを提供していても構いません。この関数の例を以下に挙げます:


s.materialBegin( plastic1 )
... # do something
s.materialBegin( plastic2 ) # マテリアルのネスト
...
s.materialEnd()
...
s.materialEnd()

代わりに間違った用法ではこのようになります:

s.materialBegin( plastic )
...
s.materialEnd()
...
s.materialEnd() # マテリアルの終了と一致しない
    
s.materialBegin( plastic ) ... # マテリアルブロックを閉じていない

The next entity to be created is an imager, that is to say the special output device used to handle rendering results. Here a "tga-saver" is created that writes the final image to a targa file.
Then a new block is introduced, as for materials: the imager passed to imagerBegin will be the current one used by the following cameras, untill imagerEnd will be called.
Before closing this block a "pinhole" camera is constructed with newCamera, passing to it the position of the eye and the one of the aim.
After having closed the imager block the rendering is done by calling render, which takes as input the camera and the resolution of the image in width-height form.

次の作成するエントリは、レンダリング結果を取り扱うために使用する特定の出力デバイスを示すイメージャーです。ここの "tga-saver" は最終画像を targa ファイルに書き出して作成します。
新規ブロックをマテリアルのために紹介します: imagerBegin に渡したイメージャーは、imageEnd を呼び出すまでカメラを続けて使われる現在の一つです。
このブロックを閉じる前に、"pinhole" カメラは eye の位置と aim の位置に渡す、newCamera で構成されます。
イメージャーブロックを閉じてしまった後で、カメラと 幅-高さ の形式で画像の解像度を入力としてとる、render を呼び出すことでレンダリングを行います。

Once you have seen and comprehended the results of the first example, you are ready to modify it in order to obtain something more than a simple sphere. Try typing this:

一度最初の例の結果を見て理解してしまえば、あなたは単純な球体以上の何かを得るためにこれを変更できるようになるでしょう。これを入力してみて下さい:


from lightflowPM import *

s = scene()

s.lightOn( s.newLight( "point", [ "position", vector3( 5.0, -5.0, 4.0 ), "color", vector3( 300.0, 300.0, 300.0 ) ] ) )


bump = s.newPattern( "multifractal", [ "basis", "sin", "scale", 0.6, "depth", 0.2, "turbulence.omega", 0.5, 0.7, "turbulence.octaves", 6] )

plastic = s.newMaterial( "standard", [ "ka", vector3( 0, 0, 0.05 ), "kc", vector3( 1, 1, 1 ), "kd", 0.5, "km", 0.1, "displacement", bump ] )


s.materialBegin( plastic )

sphere = s.newObject( "sphere", [ "radius", 1.0 ] )

s.addObject( s.newObject( "surface-engine", [ "surfaces", sphere, "tolerance", 0.02, 0.1, 0.05 ] ) )

s.materialEnd()


saver = s.newImager( "tga-saver", [ "file", "ball2.tga" ] )

s.imagerBegin( saver )

camera = s.newCamera( "pinhole", [ "eye", vector3( 0, -4, 0 ), "aim", vector3( 0, 0, 0 ) ] )

s.imagerEnd()

s.render( camera, 300, 300 )
画像の表示
You will note that the sphere has been deformed in a strange and subtle way. This is due to the effect of the "multifractal" pattern named bump, which has been inserted in the "displacement" channel of the plastic material. Then also the geometry has been modified by letting the sphere pass through a "surface-engine" object, an entity that accurately computes the visualization of generic surfaces, independently of their type. In this case it is necessary to handle the actual deformation of the sphere's surface, that otherwise would have looked flat as if it was bump-mapped.
Now that you have seen what are the simple elegance and the power of Lightflow you can start digging under the surface by reading the second chapter. In the meantime, if you want, you can take a pause and imagine how your projects will look in the future...

球体が奇妙で不可思議な方法で、奇妙な形になったことに気付くでしょう。これはプラスチックマテリアルの "displacement" チャンネルで挿入されている、bump と名前の付いた "multifractal" パターンの効果によるものです。そしてジオメトリも、その種類とは独立した、generic サーフェイスの視覚化を正確に計算する実体である、"surface-engine" オブジェクトを球体に通して渡すことで変更しています。この場合では、球体のサーフェイスの実際の変形を扱うことが必要で、さもなければ、バンプマップされたかのようにフラットに見えてしまうでしょう。
Lightflow のシンプルな優雅さとパワーが何なのかを見た今、あなたは二番目の章を読むことでサーフェイスを深く掘り下げることができます。その間、必要なら、ちょっと休憩を取って、あなたの計画が将来どのようになるだろうかと思い浮かべてみて下さい。

次へ