OpenGL笔记十七之正交投影变更实行-glm::ortho函数

打印 上一主题 下一主题

主题 862|帖子 862|积分 2586

OpenGL笔记十七之正交投影变更实行-glm:rtho函数


—— 2024-07-30 晚上

bilibili赵新政老师的教程看后笔记
code review!

  
1.glm:rtho函数

glm:rtho 函数是 OpenGL 数学库 GLM (OpenGL Mathematics) 中用于天生正交投影矩阵的函数。正交投影矩阵在渲染2D场景或需要保持对象真实尺寸的3D场景时非常有用。glm:rtho 函数的定义如下:
  1. glm::mat4 glm::ortho(
  2.     float left,
  3.     float right,
  4.     float bottom,
  5.     float top,
  6.     float zNear,
  7.     float zFar
  8. );
复制代码
参数详解


  • left: 视锥体的左边界。
  • right: 视锥体的右边界。
  • bottom: 视锥体的下边界。
  • top: 视锥体的上边界。
  • zNear: 视锥体的近剪裁面。
  • zFar: 视锥体的远剪裁面。
返回值

glm:rtho 返回一个 glm::mat4 类型的 4x4 正交投影矩阵。
工作原理

正交投影矩阵用于将3D坐标转换为2D屏幕坐标,它不会像透视投影矩阵那样产生间隔缩放效果。正交投影矩阵的天生通过以下步骤实现:

  • 缩放变更

    • 将对象的坐标从视锥体的范围 [left, right] 映射到标准扮装备坐标的范围 [-1, 1]。
    • 同理,将对象的坐标从 [bottom, top] 和 [zNear, zFar] 映射到 [-1, 1]。

  • 平移变更

    • 将对象的中央移到原点。

正交投影矩阵公式

正交投影矩阵的公式如下:

示例代码

以下是一个现实使用 glm:rtho 函数的示例:
  1. #include <glm/glm.hpp>
  2. #include <glm/gtc/matrix_transform.hpp>
  3. #include <iostream>
  4. int main() {
  5.     float left = -1.0f;
  6.     float right = 1.0f;
  7.     float bottom = -1.0f;
  8.     float top = 1.0f;
  9.     float zNear = 0.1f;
  10.     float zFar = 100.0f;
  11.     glm::mat4 orthoMatrix = glm::ortho(left, right, bottom, top, zNear, zFar);
  12.     // 打印正交投影矩阵
  13.     for (int i = 0; i < 4; ++i) {
  14.         for (int j = 0; j < 4; ++j) {
  15.             std::cout << orthoMatrix[i][j] << " ";
  16.         }
  17.         std::cout << std::endl;
  18.     }
  19.     return 0;
  20. }
复制代码
输出结果

运行上述代码将天生并打印正交投影矩阵,输出如下:
  1. 1 0 0 0
  2. 0 1 0 0
  3. 0 0 -0.0200202 -1.002
  4. 0 0 0 1
复制代码
解释



  • 第一行和第二行: 映射 x 和 y 坐标范围从 [-1, 1] 到 [-1, 1],由于 left = -1, right = 1, bottom = -1, top = 1。
  • 第三行: 映射 z 坐标范围从 0.1 到 100 到 -1 到 1。
  • 第四行: 齐次坐标。
通过明确 glm:rtho 函数的原理和使用方法,可以方便地在 OpenGL 程序中实现正交投影,从而渲染出符合预期的2D或3D场景。
2.实行一:使用glm的ortho函数

