2017-09-18 9 views
0

ターゲットは、形状を描くこと、三角形をピクセル完全にすること(頂点はピクセルで指定する必要があります)を3次元で変形できることです。OpenGLパースペクティブ投影ピクセル完全描画

私は直交射影行列でそれを試してみたし、すべてが正常に動作しますが、形状は任意の深さを持っていない - 私はY軸の周りに回転させた場合、私はちょうどXのまわりでそれをスケーリングしまうように見えます軸。 (直交の投影が明らかにこのように動作するため)。今私はの視点投影とそれを試してみたい。しかし、この投影法では、座標系が完全に変化します。このため、三角形の頂点をピクセルで指定することはできません。また、ウィンドウのサイズが変わると、(座標系が変更されたために)形状のサイズも変わります。

透視投影の座標系を変更して、正射影を使用するように頂点を指定できる方法はありますか?あるいは、誰かが最初の文章で説明した目標を達成するためのアイデアを持っていますか?

+5

2つの要件は、両方を同時に達成することが本質的に不可能です整数座標。あなたが望むことができる最高のものは、頂点座標が1:1をピクセルに変換する1つの "z平面"を持つことですが、その平面の前または後ろに、非整数で終わります。 – Thomas

+0

この "z平面"を達成する最良の方法は何でしょうか?私はこれがまさに私が望むものだと思う。 – Met

+1

その「ピクセル平面」の「z」値は、投影のFOVに依存します。シンプルな三角ジオメトリで簡単に見つけることができます。 – derhass

答えて

0

投影行列には、シーンの3D点からビューポートの2D点へのマッピングが記述されています。それは、アイ空間からクリップ空間に変換し、クリップ空間の座標は、クリップ座標のwコンポーネントで除算することによって正規化装置座標(NDC)に変換されます。 NDCは(-1、-1、-1)から(1,1,1)の範囲内にある。

投影法では、投影行列は、ピンホールカメラから見た世界の3D点からビューポートの2D点へのマッピングを記述します。
カメラ錐台(切り捨てられたピラミッド)内のアイ空間座標は、立方体(正規化されたデバイス座標)にマッピングされます。

enter image description here

透視投影行列:

r = right, l = left, b = bottom, t = top, n = near, f = far 

2*n/(r-l)  0    0    0 
0    2*n/(t-b)  0    0 
(r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1  
0    0    -2*f*n/(f-n) 0 

:Iビュー行列は恒等行列であると仮定し、したがって、ビュー空間座標が等しい

aspect = w/h 
tanFov = tan(fov_y * 0.5); 

prjMat[0][0] = 2*n/(r-l) = 1.0/(tanFov * aspect) 
prjMat[1][1] = 2*n/(t-b) = 1.0/tanFov 


世界の座標に
頂点の座標が1:1に変換されたポリゴンを描画する場合は、ポリゴンをビューポートに平行な平面に描画する必要があります。これは、すべての点が同じ深さの描画でなければならないことを意味します。
深さは、逆投影行列による正規化されたデバイス座標内の点の変換がピクセル内の頂点座標を与えるように選択する必要があります。逆投影行列による変換によって与えられる同次座標は、同次座標のw成分で除算されて、デカルト座標を得る必要があることに注意してください。
これは飛行機の深さは投影の視野角に依存すること、を意味:飛行機の

float vp_w = .... // width of the viewport in pixel 
float vp_h = .... // height of the viewport in pixel 
float fov_y = ..... // field of view angle (y axis) of the view port in degrees < 180° 

gluPerspective(fov_y, vp_w/vp_h, 1.0, vp_h*2.0f); 

その後depthZと:

あなたは、このような透視投影を設定すると仮定すると、 1:頂点座標の画素1の関係は、次のように計算される:

float angRad = fov_y * PI/180.0; 
float depthZ = -vp_h/(2.0 * tan(angRad/2.0)); 

注、ビューポートへの投影の中心点は(0,0)であるので、左下隅ポイント(-vp_w/2,-vp_h/2,depthZ)であり、右上の角点は(vp_w/2,,)である。遠近法プロジェクションの近平面が-depthZより小さく、遠方平面が-depthZより大きいことを確認してください。

はさらに参照:視点変換を非につながることができます分割ステップを伴うため

+0

ありがとう、あなたのアプローチはうまくいきます。私は期待どおりに動作しないものが1つしかありません。 300x300の四角形を描くと、x軸に45度の角度で回転し、私の四分円の視点はウィンドウ/ビューポートの高さに応じて変化します。これは、幅が変更された場合には発生しません。動画をアップロードしてこの動作を表示しました:https://www.youtube.com/watch?v=XI_WaX3W8qM&feature=youtu.be これを修正する方法はありますか? – Met

+0

@Metリンクは私にとってはうまくいかない!おそらくあなたのYouTubeアップロードへのアクセス権はありません。 – Rabbid76

+0

@注釈の視野角はビューポートの高さに合わせて調整されるので、 'fov_y'と呼ばれます。幅は常に 'aspect = w/h'で修正されます。そして、平面の深さは、ビューポートの高さに依存します。depthZ = -vp_h /(2.0 * tan(angRad/2.0)); – Rabbid76

関連する問題