首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >glm::透视解释

glm::透视解释
EN

Stack Overflow用户
提问于 2011-11-14 06:41:39
回答 2查看 57K关注 0票数 33

我正在尝试理解以下代码的作用:

代码语言:javascript
复制
glm::mat4 Projection = glm::perspective(35.0f, 1.0f, 0.1f, 100.0f);

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

gluPerspective:

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

但它不能解释参数。也许我漏掉了什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-14 07:31:42

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

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

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

在到达剪辑空间之后(即,在投影步骤之后),基元被裁剪。然后,由裁剪产生的顶点正在经历透视分割,即

代码语言:javascript
复制
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的顶点将被“挤压”,这就是导致透视效果的原因。

票数 30
EN

Stack Overflow用户

发布于 2015-07-23 20:58:23

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

代码语言:javascript
复制
# 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);
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8115352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档