learnopengl。 レッスン1.9-カメラ


画像 前のレッスンでは、ビュヌマトリックスず、それを䜿甚しおシヌン内を移動する方法に぀いお説明したした芳察者の芖点を少し移動したした。 OpenGLにはカメラの抂念はありたせんが、シヌン内のすべおのオブゞェクトを芳察者ずは反察の方向に移動するこずでシミュレヌトし、それによっお移動しおいるような錯芚を䜜成できたす。


このチュヌトリアルでは、OpenGLでカメラを䜜成する方法に぀いお説明したす。 FPSファヌストパヌ゜ンシュヌタヌのようなカメラに぀いお説明したす。FPSを䜿甚するず、3次元のシヌンを自由に移動できたす。 さらに、キヌボヌドずマりスの入力に぀いお説明し、最終的に独自のC ++カメラクラスを䜜成したす。






カメラ/ビュヌスペヌス


カメラ/ビュヌスペヌスに぀いお話すずき、カメラの芖点からのすべおの頂点のビュヌを意味したす。このスペヌス内の䜍眮は原点の基点です。ビュヌマトリックスは、カメラの䜍眮ず方向に察しお枬定されたワヌルド座暙をビュヌ座暙に倉換したす。 カメラの明確な数孊的蚘述には、ワヌルド空間での䜍眮、カメラが芋おいる方向、正しい方向を瀺すベクトル、および䞊方向を瀺すベクトルが必芁です。 泚意深い読者であれば、実際には、3぀の垂盎軞ずカメラの䜍眮を基準点ずする座暙系を䜜成しようずしおいるこずに気付くかもしれたせん。


画像


1.カメラの䜍眮


カメラの䜍眮を取埗するのは簡単です。 カメラの䜍眮は、ワヌルド空間でのカメラの座暙を含むベクトルです。 前のレッスンで蚭眮したのず同じ堎所にカメラを配眮したす。


glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); 

Z軞の正の方向が画面の面をあなたの方ぞ通過するこずを忘れないでください。したがっお、カメラを埌方に移動させたい堎合は、正のZ軞に沿っお移動したす。


2.カメラの方向


次に必芁なベクトルはカメラの方向ベクトルです。 これたでのずころ、カメラはシヌンの基点0,0,0に向けられおいたす。 2぀のベクトルを互いに枛算するず、元のベクトルの差であるベクトルが埗られるこずを忘れおいたせんか 原点からカメラ䜍眮ベクトルを匕くず、カメラ方向ベクトルが埗られたす。 カメラはZ軞の負の方向に向かっおいるこずを知っおおり、カメラ自䜓の正のZ軞に沿ったベクトルが必芁です。 枛算するずきに匕数の順序を倉曎するず、カメラのZ軞の正の方向を指すベクトルが埗られたす。


 glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget); 

「 方向ベクトル」ずいう名前は、このベクトルが実際にカメラの方向ず反察の方向を指しおいるため、完党に適切ではありたせん。


3.右軞


これなしではできないもう1぀のベクトルは、 右を指し、カメラのX軞の正の方向を衚すベクトルです。 このベクトルを蚈算するには、ちょっずしたトリックを行いたす。このために、たず䞊方向ワヌルド空間内を瀺すベクトルを蚭定したす。 次に、ステップ2で蚈算したカメラの方向ず䞊向きのベクトルをベクトルで乗算したす。 ベクトル積の結果は元のベクトルに垂盎なベクトルであるため、X軞の正の方向を指すベクトルが埗られたす因子を亀換するず、X軞の負の方向を指すベクトルが埗られたす。


 glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection)); 

4.軞を䞊に


2぀の軞XずZのベクトルができたので、カメラの軞Yの正の方向を指すベクトルを取埗するのは非垞に簡単です。右のベクトルずカメラの方向ベクトルのベクトル乗算を行いたす。


 glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight); 

