首页 > 其他分享 >【Vulkan入门】24-控制视角

【Vulkan入门】24-控制视角

时间:2025-01-10 09:30:33浏览次数:3  
标签:24 VulkanRenderer glm camera key SDL Vulkan event 入门

文章目录

先叨叨

在实现深度测试后,已经可以实现简单的3D渲染了。为了今后能更好的观察3D效果,所以需要在渲染时动态变换视角。本篇就介绍如何动态变换视角。

代码信息

  • repository: https://gitee.com/J8_series/easy-car-ui
  • tag:24-MouseControl
  • url: https://gitee.com/J8_series/easy-car-ui/tree/24-MouseControl

具体思路

glm::lookAt可以生成视角矩阵,因此主要思路就是在每帧渲染之前通过这个方法生成视角矩阵。
glm::lookAt的第一个参数是视角的位置,第二个参数时视角盯着的点,第三个参数是视角的正上方向量。
我们定义一个Camera类,该类有三个属m_posistionm_facem_up,分别代表Camera的位置、朝向、正上方。
定义了Camera类之后就可以这样使用glm::lookAt

mvp.view = glm::lookAt(m_camera.m_posistion, m_camera.m_posistion + m_camera.m_face, m_camera.m_up);

接下来就是根据用户输入,更新m_posistionm_facem_up即可。

我希望向第一视角游戏一样通过 W、S、A、D 控制视角的前后左右。按住鼠标左键可以控制视角朝向, 朝向由Yaw和Pitch角定义,Yaw的值由鼠标X值变化量得到,Pitch角由鼠标Y值的变化量得到 。

关键代码

SDL_AppEvent

这个方法是SDL接受输入的方法,在这个方法里我们会Camera的状态。

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    if (event->type == SDL_EVENT_QUIT) {
        return SDL_APP_SUCCESS;  /* end the program, reporting success to the OS. */
    }

    if (event->type == SDL_EVENT_KEY_DOWN)
    {
        if (event->key.key == SDLK_W)
        {
            VulkanRenderer::GetInstance().m_camera.m_isForward = true;
        }
        else if (event->key.key == SDLK_S)
        {
            VulkanRenderer::GetInstance().m_camera.m_isRetreated = true;
        }
        else if (event->key.key == SDLK_A)
        {
            VulkanRenderer::GetInstance().m_camera.m_isLeftwards = true;
        }
        else if (event->key.key == SDLK_D)
        {
            VulkanRenderer::GetInstance().m_camera.m_isRightwards = true;
        }
    }
    
    if (event->type == SDL_EVENT_KEY_UP)
    {
        if (event->key.key == SDLK_W)
        {
            VulkanRenderer::GetInstance().m_camera.m_isForward = false;
        }
        else if (event->key.key == SDLK_S)
        {
            VulkanRenderer::GetInstance().m_camera.m_isRetreated = false;
        }
        else if (event->key.key == SDLK_A)
        {
            VulkanRenderer::GetInstance().m_camera.m_isLeftwards = false;
        }
        else if (event->key.key == SDLK_D)
        {
            VulkanRenderer::GetInstance().m_camera.m_isRightwards = false;
        }
    }

    if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)
    {
        if (event->button.button == SDL_BUTTON_LEFT)
        {
            isMouseLeftButtonDown = true;
            lastX = event->motion.x;
            lastY = event->motion.y;
            deltaYaw = 0;
            deltaPitch = 0;
        }
    }

    if (event->type == SDL_EVENT_MOUSE_BUTTON_UP)
    {
        if (event->button.button == SDL_BUTTON_LEFT)
        {
            isMouseLeftButtonDown = false;
            VulkanRenderer::GetInstance().m_camera.CommitFace(deltaYaw, deltaPitch);
        }
    }

    if (event->type == SDL_EVENT_MOUSE_MOTION)
    {
        if (true == isMouseLeftButtonDown)
        {
            offsetX = event->motion.x - lastX;
            offsetY = lastY - event->motion.y;

            deltaYaw = offsetX * 0.1;
            deltaPitch = offsetY * 0.1;


            VulkanRenderer::GetInstance().m_camera.UpdateFace(deltaYaw, deltaPitch);
        }
    }

    return SDL_APP_CONTINUE;  /* carry on with the program! */
}

Camera::UpdatePositon

该方法根据Camera的状态更新Camera的位置。

void Camera::UpdatePositon(float deltaSeconds)
{
    if (true == m_isForward)
    {
        m_posistion += m_face * m_speed;
    }
    if (true == m_isRetreated)
    {
        m_posistion -= m_face * m_speed;
    }
    if (true == m_isLeftwards)
    {
        m_posistion -= glm::normalize(glm::cross(m_face, m_up)) * m_speed;
    }
    if (true == m_isRightwards)
    {
        m_posistion += glm::normalize(glm::cross(m_face, m_up)) * m_speed;
    }
}

Camera::UpdateFace

该方法根据deltaYaw和deltaPitch 更新Camera的m_face

void Camera::UpdateFace(float deltaYaw, float deltaPitch)
{
    m_deltaYaw = deltaYaw;
    m_deltaPitch = deltaPitch;

    float tmpPitch = m_pitch + m_deltaPitch;

    if (tmpPitch > 89.0f)
    {
        tmpPitch = 89.0f;
    }
    if (tmpPitch < -89.0f)
    {
        tmpPitch = -89.0f;
    }

    glm::vec3  direction {};
    direction.x = cos(glm::radians(tmpPitch)) * cos(glm::radians(m_yaw + m_deltaYaw));
    direction.y = sin(glm::radians(tmpPitch));
    direction.z = cos(glm::radians(tmpPitch)) * sin(glm::radians(m_yaw + m_deltaYaw));

    m_face = glm::normalize(direction);
}

