透视投影矩阵的构建

投影矩阵最终建立的是一个平截头体(也可以称为台),在这种变换下呈现远小近大的效果。这里我将我学到知识记录下来,以后备忘用。

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44926299。欢迎同行前来探讨。

       首先是使用OpenGL的glFrustum函数,它要求传入的是前后、左右、上下等参数,这要求这个平截头体是轴对称的。由它构成的矩阵是为:

       如果我们使用的不是glFrustum,而是glPerspetive,那么它的公式就更加简单了:

       我们可以借助Qt来验证一下:

 

 
  1. #include <math.h>

  2. #include <QDebug>

  3. #include <QCoreApplication>

  4. #include <QVector3D>

  5. #include <QMatrix4x4>

  6.  
  7. qreal deg2Rad( qreal deg )

  8. {

  9. return deg * 2 * M_PI / 180.0f;

  10. }

  11.  
  12. int main(int argc, char *argv[])

  13. {

  14. QCoreApplication a(argc, argv);

  15.  
  16. qreal fov = 45.0;

  17. qreal aspectRatio = 16.0 / 9.0;

  18. qreal near = 0.5;

  19. qreal far = 500.0;

  20.  
  21. qreal left = -near * tan( deg2Rad( fov ) / 2.0 ) * aspectRatio;

  22. qreal right = near * tan( deg2Rad( fov ) / 2.0 ) * aspectRatio;

  23. qreal bottom = -near * tan( deg2Rad( fov ) / 2.0 );

  24. qreal top = near * tan( deg2Rad( fov ) / 2.0 );

  25.  
  26. QMatrix4x4 matrix;

  27. matrix.frustum( left, right, bottom, top, near, far );

  28.  
  29. qDebug( ) << "The normal perspective matrix is: " << matrix;

  30.  
  31. QMatrix4x4 matrix_2;

  32. float* d = matrix_2.data( );

  33. d[0] = 2 * near / ( right - left );

  34. d[1] = 0.0;

  35. d[2] = 0.0;

  36. d[3] = 0.0;

  37. d[4] = 0.0;

  38. d[5] = 2 * near / ( top - bottom );

  39. d[6] = 0.0;

  40. d[7] = 0.0;

  41. d[8] = ( right + left ) / ( right - left );

  42. d[9] = ( top + bottom ) / ( top - bottom );

  43. d[10] = -( far + near ) / ( far - near );

  44. d[11] = -1;

  45. d[12] = 0.0;

  46. d[13] = 0.0;

  47. d[14] = -2 * far * near / ( far - near );

  48. d[15] = 0.0;

  49.  
  50. qDebug( ) << "The user manipulated matrix is: " << matrix_2;

  51.  
  52. QMatrix4x4 matrix_3;

  53. d = matrix_3.data( );

  54. d[0] = 1.0 / ( tan( deg2Rad( fov ) / 2.0 ) * aspectRatio );

  55. d[1] = 0.0;

  56. d[2] = 0.0;

  57. d[3] = 0.0;

  58. d[4] = 0.0;

  59. d[5] = 1.0 / ( tan( deg2Rad( fov ) / 2.0 ) );

  60. d[6] = 0.0;

  61. d[7] = 0.0;

  62. d[8] = 0.0;

  63. d[9] = 0.0;

  64. d[10] = -( far + near ) / ( far - near );

  65. d[11] = -1;

  66. d[12] = 0.0;

  67. d[13] = 0.0;

  68. d[14] = -2 * far * near / ( far - near );

  69. d[15] = 0.0;

  70.  
  71. qDebug( ) << "Another user manipulated matrix is: " << matrix_3;

  72.  
  73. return a.exec( );

  74. }

注意:和OpenGL一样,矩阵是列主序的,所以上述公式在赋值的时候要一列一列地读,先读第一列的四个数,然后第二列……运行结果如下:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值