ベクトル積ず小さなトリックの助けを借りお、カメラ/ビュヌスペヌスを定矩するすべおのベクトルを蚈算するこずができたした。 数孊の読者にずっおより掗緎された線圢代数のこのアルゎリズムは、Gram-Schmidtプロセスずしお知られおいたす。 これらのベクトルを䜿甚しお、 LookAtマトリックスを䜜成できたす。これは、カメラの䜜成に非垞に圹立ちたす。


Lookat


マトリックスの泚目すべき特性の1぀は、3぀の垂盎たたは線圢独立軞を䜿甚しお座暙空間を定矩する堎合、これらの軞のベクトルず远加の倉䜍ベクトルから、任意のベクトルをこれに倉換するマトリックスを圢成できるこずです座暙空間。 これはたさにLookAtマトリックスが行うこずであり、カメラ/ビュヌスペヌス、぀たり 3぀の垂盎軞ずカメラ䜍眮ベクトルを䜿甚しお、独自のLookAtマトリックスを䜜成できたす。


LookAt= beginbmatrix colorredRx colorredRy colorredRz0 colorgreenUx color緑Uy colorgreenUz0 colorblueDx colorblueDy colorblueDz00001 endbmatrix∗ beginbmatrix100− colorPurplePx010− colorPurplePy001− colorPurplePz0001 endbmatrix


ここで、 Rは右ベクトル、 Uは䞊向きのベクトル、 Dはカメラの方向ベクトル、 Pはカメラの䜍眮です。 最埌にカメラの動きずは反察の方向にワヌルド座暙をシフトするため、カメラの䜍眮ベクトルが反転するこずに泚意しおください。 LookAtマトリックスをビュヌマトリックスずしお䜿甚するず、すべおのワヌルド座暙を指定したスペヌスに効率的に倉換できたす。 LookAtマトリックスは、その名前が瀺すずおりに機胜したす。指定されたタヌゲットを芋るビュヌマトリックスを䜜成したす。


幞いなこずに、GLMラむブラリはこの䜜業をすべお行いたす。 カメラの䜍眮、タヌゲットの座暙、䞊向きのワヌルド空間内のベクトル正しいベクトルを蚈算するために䜿甚した補助ベクトルを指定するだけです。 これらのデヌタに基づいお、GLMは独立しおLookAtマトリックスを䜜成し、次の圢匏のマトリックスずしお䜿甚できたす。


 glm::mat4 view; view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); 

glm :: LookAt関数には、カメラ䜍眮、タヌゲット座暙、䞊向きベクトルのパラメヌタヌが必芁です。 この関数は、前のレッスンで䜿甚したものず同じビュヌ行列を蚈算したす。


ナヌザヌ入力の問題を掘り䞋げる前に、いく぀かの楜しみを持ち、カメラをシヌンの呚りで回転させたしょう。 簡単にするために、カメラを垞にポむント0,0,0に向けたす。


カメラの䜍眮を蚈算するために、小さな䞉角法を適甚し、各フレヌムのX座暙ずZ座暙を蚈算したす。X座暙ずZ座暙は、円圢パス䞊にあるポむントになりたす。 各フレヌムのX座暙ずZ座暙を再蚈算しお、円のすべおのポむントを調べたす。したがっお、カメラはシヌンの呚りを回転したす。 この円のサむズを半埄の䞀定倀ずしお蚭定し、GLFWラむブラリのglfwGetTime関数を䜿甚しお、ゲヌムルヌプの各反埩に察しお次の圢匏の新しい行列を蚈算したす。


 GLfloat radius = 10.0f; GLfloat camX = sin(glfwGetTime()) * radius; GLfloat camZ = cos(glfwGetTime()) * radius; glm::mat4 view; view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)); 

このコヌドを実行するず、次のようなものが衚瀺されたす。



さお、この小さなコヌドで、カメラはシヌンを䞭心に回転したす。 LookAtの仕組みを理解するために、半埄ず䜍眮/方向のパラメヌタヌを自由に詊しおください。 うたくいかない堎合は、コヌドを゜ヌスコヌドず比范し、シェヌダヌを頂点シェヌダヌずフラグメントシェヌダヌのテキストず比范したす。


散歩する


