首页 > 技术文章 > Opengl_11_相机空间

liuhan333 2017-02-01 09:16 原文

1,
相机相当于我们的眼睛,使对物体的操作都已相机(观察者)为视角。
物体在世界坐标空间,使其乘以观察矩阵(View Matrix),转换到相机空间,然后我们就可以不管世界空间只需要考虑在相机空间中了。

2,先在世界空间设置相机位置
摄像机位置简单来说就是世界空间中一个指向摄像机位置的向量。
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);

摄像机的方向,现在我们让摄像机指向场景原点:(0, 0, 0)。
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);

右向量(Right Vector),它代表摄像机空间的x轴的正方向
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));


我们已经有了x轴向量(cameraRight )z轴向量(cameraDirection) ,获取一个指向摄像机的正y轴向量就相对简单了:我们把右向量和方向向量进行叉乘:
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

这样,我们就创建了所有构成观察/摄像机空间的向量(可以看作相机位置为原点,xyz三个轴相互垂直的观察矩阵(View Matrix)),
使用这些摄像机向量我们就可以创建一个LookAt矩阵了。

3,
使用矩阵的好处之一是如果你使用3个相互垂直(或非线性)的轴定义了一个坐标空间,你可以用这3个轴外加一个平移向量来创建一个矩阵,并且你可以用这个矩阵乘以任何向量来将其变换到那个坐标空间。这正是LookAt矩阵所做的,现在我们有了3个相互垂直的轴和一个定义摄像机空间的位置坐标,我们可以创建我们自己的LookAt矩阵了:

其中R是右向量,U是上向量,D是方向向量P是摄像机位置向量。位置向量是相反的,因为我们最终希望把世界平移到与我们自身移动的相反方向。
把这个LookAt矩阵作为观察矩阵可以很高效地把所有世界坐标变换到刚刚定义的观察空间。LookAt矩阵就像它的名字表达的那样:它会创建一个看着(Look at)给定目标的观察矩阵。

幸运的是,GLM已经提供了这些支持。我们要做的只是定义一个摄像机位置,一个目标位置和一个表示世界空间中的上向量的向量(我们计算右向量使用的那个上向量)。接着GLM就会创建一个LookAt矩阵,我们可以把它当作我们的观察矩阵:

glm::mat4 view;
view = glm::lookAt(cameraPos, 
           cameraTarget, 
           up);

glm::LookAt函数需要一个位置、目标和上向量。它会创建一个观察矩阵。

glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
            glUniformMatrix4fv(glGetUniformLocation(ID, "projection"), 1, GL_FALSE, &projection[0][0]);


while (!glfwWindowShouldClose(window)){
glm::mat4 view;
        float radius = 10.0f;
        float camX   = sin(glfwGetTime()) * radius;
        float camZ   = cos(glfwGetTime()) * radius;
        view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
            glUniformMatrix4fv(glGetUniformLocation(ID, "view"), 1, GL_FALSE, &view[0][0]);


model = glm::translate(model, cubePositions[i]);
            float angle = 20.0f * i;
            model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
            glUniformMatrix4fv(glGetUniformLocation(ID, "model"), 1, GL_FALSE, &model[0][0]);
}
#version 430 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0f);
    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}



4,

Cross:两个向量的差积计算可以得到一个和这两个向量所在平面垂直的向量。
Normalize:将向量转换成单位长度。


U = U.Cross(N)确保UN垂直
V = N.Cross(U)得到up向量。

4,


5,

//默认视角从原点朝Z轴正方向,如果worldpos.z <= 0 是被裁剪掉看不见的。



//
由于相机Z轴位置设为-5,物体可以放在Z轴大于-5的区间被看见。
//
所以worldpos.z也能看见了。,

推荐阅读