今回、ソースがだいぶ汚れてきたので、円錐描画だけに整理しました。
ちなみに
が外積を使った法線ベクトル計算関数です。
普通、計算する側の事を考えて、法線ベクトルは大きさを1(単位ベクトル)にするんですが、
という、APIがあったので、OpenGL側で単位ベクトルにしてもらうようにしてます。
最後に指定された3つの頂点で三角平面を法線ベクトル付きで描画する関数
を各面ごとに呼んでカクカクした多面体描画成功~!
とかやってたら
一発で切り替わるのに気づきますた。
ファック。
ただ~し、その場合でも法線ベクトルの設定処理自体は省略できないみたいっす。OpenGL側が各頂点から法線ベクトル計算してるはずだから必要ないはずなんだけど、不思議だ。
glShadeModel(GL_SMOOTH)とglShadeModel(GL_FLAT)で切り替わる。
サンプルソースでは定数USE_FLATSHADINGを1か0で切り替わるようにしてます。
まあ、今後、外積を使う時もあるだろう、といういことで、ひとつ。
気を取り直して、カリング (culling)の話。
こいつは「余分なものを刈り取る」というのが元々の意味なんだけど、光源へのベクトルのかわりに視点へのベクトルで、面法線ベクトルとの角度求めた場合、90度以上になってたら裏返し状態だよねという話からきてます。
現実世界で裏面はもちろん存在するんだけど、今回のような円錐の場合、裏面は絶対描かれないわけっす。なら、そもそもZバッファで深度チェックする作業自体が無駄になるわけで、最初から裏に向いたら描かない方がよけいな計算で時間食わなくてサクサク動いていいよね。
というわけで、そういう指定がOpenGLでもできます。
てのがそれで、これを指定しておくと、面が裏を向くと消えます。
わざと、歯っ欠け状態の円錐を描画。ふっ、ソース読んでない人にも、円錐の底面を作ってないことがバレましたな。
カリング指定してないと欠けたところから裏面が見える。ま、こういう表現をしたい人のためにカリングする/しないの条件指定ができるわけですな。
サンプルソースでは定数USE_CALLINGを1か0で切り替わるようにしてます。
あと、裏面を向いた場合か表面を向いた場合かも指定できる。
定数USE_INVERT_CALLINGを1か0で切り替え。
この場合、前の面が隠されて、裏を向いた後ろ側が見えてるわけです。
最後に軽く鏡面反射も指定してみたんですよ。
て感じで、material_spec、LightSpecularは環境、拡散と同じでR,G,B,αっす。
ちなみにGL_FRONT_AND_BACKの他にGL_FRONTやGL_BACKも定数としてあるんだけど、glMaterialfvで指定できるのはGL_FRONT_AND_BACKだけっす。
表と裏で色変えてみよ~って試したら、全然無反応でやんの。
API仕様書みたらGL_FRONT_AND_BACKしか受け付けないって書いてました。
微妙~。
なんか使いどころがわからないな~。球体でないといまいち効果がわかりにくいな~。
みんなも、値をいろいろ変えてみて試してみてください。ていうかスライダーつけてリアルタイムに値を変化させて調子を見るのが正解だわな。誰かやってくれ。
鏡面反射計算ってのは、光が平面に反射した先に視点があれば、平面の材質ではなく光そのものが目に入るということを考慮した計算。いわゆる「てかり」です。
その度合いを調整することで紙のような質感から金属のような質感まで変化させることができる。ある程度だけど。いろいろな計算法が提案されててOpenGLはPhongの反射モデルを使ってるっぽい。他に3Dソフトでは標準装備のBlinn-Phongの反射モデルとかもあるけど、OpenGLでは時間がかかるので不採用。ただし、OpenGLのシェーダーを直接書いて実装してる人もいるみたいですな。
Phongの反射モデル
Blinn-Phongの反射モデル
なんかブリン博士、シューティングゲームやってはるで。
SIGGRAPH 2007 - コンピュータ・アニメーション・フェスティバル開幕
ま、いまいち消化不良気味だけど、いったん切り上げて、次回はテクスチャマッピング!
------------
サンプルプロジェクト:es6.zip
ちなみに
calcnormal
が外積を使った法線ベクトル計算関数です。
普通、計算する側の事を考えて、法線ベクトルは大きさを1(単位ベクトル)にするんですが、
glEnable(GL_NORMALIZE);
という、APIがあったので、OpenGL側で単位ベクトルにしてもらうようにしてます。
最後に指定された3つの頂点で三角平面を法線ベクトル付きで描画する関数
drawTriangle
を各面ごとに呼んでカクカクした多面体描画成功~!
とかやってたら
glShadeModel(GL_FLAT);
一発で切り替わるのに気づきますた。
ファック。
ただ~し、その場合でも法線ベクトルの設定処理自体は省略できないみたいっす。OpenGL側が各頂点から法線ベクトル計算してるはずだから必要ないはずなんだけど、不思議だ。
glShadeModel(GL_SMOOTH)とglShadeModel(GL_FLAT)で切り替わる。
サンプルソースでは定数USE_FLATSHADINGを1か0で切り替わるようにしてます。
まあ、今後、外積を使う時もあるだろう、といういことで、ひとつ。
気を取り直して、カリング (culling)の話。
こいつは「余分なものを刈り取る」というのが元々の意味なんだけど、光源へのベクトルのかわりに視点へのベクトルで、面法線ベクトルとの角度求めた場合、90度以上になってたら裏返し状態だよねという話からきてます。
現実世界で裏面はもちろん存在するんだけど、今回のような円錐の場合、裏面は絶対描かれないわけっす。なら、そもそもZバッファで深度チェックする作業自体が無駄になるわけで、最初から裏に向いたら描かない方がよけいな計算で時間食わなくてサクサク動いていいよね。
というわけで、そういう指定がOpenGLでもできます。
glEnable(GL_CULL_FACE);
てのがそれで、これを指定しておくと、面が裏を向くと消えます。
わざと、歯っ欠け状態の円錐を描画。ふっ、ソース読んでない人にも、円錐の底面を作ってないことがバレましたな。
カリング指定してないと欠けたところから裏面が見える。ま、こういう表現をしたい人のためにカリングする/しないの条件指定ができるわけですな。
サンプルソースでは定数USE_CALLINGを1か0で切り替わるようにしてます。
あと、裏面を向いた場合か表面を向いた場合かも指定できる。
glCullFace(GL_BACK);
定数USE_INVERT_CALLINGを1か0で切り替え。
この場合、前の面が隠されて、裏を向いた後ろ側が見えてるわけです。
最後に軽く鏡面反射も指定してみたんですよ。
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_spec);
glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
て感じで、material_spec、LightSpecularは環境、拡散と同じでR,G,B,αっす。
ちなみにGL_FRONT_AND_BACKの他にGL_FRONTやGL_BACKも定数としてあるんだけど、glMaterialfvで指定できるのはGL_FRONT_AND_BACKだけっす。
表と裏で色変えてみよ~って試したら、全然無反応でやんの。
API仕様書みたらGL_FRONT_AND_BACKしか受け付けないって書いてました。
微妙~。
なんか使いどころがわからないな~。球体でないといまいち効果がわかりにくいな~。
みんなも、値をいろいろ変えてみて試してみてください。ていうかスライダーつけてリアルタイムに値を変化させて調子を見るのが正解だわな。誰かやってくれ。
鏡面反射計算ってのは、光が平面に反射した先に視点があれば、平面の材質ではなく光そのものが目に入るということを考慮した計算。いわゆる「てかり」です。
その度合いを調整することで紙のような質感から金属のような質感まで変化させることができる。ある程度だけど。いろいろな計算法が提案されててOpenGLはPhongの反射モデルを使ってるっぽい。他に3Dソフトでは標準装備のBlinn-Phongの反射モデルとかもあるけど、OpenGLでは時間がかかるので不採用。ただし、OpenGLのシェーダーを直接書いて実装してる人もいるみたいですな。
Phongの反射モデル
Blinn-Phongの反射モデル
なんかブリン博士、シューティングゲームやってはるで。
SIGGRAPH 2007 - コンピュータ・アニメーション・フェスティバル開幕
ま、いまいち消化不良気味だけど、いったん切り上げて、次回はテクスチャマッピング!
------------
サンプルプロジェクト:es6.zip