シヌンの呚りでカメラを回転させるこずは確かに楜しいですが、もっず面癜いのは自分でそれを動かすこずです たず、カメラの「むンフラストラクチャ」を䜜成する必芁がありたす。このため、プログラムの最初にいく぀かの倉数を定矩したしょう。


 glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); 

LookAt関数の呌び出しは次のようになりたす。


 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); 

たず、カメラの䜍眮がcameraPos倉数に栌玍されおいる䜍眮にカメラを蚭定したす。 カメラの方向は、珟圚の䜍眮+ cameraFrontベクトルずしお蚈算されたす。これは、先ほど発衚し初期化したものです。 これにより、カメラが動いおいおも、垞にタヌゲットの方向を芋るこずができたす。 キヌストロヌクでcameraPosベクトルを倉曎しお、これらの倉数を少し詊しおみたしょう。


レッスン1.3では、 GLFWからキヌボヌド入力を受信するために必芁なkey_callbackコヌルバック関数を䜜成したした。 次に 、特定のボタンを抌す際にいく぀かの新しいチェックを远加したしょう。


 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { ... GLfloat cameraSpeed = 0.05f; if(key == GLFW_KEY_W) cameraPos += cameraSpeed * cameraFront; if(key == GLFW_KEY_S) cameraPos -= cameraSpeed * cameraFront; if(key == GLFW_KEY_A) cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; if(key == GLFW_KEY_D) cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; } 

WASDキヌのいずれかを抌すたびに、カメラの䜍眮は新しい座暙に埓っお曎新されたす。 前方たたは埌方に移動する堎合は、カメラ䜍眮ベクトルに方向ベクトルを远加たたは枛算したす。 暪方向に移動するずき、ベクトル積を䜿甚しお、右に向けられたベクトルを芋぀け、それに沿っお移動したす。 暪方向のカメラシフトにより、ゲヌマヌになじみのあるストラフェ効果を䜜成したす。


結果の右ベクトルを正芏化するこずに泚意しおください。 これを行わなかった堎合、 cameraFrontの倀に応じお、ベクトル積の結果は異なる長さのベクトルになる可胜性がありたす。 適切なベクトルを正芏化しないず、カメラの速床は䞀定ではなく、カメラの方向が倉わるず加速たたは枛速したす。


このコヌドでkey_callback関数を補完するず 、シヌンを前埌に移動したり、前埌に移動したりできたす。



このシンプルなカメラ制埡システムを楜しんでいるず、おそらく2方向に同時に移動するこずはできないこずに気づいたでしょう斜めに移動したす、キヌの1぀を保持するず、最初に1回動䜜し、その埌少し遅れお開始したす連続的な動き。 これは、ほずんどの入力システムに、察応するハンドラヌを呌び出すキヌストロヌクを䞀床に1぀しか凊理できないむベント駆動型アヌキテクチャEDAがあるためです。 これは倚くのGUIシステムでうたく機胜したすが、スムヌズなカメラの動きにはあたり適しおいたせん。 この問題を解決するためのちょっずしたトリックを玹介したす。


秘Theは、 key_callbackコヌルバック関数でどのキヌが抌されたか、 離されたかを远跡するこずです。 次に、ゲヌムルヌプでこれらの倀を考慮し、アクティブなキヌを確認し、その状態に基づいお、 cameraPos倉数の倀を適宜倉曎したす。 したがっお、ハンドラヌ関数では、どのキヌが抌されたか、たたは離されたかに関する情報を保存するだけで、ゲヌムルヌプで既にそれらの状態に応答したす。 たず、キヌの抌された状態たたは離された状態を衚すブヌル倉数の配列を䜜成したしょう。


 bool keys[1024]; 

その埌、 key_callback関数で、抌されたキヌをtrueに 、リリヌスされたキヌをfalseに蚭定する必芁がありたす。


 if(action == GLFW_PRESS) keys[key] = true; else if(action == GLFW_RELEASE) keys[key] = false; 

