前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >opengl入门-摄像机

opengl入门-摄像机

作者头像
公号sumsmile
发布2020-06-15 11:09:13
1.1K0
发布2020-06-15 11:09:13
举报

摄像机实现的原理:通过位移+旋转对原物体的坐标反向变换,模拟相机机位的变化,详细推演可以参考《计算机视觉基础》第6章-几何变换 p105和第13章节-交互式图形流程。核心公式:

从右往左看,第一个矩阵调整原始点的位移,模拟相机的反向位移,第二个矩阵模拟坐标的旋转。没有理解原理硬记下也是可以的。

一、实现一个基础的摄像机环绕效果
  1. 效果
  1. opengl中的实现:幸运的是,GLM已经提供了这些支持。我们要做的只是定义一个摄像机位置,一个目标位置和一个表示世界空间中的上向量的向量(我们计算右向量使用的那个上向量)。 接着GLM就会创建一个LookAt矩阵,我们可以把它当作我们的观察矩阵:
代码语言:javascript
复制
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));
  1. 代码和上一篇中区别很小,对view的实现做了调整,代码如下:
代码语言:javascript
复制
        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));

方便观察,把每个立方体自旋转部分的逻辑注释掉了

代码语言:javascript
复制
        for (unsigned int i = 0; i < 10; i++) {
            glm::mat4 model;
            model = glm::translate(model, cubePositions[i]);
//            float angle = 20.0f * i + (float)glfwGetTime();
//            model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
            ourShader.setMat4("model", model);
            glDrawArrays(GL_TRIANGLES, 0, 36);
        }
二、按键调整相机机位

1.效果

按键调整

2.代码说明,有两处需要修改 // main函数里的变量提出来,方便在processInput里全局引用

代码语言:javascript
复制
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);

// 在processInput中监听按键,W S A D分别控制上下左右移动,跟打CS游戏一样,注意,左右移动机位需要归一化,目的是控制移动速度平稳,因为初始值在操作过程中是个变值。

代码语言:javascript
复制
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){
        glfwSetWindowShouldClose(window, true);
    }
    
    float cameraSpeed = 0.05f;
    
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
        cameraPos += cameraSpeed * cameraFront;
    } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
        cameraPos -= cameraSpeed * cameraFront;
    } else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
        cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
        cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
    }
}

// while循环中view的计算

代码语言:javascript
复制
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

注意!!view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);一开始对cameraPos + cameraFront怎么也不理解,既然是表示方向,方向向量的标量值是没有意义的,很奇怪,做了个实验,写死glm::lookAt第二个参数看效果,发现第二个值如果和第一个值一样大,屏幕空白,只要第二个值比第一个参数小,哪怕只小一点点效果就正常。仔细看了glm::lookAt方法的说明,第二个参数并不是向量,是一个三维坐标,即相机拍摄的方向,如果这个点和相机镜头是同一个点,那该往哪个方向看呢?系统自己就傻了。

代码语言:javascript
复制
view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 2.9f), cameraUp);
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、实现一个基础的摄像机环绕效果
  • 二、按键调整相机机位
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档