18. ライトと影

18.010 ライト処理について知っておくべき一般的な事がらは?

幾何学とともに垂直線を指定しなければならないか、または予期されるように働くために点火するための注文において評価者とそれらを自動的に生成しなければなりません。 これは問題18.020によりカバーされます

点火は、現在の色 として glColor*()により設定された によって働きません。 それは物質的な色によって作動します。 材料をセットしてください 色づく と glMaterialである 。 物質的な色は色物質的機能によって現在の色を追跡させられえます。 色素材を使うために、電話しなさい glEnableです(GL_COLOR_MATERIAL)。 デフォルトで、これは、周囲のおよび放散物質的色に現在の色を追跡させます。 どの物質的な色が呼び出し に () glColorMaterialである によって現在の色を追跡するかを指定できます。

素材を交換することは物質的な色によって着色し、glColor*()呼び出しは、glMaterialなので、使うより効率的であるかもしれません。 詳細については問題18.080を見てください

照明は個々の頂点で計算されます((およびプリミティブを横切って改ざんされます。その時glShadeModel()はGL_SMOOTH) ) (に設定されます)。 たとえプリミティブの上でライトが集中させられても、これはプリミティブを暗すぎるようにさせるかもしれません。 より高い表面近似によって、または軽いマップを使ってより正しい照明を得ることができます

ライトのポジションは、ポジションが呼び出しによってglLight*()に指定される時間に、現在のModelView行列により変換されます。 それらが呼び出しによってglVertex*()に指定される時にどれほど幾何学の頂点が現在のModelView行列により変換されるかのためにこれは相似です。 軽いソースを置くことの詳細について、問題18.050を見てください

18.020 なぜ私のオブジェクトはすべて同一色で、陰影も光もないのでしょう?

個々の頂点で正常を供給することに失敗する時には、この効果が起こります

点火方程式、およびそれを計算するOpenGLニーズ垂直線は、 あなたのための垂直線を計算しません(評価者を除いて)。 もしアプリケーションがglNormal*()を呼ばないならば、それはすべての頂点でデフォルト正常(0.0、0.0、および1.0) of を使います。 OpenGLはその時同じ、またはおよそ同じを計算し、個々の頂点で結果に点火します。 これはモデルを平らであることと不足明暗法ように見えさせます。

解決は、どのような与えられた頂点でも指定される必要がある垂直線を単に計算することです。 そして、呼び出しによって、それらを、OpenGLに、glNormal3f() 正常が関連する頂点を指定することに先がけて正しい に送ってください。

もしどのように正常を計算するかを知らないならば、ほとんどのケースにおいて、単にベクトル斜め製品でそれをすることができるでしょう。 OpenGLプログラミングガイドはどのように垂直線を計算するかを説明している小さいセクションを含んでいます。 また、それがOpenGL具体的ではないので、最も基本の3Dコンピュータ・グラフィックス本はそれをカバーします。

18.030 OpenGL に曲面法線を自動的に計算させるには?

評価者を使っていない限り、OpenGLはこれをしません

18.040 モデルにライティングしても、フラット・シェーディングしか得られないのですが?

第一に、明らかをチェックしてください。 glShadeModel()はGL_SMOOTHに設定されるべきで、それはデフォルト値です。もし従って、glShadeModel()を全然呼ばなかったならば、それはたぶん、すでにGL_SMOOTHに設定し、他に何かが悪い。

もしglShadeModel()が正しく設定されるならば、問題はたぶん、表面垂直線にあります。 スムーズな明暗法効果を達成するために、一般に、個々の頂点で、違う正常を指定する必要があります。 もしほとんどのケースに個々の頂点で同じ正常を設定した 結果 ならば、平らに影をつけられたプリミティブであるでしょう。

典型的な表面正常が、近づくために試みている表面と直角であることを心に留めてください

このシナリオは、ラージモデルのための特にデバッグすることが難しいかもしれません。 最もよいデバッグアプローチが、ほんの1つのプリミティブを引く小さいテストプログラムを書く必要があることおよび問題を再生する試み。 それは、問題を再生する小さいプログラムを分離し、固定するために通常使いやすい デバッガ 。

18.050 光を動かしたり、動かないようにしたり、光の位置をコントロールするには?

第一に、どのように軽いポジションがOpenGLにより変換されるかを理解しなければなりません

呼び出しによってglLightfvに軽いポジションを指定する時には、軽いポジションはModelView行列スタックの現在のトップの内容により変換されます(GL_LIGHT_POSITION、…)。 もし後で、ModelView行列〈眺めが次のフレームに移行する時などの〉を変更するならば、軽いポジションはModelView行列の新しい内容により自動的に再変換されません。 もしライトのポジションをアップデートしたいならば、また、呼び出しによってglLightfvに軽いポジションを指定しなければなりません(GL_LIGHT_POSITION、…)。

