OpenGL学习之路10----透视投影

代码放在github上

本文根据教程:ogldev进行扩充学习,一步步从零开始,记录学习历程

一、透视投影

1.1 透视投影定义

中心投影法:
- 光线照射物体时,可在预设的地面或墙面上产生影子,根据这一自然现象,经科学的抽象总结,产生了投影法。
- 投射线通过物体,向选定的面投射,并在该面上得到图形的方法称为投影法
- 投射线汇交于投射中心的投影法叫做中心投影法

中心投影法示意图:
这里写图片描述

透视投影是用中心投影法将形体投射到投影面上,从而获得的一种较为接近视觉效果的单面投影图

透视投影符合人们心理习惯,即离视点近的物体大,离视点远的物体小,远到极点即为消失,成为灭点

透视投影示意图:
这里写图片描述

1.2 视锥体

当使用投影矩阵,场景中的并行线会在屏幕上的一个消失点处汇聚到一起,物体离得越远,则变得越小。看到的空间区域被称为视椎体。

通过视椎体投影:
这里写图片描述

1.3 必要的参数

  • 90°视野和45°视野:
    这里写图片描述

  • 屏幕的宽高比: 因为我们在一个宽高相等(-1到1)的单位化窗口里展示坐标系,而通常电脑屏幕的宽度是大于高度的(比如1024*768),所以需要在水平方向上的轴线上步骤更加密集的坐标点,竖直方向上相对稀疏。

  • 到远处和近处的距离:需要把离相机太近和太远的物体裁掉

1.4 透视投影矩阵

正如我们之前教程对要绘制的图形进行平移、旋转和缩放操作时,则用平移矩阵、旋转矩阵和缩放矩阵跟图形的位置坐标进行相乘即可得到变换后的图形坐标。(可以点击链接进入教程学习)
OpenGL学习之路6—-平移,旋转和缩放变换

我们对图形进行一个透视投影操作,也其实就是找到透视投影矩阵跟我们的图形位置相乘得到透视投影后的图形位置。

如果想了解投影矩阵的详细推导步骤请移步原教程
Perspective Projection

这里直接给出透视投影矩阵并稍作解释
这里写图片描述
- a: 相当于焦距,大小为 1/tan(视野/2)

    即当视野为90°,则a=1/tan(90°/2)=1

- aspect:屏幕的宽高比,宽度/高度
- f:到远处平面的距离,必须正值且大于到近处平面的距离
- n:到近处平面的距离,必须是正值

1.5 代码中得到一个透视投影矩阵

struct PersProjInfo
{
    float FOV;
    float Width;
    float Height;
    float zNear;
    float zFar;
};
inline void PersProjectionMatrix44(Matrix44f m, PersProjInfo p)
{
    const float ar = p.Width / p.Height;
    const float zRange = p.zNear - p.zFar;
    const float tanHalfFOV = tanf(DegToRad(p.FOV / 2.0f));

    m[0] = 1.0f / (tanHalfFOV * ar); m[4] = 0.0f;                m[8] = 0.0f;                           m[12] = 0.0;
    m[1] = 0.0f;                     m[5] = 1.0f / tanHalfFOV;   m[9] = 0.0f;                           m[13] = 0.0;
    m[2] = 0.0f;                     m[6] = 0.0f;                m[10] = (-p.zNear - p.zFar) / zRange;  m[14] = 2.0f*p.zFar*p.zNear / zRange;
    m[3] = 0.0f;                     m[7] = 0.0f;                m[11] = 1.0f;                          m[15] = 0.0;

}
  • 设置一个结构体用来存放透视投影的配置参数,分别是视野(角度)、屏幕宽度、屏幕高度、到近处平面的距离和到远处平面的距离
  • 通过一个内联函数PersProjectionMatrix44()传入要设置的透视投影矩阵和配置参数结构体实例,设置相应参数的透视投影的值

二、代码解释

2.1 增加管线类的相关代码

opengl_pipeline.h:

#ifndef __OPENGL_PIPELINE_H
#define __OPENGL_PIPELINE_H

#include "opengl_math.h"

class Pipeline
{
private:
    Vector3f m_scale;
    Vector3f m_worldPos;
    Vector3f m_rotateInfo;

    Matrix44f m_Wtransformation;
    Matrix44f m_ProjTransformation;
    Matrix44f m_WPtransformation;

    PersProjInfo m_persProjInfo;
public:
    Pipeline() {
        LoadVector3(m_scale,1.0f, 1.0f, 1.0f);
        LoadVector3(m_worldPos,0.0f, 0.0f, 0.0f);
        LoadVector3(m_rotateInfo,0.0f, 0.0f, 0.0f);
    }
    void Scale(float ScaleX, float ScaleY, float ScaleZ)
    {
        LoadVector3(m_scale, ScaleX, ScaleY, ScaleZ);
    }

    void WorldPos(float x, float y, float z)
    {
        LoadVector3(m_worldPos, x, y, z);
    }
    void Rotate(float RotateX, float RotateY, float RotateZ)
    {
        LoadVector3(m_rotateInfo, RotateX, RotateY, RotateZ);
    }
    void SetPerspectiveProj(const PersProjInfo& p)
    {
        m_persProjInfo = p;
    }

    const Matrix44f* GetWorldTrans();
    const Matrix44f* GetProjTrans();
    const Matrix44f* GetWPTrans();

};

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenGL ES 中的投影矩阵可以使用透视投影交投影两种方式进行设置。 透视投影是一种模拟人眼观察物体的方式,近处的物体看起来比远处的物体大,而且在远处的物体看起来比在近处的物体更小。在 OpenGL ES 中,透视投影的矩阵通常由 glFrustum() 或者 gluPerspective() 函数生成。这些函数所需要的参数包括视角、画面宽高比、近裁剪面和远裁剪面的距离。 交投影则是一种无论远近都能保持物体大小一致的投影方式。在 OpenGL ES 中,交投影的矩阵通常由 glOrtho() 函数生成。这个函数需要指定可视空间的左、右、上、下、近、远六个面。 下面是一个简单的 OpenGL ES 代码示例,使用透视投影交投影来绘制一个立方体: ```c++ // 使用透视投影绘制立方体 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1, 10); // 绘制立方体 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -5); glRotatef(angle, 1, 1, 1); glColor3f(1, 0, 0); glutWireCube(2); // 使用交投影绘制立方体 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-2, 2, -2, 2, 1, 10); // 绘制立方体 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -5); glRotatef(angle, 1, 1, 1); glColor3f(0, 0, 1); glutWireCube(2); ``` 其中,glFrustum() 函数生成的透视投影矩阵,可以让离观察者比较近的物体显得比较大,而离观察者比较远的物体显得比较小。glOrtho() 函数生成的交投影矩阵,则可以让物体无论离观察者多远,都保持一致的大小。 需要注意的是,在使用不同的投影方式时,需要先将当前矩阵模式设置为投影矩阵模式,然后再进行矩阵的设置和变换。最后,需要将矩阵模式设置回模型视图矩阵模式,以便绘制物体。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值