【问题标题】:glm::perspective explanationglm::透视解释
【发布时间】:2011-11-13 22:41:39
【问题描述】:

我试图了解以下代码的作用:

glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f);

它会创建一个projection matrix吗?剪掉任何不在用户视图中的东西? 我在API page 上找不到任何东西,我在他们网站上的 pdf 中唯一能找到的是:

glu透视:

glm::mat4 perspective(float fovy, float aspect, float zNear,
float zFar);
glm::dmat4 perspective(
double fovy, double aspect, double zNear,
double zFar);
From GLM_GTC_matrix_transform extension: <glm/gtc/matrix_transform.hpp>

但它没有解释参数。也许我错过了什么。

【问题讨论】:

    标签: opengl glm-math


    【解决方案1】:

    它创建一个投影矩阵,即描述将向量从眼睛空间转换到剪辑空间的线性方程组的矩阵。矩阵真的不是黑魔法。在 OpenGL 的情况下,它们恰好是 4×4 的数字排列:

    X_x Y_x Z_x T_x
    X_y Y_y Z_y T_y
    X_z Y_z Z_z T_z
    X_w Y_w Z_w W_w
    

    你可以将一个 4 向量乘以一个 4×4 矩阵:

    v' = M * v
    
    v'_x = M_xx * v_x + M_yx * v_y + M_zx * v_z + M_tx * v_w
    v'_y = M_xy * v_x + M_yy * v_y + M_zy * v_z + M_ty * v_w
    v'_z = M_xz * v_x + M_yz * v_y + M_zz * v_z + M_tz * v_w
    v'_w = M_xw * v_x + M_yw * v_y + M_zw * v_z + M_tw * v_w
    

    到达裁剪空间后(即投影步骤之后),图元被裁剪。裁剪产生的顶点然后进行透视划分,即

    v'_x = v_x / v_w
    v'_y = v_y / v_w
    v'_z = v_z / v_w
    ( v_w = 1 = v_w / v_w )
    

    就是这样。在所有这些转换步骤中,实际上没有什么比普通的矩阵向量乘法更多的了。

    现在很酷的是,矩阵可以用来描述一个坐标系在另一个坐标系中的相对对齐。透视变换所做的是,它让顶点 z 值也“滑入”它们的投影 w 值。并且通过透视划分一个非统一的 w 将导致顶点坐标的“失真”。 z 较小的顶点会被较小的 w 分割,因此它们的坐标会“爆炸”,而 z 较大的顶点会被“挤压”,这就是造成透视效果的原因。

    【讨论】:

      【解决方案2】:

      这是同一功能的 c 独立版本。这大致是the original的复制粘贴版本。

      # include <math.h>
      # include <stdlib.h>
      # include <string.h>
      
      typedef struct s_mat {
          float *array;
          int width;
          int height;
      } t_mat;
      
      t_mat *mat_new(int width, int height)
      {
          t_mat *to_return;
      
          to_return = (t_mat*)malloc(sizeof(t_mat));
          to_return->array = malloc(width * height * sizeof(float));
          to_return->width = width;
          to_return->height = height;
          return (to_return);
      }
      
      void mat_zero(t_mat *dest)
      {
          bzero(dest->array, dest->width * dest->height * sizeof(float));
      }
      
      void mat_set(t_mat *m, int x, int y, float val)
      {
          if (m == NULL || x > m->width || y > m->height)
              return ;
          m->array[m->width * (y - 1) + (x - 1)] = val;
      }
      
      t_mat *mat_perspective(float angle, float ratio,
              float near, float far)
      {
          t_mat *to_return;
          float tan_half_angle;
      
          to_return = mat_new(4, 4);
          mat_zero(to_return);
          tan_half_angle = tan(angle / 2);
          mat_set(to_return, 1, 1, 1 / (ratio * tan_half_angle));
          mat_set(to_return, 2, 2, 1 / (tan_half_angle));
          mat_set(to_return, 3, 3, -(far + near) / (far - near));
          mat_set(to_return, 4, 3, -1);
          mat_set(to_return, 3, 4, -(2 * far * near) / (far - near));
          return (to_return);
      }
      

      【讨论】:

      • 没有帮助,我的朋友。您不妨粘贴已编译的 x86 汇编指令。原始海报正在寻找其工作原理的解释。
      猜你喜欢
      • 2018-03-30
      • 1970-01-01
      • 2018-12-20
      • 2022-01-16
      • 1970-01-01
      • 2011-02-01
      • 2014-11-20
      • 1970-01-01
      • 2013-02-02
      相关资源
      最近更新 更多