VulkanRenderer::UpdateUniformBuffer

在该方法中调用glm::lookAt更新视角矩阵

void VulkanRenderer::UpdateUniformBuffer(float deltaSeconds)
{
    static auto startTime = std::chrono::high_resolution_clock::now();

    auto currentTime = std::chrono::high_resolution_clock::now();
    float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();

    m_camera.UpdatePositon(deltaSeconds);

    ModelViewProj mvp{};
    mvp.model = glm::mat4(1.0f);
    mvp.view = glm::lookAt(m_camera.m_posistion, m_camera.m_posistion + m_camera.m_face, m_camera.m_up);
    mvp.proj = glm::perspective(glm::radians(45.0f), m_width / (float) m_height, 0.1f, 10.0f);

    memcpy(m_uniformBufferMapped, &mvp, sizeof(mvp));
}

运行效果

我不会录制gif格式图片,不过现在已经可以用鼠标和键盘控制视角了
在这里插入图片描述

标签:24,VulkanRenderer,glm,camera,key,SDL,Vulkan,event,入门
From: https://blog.csdn.net/patronwa/article/details/145040704

相关文章

  • 【专题】2024年直播、短视频:抖音、小红书、快手行业报告汇总PDF合集分享(附原数据表)
    原文链接: https://tecdat.cn/?p=38697在当今数字化飞速发展的时代,直播、短视频行业已然成为了大众生活与商业运作中不容忽视的重要力量,正不断重塑着信息传播与消费的格局。2024年,这一领域更是呈现出多元且复杂的发展态势。从内容创作者生态来看,抖音、小红书、快手等平台各有热......
  • 2024年最新IDE激活码,激活到2099年,可用一辈子!
    KQ8KMJ77TY-eyJsaWNlbnNlSWQiOiJLUThLTUo3N1RZIiwibGljZW5zZWVOYW1lIjoiVW5pdmVyc2l0YXMgTmVnZXJpIE1hbGFuZyIsImxpY2Vuc2VlVHlwZSI6IkNMQVNTUk9PTSIsImFzc2lnbmVlTmFtZSI6IkpldOWFqOWutuahtiDorqTlh4blupflkI0iLCJhc3NpZ25lZUVtYWlsIjoibmtucWFyY214a0AxNjMuY29tIiwibGljZW5z......
  • 2024年生成式AI技术实践进展和应用突破(附最佳实践资料)
    2024年生成式AI技术在多个领域取得了显著的实践进展和应用突破,以下是一些关键的实践案例和技术进展:视觉影像领域可灵AI:采用类Sora的“DiT”结构,以Transformer替代传统扩散模型中的U-Net,显著提升了视频生成的处理能力和效率。其核心优势在于能生成大幅度的合理运动、模拟物理......
  • 跟我一起学 Python 数据处理(二十五):PDF 文件处理入门与工具抉择
    跟我一起学Python数据处理(二十五):PDF文件处理入门与工具抉择在数据处理的征程中,我们时常会遇到各种格式的数据,而PDF作为一种常见但处理难度较大的格式,掌握其处理方法至关重要。本文旨在与大家共同探索Python处理PDF文件的奥秘,帮助大家提升数据处理技能。一、PDF......
  • AI Agent(智能体)技术白皮书(Google,2024)中文+英文
    译者序本文翻译自2024年Google团队的一份 Agents白皮书,作者JuliaWiesinger,PatrickMarlow,VladimirVuskovic。Agent可以理解为是一个扩展了大模型出厂能力的应用程序。工具的使用,是人类区别于动物的标志——也是Agent区别于大模型的标志。水平及维护精力所......
  • Python + Appium 自动化操作微信入门(超详细)
    Appium是一个开源的自动化测试工具,支持Android、iOS平台上的原生应用,支持Java、Python、PHP等多种语言。Appium封装了Selenium,能够为用户提供所有常见的JSON格式的Selenium命令以及额外的移动设备相关的控制命令,比如:多点触控手势、屏幕朝向等。环境本文主要环境如下:......
  • NOIP2024 游记
    \(100+15+0+20=\)寄。好了,本学年已经没有可以打的ccf比赛了。Day-?NOIP前两天在补历年NOIP真题,有没有用我不知道。但现在看来应该把lxl的DS题先补了。/llDay0车上看了板子,然后把Sublime的配置里的一团乱码硬是背下来了。考场在人大附中,不过个人觉得机房条件......
  • 前端报告 2024:全新数据,深度解析未来趋势
    温馨提示:此报告为国际版全球报告,其中所涉及的技术应用、工具偏好、开发者习惯等情况反映的是全球前端开发领域的综合态势。由于国内外技术发展环境、行业生态以及企业需求等存在差异,可能有些内容并不完全契合国内的实际情况,请大家理性阅读,批判性地吸收其中的观点与信息。......
  • 奇异搞笑的2024年末总结
    本来不想写年终总结这个东西的,但是,我晚上拉肚子后睡不着了,那就用手机写写吧,刚好可以练我的双拼能力。突然反应过来,高考就是今年的事,但我的记忆已经模糊了。激素水平下降了,小电影也看多了,记忆力就这样下降了,过去都过去了。大抵上是我觉得高中没什么好怀念的吧,不过是一个人闷着头读......
  • NRF24L01模块STM32-调试心得:报错 1E
    前言环境:芯片:STM32F103C8T6Keil:V5.24.2.0调试时我们会尝试读取STATUS寄存器状态来了解模块目前的状态,但是我们在读取时至为0x1E,这就很纳闷,根据寄存器描述0x1E:对应寄存器4:1,关系有:达到最大重发次数        RXFIFO为空,第四位很好理解也......