NDC坐标
  1. viewMatrix = glm::lookAt(glm::vec3(0.0f,0.0f,1.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  2. orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
  3. float positions[] = {
  4.         -0.5f, -0.5f, 0.0f,
  5.         0.5f, -0.5f, 0.0f,
  6.         0.0f,  0.5f, 0.0f,
  7. };
复制代码
运行

2.实行二:使用非NDC数据


  1. viewMatrix = glm::lookAt(glm::vec3(0.0f,0.0f,1.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  2. orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
  3. float positions[] = {
  4.         -1.0f, 0.0f, 0.0f,
  5.         1.0f, 0.0f, 0.0f,
  6.         0.0f,  1.0f, 0.0f,
  7. };
复制代码
运行

3.实行三:将顶点向世界坐标系的-z方向推进较大范围(-5)(剪裁)

  1. float positions[] = {
  2.         -1.0f, 0.0f, -5.0f,
  3.         1.0f, 0.0f, -5.0f,
  4.         0.0f,  1.0f, -5.0f,
  5. };
复制代码
运行

4.实行四:将可视范围盒子向相机坐标系的+x方向推进1个单元

  1. orthoMatrix = glm::ortho(-1.0f, 3.0f, -2.0f, 2.0f, 2.0f, -2.0f);float positions[] = {
  2.         -1.0f, 0.0f, -5.0f,
  3.         1.0f, 0.0f, -5.0f,
  4.         0.0f,  1.0f, -5.0f,
  5. };
复制代码
运行

5.实行五:保持可视范围盒子不动,动相机(1.0,0.0,0.1)

  1. viewMatrix = glm::lookAt(glm::vec3(1.0f,0.0f,0.1f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  2. orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
  3. float positions[] = {
  4.         -1.0f, 0.0f, 0.0f,
  5.         1.0f, 0.0f, 0.0f,
  6.         0.0f,  1.0f, 0.0f,
  7. };
复制代码
运行

5.实行六:保持可视范围盒子不动,动相机(1.0,0.0,1.0-剪裁)

  1. viewMatrix = glm::lookAt(glm::vec3(1.0f,0.0f,1.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  2. orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
  3. float positions[] = {
  4.         -1.0f, 0.0f, 0.0f,
  5.         1.0f, 0.0f, 0.0f,
  6.         0.0f,  1.0f, 0.0f,
  7. };
复制代码
运行

6.vs

  1. #version 330 core
  2. layout (location = 0) in vec3 aPos;
  3. layout (location = 1) in vec3 aColor;
  4. layout (location = 2) in vec2 aUV;
  5. out vec3 color;
  6. out vec2 uv;
  7. uniform mat4 transform;
  8. uniform mat4 viewMatrix;
  9. uniform mat4 projectionMatrix;
  10. //aPos作为attribute(属性)传入shader
  11. //不允许更改的
  12. void main()
  13. {
  14.         vec4 position = vec4(aPos, 1.0);
  15.         position = projectionMatrix * viewMatrix * transform * position;
  16.         gl_Position = position;
  17.         color = aColor;
  18.         uv = aUV;
  19. }
复制代码
7.fs

  1. #version 330 core
  2. out vec4 FragColor;
  3. in vec3 color;
  4. in vec2 uv;
  5. uniform sampler2D sampler;
  6. void main()
  7. {
  8.   FragColor = texture(sampler, uv);
  9. }
复制代码
8.main.cpp

  1. #include <iostream>
  2. #include "glframework/core.h"
  3. #include "glframework/shader.h"
  4. #include <string>
  5. #include <assert.h>//断言
  6. #include "wrapper/checkError.h"
  7. #include "application/Application.h"
  8. #include "glframework/texture.h"
  9. /*
  10. *┌────────────────────────────────────────────────┐
  11. *│ 目           标: 学习使用正交投影矩阵
  12. *│ 讲    师: 赵新政(Carma Zhao)
  13. *│ 拆分目标:
  14. *                                -1 学会使用glm的ortho函数 (orthographic)
  15.                                         ***ortho的数据是摄像机坐标系下***
  16.                                         1.1 使用glm的ortho函数,生成了一个正交投影矩阵       
  17.                                                 此矩阵的作用是:生成一个投影盒子,将内部顶点转化到NDC坐标系
  18.                                         1.2 在vertexShader当中,添加了projectionMatrix的uniform变量       
  19.                                         1.3 在每一帧渲染之前,更新projectionMatrix这个uniform
  20.                                        
  21. *                                -2 学习使用非NDC数据
  22. *                                        1 按照标准案例进行构建(ppt上)
  23. *                                        2 将顶点向世界坐标系的-z方向推进较大范围(-5)(剪裁)
  24. *                                        3 将可视范围盒子向相机坐标系的+x方向推进1个单位
  25. *                                        4 保持可视范围盒子不动,动相机(1.0,0.0,0.1)(1.0,0.0,1.0-剪裁)
  26. *
  27. *                                -3 理解剪裁
  28. *└────────────────────────────────────────────────┘
  29. */
  30. GLuint vao;
  31. Shader* shader = nullptr;
  32. Texture* texture = nullptr;
  33. glm::mat4 transform(1.0f);
  34. glm::mat4 viewMatrix(1.0f);
  35. glm::mat4 orthoMatrix(1.0f);
  36. void OnResize(int width, int height) {
  37.         GL_CALL(glViewport(0, 0, width, height));
  38.         std::cout << "OnResize" << std::endl;
  39. }
  40. void OnKey(int key, int action, int mods) {
  41.         std::cout << key << std::endl;
  42. }
  43. void prepareVAO() {
  44.         //1 准备positions colors
  45.         // float positions[] = {
  46.         //         -0.5f, -0.5f, 0.0f,
  47.         //         0.5f, -0.5f, 0.0f,
  48.         //         0.0f,  0.5f, 0.0f,
  49.         // };
  50.         float positions[] = {
  51.                 -1.0f, 0.0f, 0.0f,
  52.                 1.0f, 0.0f, 0.0f,
  53.                 0.0f,  1.0f, 0.0f,
  54.         };
  55.         float colors[] = {
  56.                 1.0f, 0.0f,0.0f,
  57.                 0.0f, 1.0f,0.0f,
  58.                 0.0f, 0.0f,1.0f,
  59.         };
  60.         float uvs[] = {
  61.                 0.0f, 0.0f,
  62.                 1.0f, 0.0f,
  63.                 0.5f, 1.0f,
  64.         };
  65.         unsigned int indices[] = {
  66.                 0, 1, 2,
  67.         };
  68.         //2 VBO创建
  69.         GLuint posVbo, colorVbo, uvVbo;
  70.         glGenBuffers(1, &posVbo);
  71.         glBindBuffer(GL_ARRAY_BUFFER, posVbo);
  72.         glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
  73.         glGenBuffers(1, &colorVbo);
  74.         glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
  75.         glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
  76.         glGenBuffers(1, &uvVbo);
  77.         glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
  78.         glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);
  79.         //3 EBO创建
  80.         GLuint ebo;
  81.         glGenBuffers(1, &ebo);
  82.         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  83.         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  84.         //4 VAO创建
  85.         glGenVertexArrays(1, &vao);
  86.         glBindVertexArray(vao);
  87.         //5 绑定vbo ebo 加入属性描述信息
  88.         //5.1 加入位置属性描述信息
  89.         glBindBuffer(GL_ARRAY_BUFFER, posVbo);
  90.         glEnableVertexAttribArray(0);
  91.         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0);
  92.         //5.2 加入颜色属性描述数据
  93.         glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
  94.         glEnableVertexAttribArray(1);
  95.         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0);
  96.         //5.3 加入uv属性描述数据
  97.         glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
  98.         glEnableVertexAttribArray(2);
  99.         glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0);
  100.         //5.4 加入ebo到当前的vao
  101.         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  102.         glBindVertexArray(0);
  103. }
  104. void prepareShader() {
  105.         shader = new Shader("assets/shaders/vertex.glsl","assets/shaders/fragment.glsl");
  106. }
  107. void prepareTexture() {
  108.         texture = new Texture("assets/textures/goku.jpg", 0);
  109. }
  110. void prepareCamera() {
  111.         //lookat:生成一个viewMatrix
  112.         //eye:当前摄像机所在的位置
  113.         //center:当前摄像机看向的那个点
  114.         //up:穹顶向量
  115.         viewMatrix = glm::lookAt(glm::vec3(1.0f,0.0f,1.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  116.         // viewMatrix = glm::lookAt(glm::vec3(1.0f,0.0f,0.1f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  117.         // viewMatrix = glm::lookAt(glm::vec3(0.0f,0.0f,1.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
  118. }
  119. void prepareOrtho() {
  120.         orthoMatrix = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 2.0f, -2.0f);
  121. }
  122. void render() {
  123.         //执行opengl画布清理操作
  124.         GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
  125.         //绑定当前的program
  126.         shader->begin();
  127.         shader->setInt("sampler", 0);
  128.         shader->setMatrix4x4("transform", transform);
  129.         shader->setMatrix4x4("viewMatrix", viewMatrix);
  130.         shader->setMatrix4x4("projectionMatrix", orthoMatrix);
  131.         //绑定当前的vao
  132.         GL_CALL(glBindVertexArray(vao));
  133.         //发出绘制指令
  134.         GL_CALL(glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0));
  135.         GL_CALL(glBindVertexArray(0));
  136.         shader->end();
  137. }
  138. int main() {
  139.         if (!app->init(800, 600)) {
  140.                 return -1;
  141.         }
  142.         app->setResizeCallback(OnResize);
  143.         app->setKeyBoardCallback(OnKey);
  144.         //设置opengl视口以及清理颜色
  145.         GL_CALL(glViewport(0, 0, 800, 600));
  146.         GL_CALL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));
  147.         prepareShader();
  148.         prepareVAO();
  149.         prepareTexture();
  150.         prepareCamera();
  151.         prepareOrtho();
  152.         while (app->update()) {
  153.                 render();
  154.         }
  155.         app->destroy();
  156.         return 0;
  157. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表