どのように 行ない 質問"をし、私は私の啓発をします動いてください。さもなければ、「どのように、私は私の軽い滞在を 行ない 静かにします」は、質問に答えるために、通常十分な情報を提供しません。 よりよい答えのために、より具体的である必要があります。 ここには数いくつか具体的な質問、およびそれらの答えがあります:

目同等スペースのライトを指定する必要があります。 そうするには、ModelView行列をアイデンティティに設定し、そして、軽いポジションを指定してください。 1つのライトあたりそれに置かれるような1つのヘッドライト(を作るためにまたは 目 およびline of sight)に沿った輝きModelViewが、アイデンティティ、起源で軽いポジション(またはそれの近くの)が設定されること、および方向がネガティブなZ軸に設定されることに設定されます。

目と関連するのでライトのポジションが固定されている時には、すべてのフレームのための軽いポジションを再指定する必要はない。 一般に、プログラムが初期設定する時を1回指定します。

見方が変わると、また、ModelView行列が変わります。 これは、通常すべてのフレームの開始の時に軽いポジションを再指定する必要があるのを意味しています。 典型的なアプリケーションは以下の擬似コードによってフレームを表示します:

眺め変化を設定してください。
軽いポジション//glLightfv(GL_LIGHT_POSITION、…)発送を降ろしてください 場
面またはモデル幾何学. スワップバッファ 。

もし軽いソースが軽い据え付け品の一部であるならば、モデリング変化を指定する必要があるでしょう。従って、軽いポジションは周辺の据え付け品幾何学と同じ位置にあります

また、毎回 眺め変化 この軽いポジションを再指定する必要があります。 さらに、このライトは、軽いポジションを指定する前にModelView行列にある必要がある動的なモデリング変化を持っています。 擬似コードにおいて、以下のような何かをする必要があります:

眺め変化を設定してください
行列スタックを押してください
軽いポジション//glLightfv(GL_LIGHT_POSITION、…)を課されるライトのポジショ
ンをアップデートするために、モデル変化を設定してください ポップ行列スタック 
場面またはモデル幾何学 スワップバッファ を下方へやってください。

18.060 スポットライトを機能させるには?

スポットライトは、単に、小さな軽い円錐半径を持つポイントライトソースです。 代わりに、ポイントライトは、まさに、180度半径ライト円錐を持つ即座のライトです。 ライトの遮断パラメータを変更して軽い円錐の半径を設定してください:

glLightf(GL_LIGHT1、GL_SPOT_CUTOFF、15.f);

上記の呼び出しにより軽い円錐半径は、15度 軽い 1 のために に設定されます。 ライト円錐の全体の広がりは30度です。

スポットライトのポジションと方向は、どのような正常なライトについても設定されます

18.070 GL_MAX_LIGHTS で定義された数より多くのライトを生成するには?

第一に、OpenGLが提供するより多く本当に必要があることを確かめてください。 例えば、夜多くの建物とstreetlightsによって通り場面をする時には、あなた自身に尋ねる必要があります: すべての建物はすべての単一のstreetlightのため照明される必要がありますか? 軽い弱めと方向が見なされている時には、場面の幾何学のどのような与えられた断片でも少ない一握りのライトにより照明されるだけであると気付くかもしれません。

もしこれがケースであるならば、場面をすると入手可能なOpenGLライトを再利用するか、または循環させる必要があります

GLUT配布は有益であるかもしれない小さい例によってあなたに来ます。 それはマルチlight.cを呼びました。

もし本当に、OpenGLが提供するより多いライトによって幾何学の単一の断片を照明させる必要があるならば、何とかして、効果をシミュレーションする必要があるでしょう。 一方の方法は、いくつかまたはすべてのライトのための照明を計算することです。 別の方法は、点火効果をシミュレーションするためにテクスチャーマップを使用することです。

18.080 glMaterial*()関数の呼び出しと、glColorMaterial()の使用のどちらが速いですか?

glBegin()/glEnd()ペア内では、ほとんどのOpenGLインプリメンテーションでは、glColor3f()への呼び出しは一般に呼び出しよりglMaterialfv()のために速い。 これは、単にほとんどのインプリメンテーションがglColor3f()を調整するからであり、重大な変化を処理することは複雑で、最適化しづらいかもしれません。 この理由のために、一般に、() glColorMaterialなので、オブジェクトの物質的な絵の具を交換するための最も効率的な方法として認められています。