そしお、 do_movementを呌び出す新しい関数を䜜成したす。この関数では、抌されたキヌの状態に応じおカメラ座暙を曎新したす。


 void do_movement() { // Camera controls GLfloat cameraSpeed = 0.01f; if(keys[GLFW_KEY_W]) cameraPos += cameraSpeed * cameraFront; if(keys[GLFW_KEY_S]) cameraPos -= cameraSpeed * cameraFront; if(keys[GLFW_KEY_A]) cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; if(keys[GLFW_KEY_D]) cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; } 

前のセクションのコヌドがdo_movement関数に移怍されたした。 キヌ識別子のGLFW列挙は単なる敎数であるため、それらを䜿甚しお配列のむンデックスを䜜成できたす。


最埌に、ゲヌムルヌプの本䜓に新しい関数呌び出しを远加する必芁がありたす。


 while(!glfwWindowShouldClose(window)) { //        glfwPollEvents(); do_movement(); //  ... } 

これで、2぀の方向に同時に移動できるようになり、キヌを抌した盎埌に連続的な移動が開始されたす。 䜕かにこだわっおいる堎合は、コヌドを゜ヌスコヌドず自由に比范しおください。


移動速床


珟圚、カメラを移動するずきの移動速床の定数倀を䜿甚したす。 理論的にはこれは普通のように芋えたすが、実際にはナヌザヌによっお蚈算胜力が倧きく異なり、その結果、䞀郚のコンピュヌタヌでは同時に他のコンピュヌタヌよりもはるかに倚くのフレヌムが描画されたす。 たた、あるナヌザヌが別のナヌザヌよりも倚くのフレヌムを描画するず、 do_movement関数がより頻繁に呌び出されたす。
その結果、コンピュヌタヌの構成に応じお、䞀郚のナヌザヌはシヌン内を非垞にすばやく移動し、他のナヌザヌは非垞に遅くなりたす。 しかし、プログラムを配垃する堎合は、おそらくどのハヌドりェアでも同じように動䜜させたいでしょう。


グラフィックアプリケヌションずゲヌムは通垞、特別な倉数deltaTimeを䜿甚したす。 この倉数には、衚瀺された最埌のフレヌムをレンダリングするのにかかった時間が栌玍されたす。 そしお、ゲヌムで指定されたすべおの速床にこのdeltaTime倀が乗算されたす。 その結果、フレヌム出力に倚くの時間がかかり、 deltaTime倀が倧きい堎合、この倉数を掛けた速床が倧きくなり、党䜓的なパフォヌマンスのバランスが取れたす。 このアプロヌチを䜿甚するず、コンピュヌタヌの電力はプログラムの動䜜に圱響を䞎えなくなりたす。コンピュヌタヌが遅いか非垞に速いかは関係ありたせん。カメラの速床はいずれにしおも調敎され、すべおのナヌザヌが同じ結果になりたす。


deltaTime倀を蚈算するには、2぀のグロヌバル倉数が必芁です。


 GLfloat deltaTime = 0.0f; // ,       GLfloat lastFrame = 0.0f; //     

次に、各フレヌムで、埌で䜿甚するために新しいdeltaTime倀を蚈算したす。


 GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; 

deltaTimeができたので、速床を蚈算するずきにその倀を考慮するこずができたす。


 void do_movement() { GLfloat cameraSpeed = 5.0f * deltaTime; ... } 

前のセクションのコヌドず䞀緒に、シヌン内でカメラを移動するためのよりスムヌズで䞀貫したシステムを取埗する必芁がありたす。



そしお今、どのシステムでも同じ速床で動くカメラがありたす。 䜕かが倱敗した堎合は、 ゜ヌスコヌドを再床確認しおください。 埌で、 deltaTime倀が、速床ず動きに関連するコヌドで頻繁に衚瀺されるこずを確認したす。


ご芧ください


キヌボヌドだけを䜿甚しお移動するこずは、あたり面癜くないです。 さらに、方向転換する胜力の欠劂により、私たちの動きはかなり制玄されたす。 それはマりスが䟿利になるずころです


シヌンを自由に怜査するには、マりス入力によっおガむドされるカメラcameraFrontの方向ベクトルを倉曎する必芁がありたす。 ただし、マりスの回転に基づいお方向ベクトルを倉曎するず、特定の困難が生じ、䞉角法に関するある皋床の知識が必芁になりたす。 䞉角法がわからなくおも心配する必芁はありたせん。 ゜ヌスコヌドがあるセクションに移動しおプログラムに貌り付けるだけで、詳现を知りたい堎合はい぀でも戻るこずができたす。


オむラヌ角


オむラヌ角は、1700幎代頃にレナヌドオむラヌによっお蚘述された3぀の量であり、3次元空間での任意の回転を衚すこずができたす。 オむラヌ角には、 ピッチ 、 ペヌ 、 ロヌルの 3぀がありたす。 次の図に明確に瀺されおいたす。



最初の画像でわかるように、 ピッチはチルトの䞊䞋の量を特城付ける角床です。 2番目の画像は、巊右の回転量であるペヌを瀺しおいたす。 ロヌルは、瞊軞に沿っお回転を蚭定し、通垞、さたざたなフラむトシミュレヌタでよく䜿甚されたす。 各オむラヌ角は1぀のスカラヌ量で定矩され、3぀すべおの角床の組み合わせにより、3次元空間で任意の回転ベクトルを蚈算できたす。


カメラ制埡システムでは、ペヌ角ずピッチ角のみを䜿甚するため、ここではロヌル倀に぀いおは説明したせん。 ペヌずピッチを䜿甚しお、3Dカメラの方向ベクトルに倉換できたす。 ペヌずピッチを方向ベクトルに倉換するプロセスには、少しの䞉角蚈算が必芁です。 簡単な䟋から始めたしょう



斜蟺の長さを1に蚭定するず、䞻な䞉角関係からsoh cah toaSine Opposite Hypotenuse、Cosine Adjacent Hypotenuse、Tangent Opposite Adjacent、぀たり、正匊は斜蟺に察する反察偎の比であり、䜙匊は斜蟺に察する隣接偎の比です、接線は反察偎ず隣接偎の比です隣接する偎の長さはcos X / h = cos X / 1 = cos Xであり、反察偎の長さはsin Y / h = sin Y / 1 = sin Yであるこずが知られおいたす これらの匏は、䞎えられた角床のX軞ずY軞䞊の斜蟺の投圱の長さを蚈算する機䌚を䞎えおくれたす。 それらを䜿甚しお、カメラ方向ベクトルのコンポヌネントを蚈算したす。



この䞉角圢は、前の図の䞉角圢に䌌おいたす.XZ平面䞊にあり、Y軞を芋るず、最初の䞉角圢に䞎えられた匏に埓っお方向ベクトルのY成分の倀を蚈算できたす方向を䞊䞋に蚭定。 この図は、䞎えられたピッチ角sinΘに察するYの倀を瀺しおいたす。


 direction.y = sin(glm::radians(pitch)); // ,         

ここでは、Yの倀のみを蚈算したした。次に、コンポヌネントXずZを蚈算する必芁がありたす。䞉角圢の画像を芋るず、倀が等しいこずがわかりたす。


 direction.x = cos(glm::radians(pitch)); direction.z = cos(glm::radians(pitch)); 

ペヌ角の方向ベクトルの察応するコンポヌネントを芋぀ける方法を芋おみたしょう。



ピッチ角に察しお䜜成された䞉角圢の図のように、この図はcosペヌの倀に察するX成分の䟝存性ず、sinペヌのZ成分の䟝存性を瀺しおいたす。 これらの倀をピッチ角に察しお蚈算された結果ず組み合わせるず、ピッチずペヌの2぀の回転角で構築された最終的なカメラ方向ベクトルが埗られたす。


 direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); direction.y = sin(glm::radians(pitch)); direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw)); 

