OpenGL模型变换,透视变换,视角变换以及它们的外部交互代码。
不管是何种坐标变换,最终都直接落实到顶点上,顶点被传入shader,因此在shader中变换它。
模型变换
- 模型变换,就是对顶点的变换,无论此顶点在 [世界空间坐标系],还是[OpenGL标准坐标系]
- 将顶点与之前提到的坐标左乘即可:
-
- gl_Position = modelTransMatrix * vec4(originPos,1.0);
-
- modelTransMatrix = TX(4,4) * SX(4,4) * ZX(4,4)
-
- 最终:gl_Position = TX(4,4) * SX(4,4) * ZX(4,4) * vec4(originPos,1.0);
视角变换
- 要完成各种奇妙的视角变换,真的很复杂。。。(哭)
- 视角变换涉及 Camera :
-
- Camera所摄制的内容就是屏幕显示的内容。
-
- 针对Camera本身的变换:包括Camera位移,Camera自身旋转。
-
- Camera变换涉及的参数:
-
-
- Camera的中心 [CameraPos] 就是 [世界空间坐标系] 下的 [屏幕中心 | OpenGL标准坐标系原点]。
- Camera位置的变换,最终影响CameraPos,也是对顶点坐标的一次平移变换
- CameraPos在世界空间的正位移变换,等价于顶点在OpenGL标准坐标系中的负位移变换。
- Camera的中心 [CameraPos] 就是 [世界空间坐标系] 下的 [屏幕中心 | OpenGL标准坐标系原点]。
-
-
-
- Camera还拥有以下属性:
- Direction > Camera的指向向量:是 [空间中的某点] 指向摄像机的方向向量
- 也是世界坐标空间中,将摄像机设置为原点后,顶点所处位置指向摄像机的 方向向量。
- 当Camera直线前进靠近顶点时,顶点坐标其实是在做完全相反的变换来靠近Camera,Camera就需要给出指导顶点相反移动的ViewMatrix
- 指向向量就是指导顶点进行 相反变换的[参数]。
- Direction > Camera的指向向量:是 [空间中的某点] 指向摄像机的方向向量
- Camera还拥有以下属性:
-
-
-
-
- CameraRight > Camera自身的右方向向量
- glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); //世界空间坐标上方向单位向量。
- glm::vec3 CameraRight = glm::normalize(glm::cross(CameraUp, Direction));
- CameraRight > Camera自身的右方向向量
-
-
-
-
-
- CameraUp > Camera自身的上方向向量
- glm::vec3 CameraUp = glm::cross(Direction, CameraRight);
- CameraUp > Camera自身的上方向向量
-
-
-
-
-
- Camera的朝向:Camera的 三个偏航角
- 垂直于 世界坐标系Y轴的, 旋转角:YAW
- 垂直于 世界坐标系X轴的, 旋转角:PITCH
- 垂直于 世界坐标系Z轴的, 旋转角:ROLL
- Camera的朝向:Camera的 三个偏航角
-
-
-
-
-
- 更改Camera的朝向,可以先通过YAW,PITCH,ROLL来更改:Direction,再更新R,U
- 最后通过更改LookAtMatrix中的RUD,来更改视角。
- 约定:以垂直平面的横向坐标轴为起始轴面向当前坐标轴的正方向开始旋转:沿顺时针为负,逆时针为正
- 如:x垂直于yz,左手系时 z轴为横向坐标轴,面向x轴正方向旋转。
-
-
-
-
- LookAtMatrix:
- 一种viewMatrix,它可以立刻将摄像机指向 [目标方向|目标位置 (不建议在此处直接更改目标位置) ]。
- 使用LookAtMatrix,可以直接统计对Camera的所有变换。
- LookAtMatrix:
- [Rx, Ry, Rz, 0] * [1, 0, 0, Px]
- [Ux, Uy, Uz, 0] * [0, 1, 0, Py]
- [Dx, Dy, Dz, 0] * [0, 0, 1, Pz]
- [0, 0, 0, 0] * [0, 0, 0, 1]
- LookAtMatrix:
-
-
- Camera变换的一些解决方法:
- Camera平移变换:
- 生成LookAtMatrix:
- LookAtMatrix = glm::lookAt(
- CameraPos, > 加减增量:glm::vec3(float Offset_x,float Offset_y,float Offset_z);
- CameraTarget, > 加减增量:glm::vec3(float Offset_x,float Offset_y,float Offset_z);
- glm提供的,lookAt生成函数所需的CameraTarget,可以视为CameraPos + CameraDirection(与Direction相反)
- CameraDirection = (
- cos(glm::radians(pitch)) * cos(glm::radians(yaw)),
- sin(glm::radians(pitch)),
- cos(glm::radians(pitch)) * sin(glm::radians(yaw)),
- ); //因为实际不太使用roll视角,所以这里不加入Roll。
- WorldUp > 无需改变
- );
- LookAtMatrix = glm::lookAt(
- 不使用LookAtMatrix:
- 直接向view左乘[位移矩阵],等价于 > 向[model矩阵]中添加一个[位移变换矩阵]。
- 生成LookAtMatrix:
- Camera旋转变换:
- 生成LookAtMatrix:
- LookAtMatrix = glm::lookAt(
- CameraPos, > 无需改变
- CameraTarget, > 重置CameraTarget = CameraPos + NewCameraDirection
- CameraDirection = (
- cos(glm::radians(pitch + angleSpinBy_x)) * cos(glm::radians(yaw + angleSpinBy_y)),
- sin(glm::radians(pitch + angleSpinBy_x)),
- cos(glm::radians(pitch + angleSpinBy_x)) * sin(glm::radians(yaw + angleSpinBy_y)),
- ); //因为实际不太使用roll视角,所以这里不加入Roll。
- CameraDirection = (
- WorldUp > 无需改变
- );
- LookAtMatrix = glm::lookAt(
- 生成LookAtMatrix:
- Camera平移变换:
- Camera变换的一些解决方法:
-
-
- Camera视角下,世界空间的旋转,其实就是一个 [全局的model旋转变换]
-
- 创建Camera就是将 屏幕中心[OpenGL标准坐标系] 封装起来:
- Camera.h:
-
1 #ifndef CAMERA_H 2 #define CAMERA_H 3 4 #include <glew.h> 5 #include <glm.hpp> 6 #include <gtc/matrix_transform.hpp> 7 8 //default value 9 const float ORIGIN_YAW = 90.0f; 10 const float ORIGIN_PITCH = 0.0f; 11 const float ORIGIN_ROLL = 0.0f; 12 const glm::vec3 ORIGIN_CAMERAPOS = glm::vec3(0.0f,0.0f,-3.0f); 13 14 //应该考虑将此条内容封装到更高级别的定义中: 15 const glm::vec3 WorldUp = glm::vec3(0.0f, 1.0f, 0.0f); 16 17 class Camera 18 { 19 private: 20 21 unsigned int MeshShaderID; 22 //Camera 当前渲染的Mesh的shaderID。 23 // ------------------------------------------------------------- 24 25 float YAW; 26 float PITCH; 27 float ROLL; 28 // Angle To Init CameraDirection 29 // ------------------------------------------------------------- 30 31 glm::vec3 CameraDirection; 32 glm::vec3 CameraPos; 33 // CameraTarget = CameraPos + CameraDirection 34 // LookAt = glm::lookAt(CameraPos, CameraTarget, WorldUp); 35 // ------------------------------------------------------------- 36 37 glm::vec3 Direction; 38 glm::vec3 CameraUp; 39 glm::vec3 CameraRight; 40 // 自定义LookAt时可能会用到的三个参数,如下公式: 41 // LookAt = [[R,0],[U,0],[D,0],glm::vec4(0)] * [E + P] 42 // ------------------------------------------------------------- 43 44 glm::mat4 ViewMatrix; 45 //暂存的ViewMatrix, 降帧时,可以考虑在同一帧中 将原本的多次不同类型的view变换 压缩到一次中(就是将多次变换集成到同一个viewMatrix中) 46 47 public: 48 Camera(unsigned int MESH_SHADERID); 49 50 //Camera(glm::vec3 cameraPos, glm::vec3 cameraTarget); 51 //Camera(glm::vec3 cameraPos, glm::vec3 cameraDirection); 52 //Camera(glm::vec3 cameraPos, glm::vec3 direction); 53 //Camera(glm::vec3 cameraPos, float pitch = OriginPITCH, float yaw = OriginYAW); 54 //Camera(glm::vec3 cameraPos, float pitch = OriginPITCH, float yaw = OriginYAW, float roll = OriginROLL); 55 //保留的构造器接口------------------------------------------------------------------------------------------- 56 57 void ownerChange(unsigned int MESH_SHADERID); 58 void cameraMove(float Offset_x, float Offset_y, float Offset_z, bool AUTO_UPDATE_VIEWMATRIX = true); 59 void cameraSpin(float AngleOffsetAround_x, float AngleOffsetAround_y, bool AUTO_UPDATE_VIEWMATRIX = true); 60 61 void commitViewMatrix(); //将ViewMatrix提交给当前设置的MeshShaderID; 62 63 ~Camera(); 64 }; 65 66 #endif
- Camera.cpp:
-
1 #include "Camera.h" 2 3 void Camera::commitViewMatrix() 4 { 5 glUniformMatrix4fv(glGetUniformLocation(MeshShaderID, "view"), 1, GL_FALSE, &ViewMatrix[0][0]); 6 } 7 8 Camera::Camera(unsigned int MESH_SHADERID) 9 { 10 //TODO: Minimal initialization; 11 12 YAW = ORIGIN_YAW; 13 PITCH = ORIGIN_PITCH; 14 ROLL = ORIGIN_ROLL; 15 16 CameraPos = ORIGIN_CAMERAPOS; 17 CameraDirection = glm::vec3 18 ( 19 cos(glm::radians(ORIGIN_YAW))*cos(glm::radians(ORIGIN_PITCH)), 20 sin(glm::radians(ORIGIN_PITCH)), 21 sin(glm::radians(ORIGIN_YAW))*cos(glm::radians(ORIGIN_PITCH)) 22 ); 23 24 ViewMatrix = glm::lookAt(CameraPos, CameraDirection + CameraPos, WorldUp); 25 commitViewMatrix(); 26 } 27 28 void Camera::ownerChange(unsigned int MESH_SHADERID) 29 { 30 MeshShaderID = MESH_SHADERID; 31 } 32 33 void Camera::cameraMove(float Offset_x, float Offset_y, float Offset_z, bool AUTO_UPDATE_VIEWMATRIX) 34 { 35 //TODO: 36 CameraPos += glm::vec3(Offset_x, Offset_y, Offset_z); 37 38 if (AUTO_UPDATE_VIEWMATRIX) 39 { 40 ViewMatrix = glm::lookAt(CameraPos, CameraDirection + CameraPos, WorldUp); 41 commitViewMatrix(); 42 } 43 } 44 45 void Camera::cameraSpin(float AngleOffsetAround_x, 46 float AngleOffsetAround_y, 47 bool AUTO_UPDATE_VIEWMATRIX) 48 { 49 //TODO: 50 PITCH += AngleOffsetAround_x; 51 YAW += AngleOffsetAround_y; 52 CameraDirection = glm::vec3 53 ( 54 cos(glm::radians(YAW))*cos(glm::radians(PITCH)), 55 sin(glm::radians(PITCH)), 56 sin(glm::radians(YAW))*cos(glm::radians(PITCH)) 57 ); 58 59 if (AUTO_UPDATE_VIEWMATRIX) 60 { 61 ViewMatrix = glm::lookAt(CameraPos, CameraDirection + CameraPos, WorldUp); 62 commitViewMatrix(); 63 } 64 } 65 66 67 Camera::~Camera() 68 { 69 }
透视变换:

浙公网安备 33010602011771号