18.090 シーンのサイズを変更した後、照光処理が不正確になるのはのなぜ?

典型的な照明結果を達成するユニット長さであるように、OpenGL指定には垂直線が必要です。 現在のModelView行列は垂直線を変換します。 もしその行列がスケール変化を含んでいるならば、変換された垂直線はユニット長さであらず、不適当な照明問題を結果として生じます。

OpenGL1.1は、あなたを、 電話する glEnableで(GL_NORMALIZE)させて、それらが変換された後に、それがすべての垂直線ユニット長さを作ります。 これはしばしば平方根によって実装されて、幾何学制限アプリケーションのために高価であるかもしれません。

別の解決は、OpenGL1.2(そして多くの1.1のインプリメンテーションへの拡張としての)で入手可能なのでglEnableです(GL_再SCALE_NORMAL)。 平方根を計算することによる制作垂直線ユニット長さより、GL_再SCALE_NORMALは、倍率を、変換された正常に乗算します。 もしオリジナルな垂直線がユニット長さであり、ModelView行列が均一な測量を含んでいるならば、この増加によって、垂直線はユニット長さに回復するでしょう。

もしModelView行列が不均一な測量を含んでいるならば、GL_NORMALIZEは、好まれた解決です

18.100 ライティング処理を行ったら、すべてのオブジェクトが光ってしまいました。いくつかのオブジェクトだけを照らすことは出来ますか?

OpenGLが国のマシンであることを覚えていてください。 これのような何かをする必要があります:

glEnableです(GL_LIGHTING);
//、与える点火された幾何学。
glDisableです(GL_LIGHTING);
//、与える不点火であった幾何学。

18.110 OpenGL で Quake のようなライトマップを使うには?

テクスチャー・マッピングセクションでこの問題を見てください

18.120 屈折光の効果を得るには?

第一に、OpenGLがあなたのための右のAPIであるかどうかを考慮してください。 複雑なライトを達成するために、光線トレーサを使用する必要があるかもしれません 屈折など影響する 。

もしOpenGLを使いたいと確信しているならば、屈折効果を生み出すためにOpenGLが機能を提供しないことを心に留めている必要があります。 それを偽造する必要があります。 最もありそうな解決は、屈折する与えと一致しているイメージを計算することであり、マップ ライトを屈折させるプリミティブの表面上へのそれ を織ってください。

18.130 焦面をレンダリングするには?

OpenGLは、テクスチャー・マッピングを除いて、焼灼剤をすることを手助けできません。 GLUT 3.7は、どのように苛性の照明効果を達成するかをあなたに示すいくつかのデモで来ます。

18.140 自分のシーンに影を追加するには?

OpenGLは影の与えを直接サポートしません。 しかし、OpenGLにおいて、影をするためのどのような標準のアルゴリズムでも使われえます。 http://www.opengl.orgでいくつかのアルゴリズムが説明されます。 コード化チュートリアル&テクニックリンクをたどってください。そして、表現テクニックはリンクします。 照明、影、&映像セクションに下にスクロールしてください。

どのようにこの使用投射をするかを実演する例によってGLUT 3.7配布が来ること 影で覆う と型板バッファ

もし影がであるならば、投射影は理想的で、平面のオブジェクトに横たわっているだけです。 投射飛行機の上にオブジェクトを変換するために、影の使用glFrustum()の幾何学を生成できます。

型板バッファを影で覆うことは、平面であるので、影がどのようなオブジェクトにも横たわっていることを可能にするので、より柔軟か、または違っています。 基本的なアルゴリズムは「影のボリューム」を計算する必要があります。 影のボリュームの後ろの面を選び、型板価値が裏返しに正面をしてください 型板バッファに直面している 。 そして、また、型板価値が裏返しに、前の面を選ぶこと、および後ろをすること 型板バッファに直面している によって二回目を影のボリュームに与えてください。 結果は、現在、型板飛行機が、不 0の価値を、影がされるべき所に含むことです。 可能であった周囲のライトだけおよびGL_EQUALに設定されたglDepthFunc()によって二回目を場面に与えてください。 結果は、された影です。

影をするための別のメカニズムは、SIGGRAPH' 92紙 において概説されますテクスチャー・マッピングを使っている速い影と照明効果マークセガール この紙は、相対的に簡単な拡張を、影のテクスチャーマップとして深さバッファを使うためのOpenGLに記述します。 GL_EXT_depth_textureおよびGL_EXT_texture3D(またはOpenGL1.2)拡張は、この方法を使うために必要です。