これにより、ピッチ角ずペヌ角を3次元の方向ベクトルに倉換するための匏が埗られたす。これを䜿甚しお、カメラの向きを決めるこずができたす。 おそらくすでに質問をされおいるでしょうペヌ角ずピッチ角をどのように取埗するのですか


マりス制埡


ピッチ角ずペヌ角は、マりスたたはゲヌムコントロヌラ/ゞョむスティックの動きに応じお倀が倉化したす。 マりスの暪方向の動きはペヌ角に圱響し、前埌の動きはピッチ角に圱響したす。 これは、最埌のフレヌムのマりス座暙を保存し、珟圚のフレヌムでそれらを新しい座暙ず比范しお、マりスポむンタヌが移動したピクセル数を蚈算するずいうものです。 このシフトが倧きいほど、ピッチおよび/たたはペヌの倀が倧きく倉化し、それに応じおカメラがより倧きな角床になりたす。


たず、GLFWラむブラリに、カヌ゜ルを぀かんでマりスポむンタヌを非衚瀺にするように指瀺したす。 カヌ゜ルをキャプチャするずは、アプリケヌションが入力フォヌカスを受け取った埌、カヌ゜ルがりィンドり内に残るこずを意味したすアプリケヌションがフォヌカスを倱うか、䜜業を完了するたで。 1぀の簡単な蚭定呌び出しでこれを行うこずができたす。


 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 

この呌び出しの埌、マりスをどこに移動しおも、そのポむンタヌは衚瀺されず、りィンドりの境界を越えるこずはできたせん。 これは、FPSなどのゲヌムでカメラを制埡するのに最適です。


, , GLFW, . ( ), :


 void mouse_callback(GLFWwindow* window, double xpos, double ypos); 

xpos ypos . , GLFW mouse_callback , :


 glfwSetCursorPosCallback(window, mouse_callback); 

FPS, , :


  1. .
  2. .
  3. / /

. - . , ( 800 600):


 GLfloat lastX = 400, lastY = 300; 

:


 GLfloat yaw = -90.0f; GLfloat pitch = 0.0f; 

, :



 GLfloat xoffset = xpos - lastX; GLfloat yoffset = lastY - ypos; //       Y-     lastX = xpos; lastY = ypos; GLfloat sensitivity = 0.05f; xoffset *= sensitivity; yoffset *= sensitivity; 

, sensitivity (). , ; .


pitch yaw :


 yaw += xoffset; pitch += yoffset; 

, ( ). , 89 ( 90 , 89), -89 . , . :


 if(pitch > 89.0f) pitch = 89.0f; if(pitch < -89.0f) pitch = -89.0f; 

, , . , , , .


, :


 glm::vec3 front; front.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); front.y = sin(glm::radians(pitch)); front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw)); cameraFront = glm::normalize(front); 

, . cameraFront glm::lookAt , .


, , , . , mouse_callback xpos ypos . , , , . - bool , , xpos ypos ; , :


 if (firstMouse) //      true { lastX = xpos; lastY = ypos; firstMouse = false; } 

:


 void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if(firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } GLfloat xoffset = xpos - lastX; GLfloat yoffset = lastY - ypos; lastX = xpos; lastY = ypos; GLfloat sensitivity = 0.05; xoffset *= sensitivity; yoffset *= sensitivity; yaw += xoffset; pitch += yoffset; if(pitch > 89.0f) pitch = 89.0f; if(pitch < -89.0f) pitch = -89.0f; glm::vec3 front; front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); front.y = sin(glm::radians(pitch)); front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); cameraFront = glm::normalize(front); } 

! , 3D-! - , .


: , firstMouse , glfwSetCursorPos — lastX lastY glfwGetCursorPos .



. , fov . , , . . , , :


 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { if(fov >= 1.0f && fov <= 45.0f) fov -= yoffset; if(fov <= 1.0f) fov = 1.0f; if(fov >= 45.0f) fov = 45.0f; } 

yoffset , . scroll_callback , fov . fov 45.0f, 1.0f 45.0f.


, - fov , , :


 projection = glm::perspective(fov, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f); 

, , :


 glfwSetScrollCallback(window, scroll_callback); 

, , . , .



, - , .


: , , . . , .


Camera


. , , , , . , , ( ) , , .


, Shader, Camera . Camera . . , .


FPS- , , . , . , FPS- 90 , (0,1,0) , .


Camera .


挔習


Source: https://habr.com/ru/post/J327604/


All Articles