首页 > 编程语言 > 详细

c++光栅化软渲染器(四)三维渲染篇

时间:2021-04-01 13:48:09      阅读:46      评论:0      收藏:0      [点我收藏+]

 

引言

  上一篇我们完成了2D渲染器,接下来要实现3D几何体的绘制。其实3D比2D没有多太多内容,无非就是多了几步空间变换和一个视角控制的部分。首先,我们设置一下视角,为之后的三维渲染做准备。

 

空间变换与相机

  这里我们来简单谈谈空间变换。它的概念在unity渲染管线那篇文章中有详细介绍,大概就是要从模型空间变换到世界空间、变换到视角空间、变换到裁剪空间、变换到ndc空间、变换到屏幕坐标。因为这部分属于图形学入门的知识,再加上自己太懒不想打太多数学符号,因此直接上几张自己曾经做过的白板ppt:

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

 

  好了,相信你对这几个空间变换有了一定的了解,那么接下来我们就补充一下Matrix类:

 1 void Matrix::lookat(Vector3D camPos,Vector3D tarPos,Vector3D up){
 2     Vector3D xAxis,yAxis,zAxis;
 3     zAxis=-(tarPos-camPos);
 4     zAxis.normalize();
 5     xAxis=up.product(zAxis);
 6     xAxis.normalize();
 7     yAxis=zAxis.product(xAxis);
 8     yAxis.normalize();
 9     normalize();
10     ele[0][0]=xAxis.x;
11     ele[0][1]=xAxis.y;
12     ele[0][2]=xAxis.z;
13     ele[1][0]=yAxis.x;
14     ele[1][1]=yAxis.y;
15     ele[1][2]=yAxis.z;
16     ele[2][0]=zAxis.x;
17     ele[2][1]=zAxis.y;
18     ele[2][2]=zAxis.z;
19     ele[0][3]=-(xAxis.dot(camPos));
20     ele[1][3]=-(yAxis.dot(camPos));
21     ele[2][3]=-(zAxis.dot(camPos));
22 }
23 
24 void Matrix::perspective(float fovy, float aspect, float near, float far){
25     ele[0][0]=1/(aspect*tanf(fovy/2));
26     ele[1][1]=1/(tanf(fovy/2));
27     ele[2][2]=-((far+near)/(far-near));
28     ele[2][3]=-(2*far*near)/(far-near);
29     ele[3][2]=-1;
30 }
31 
32 void Matrix::viewPort(int left,int top,int width,int height){
33     normalize();
34     ele[0][0]=static_cast<float>(width)/2.0f;
35     ele[1][1]=-static_cast<float>(height)/2.0f;
36     ele[0][3]=static_cast<float>(left)+static_cast<float>(width)/2.0f;
37     ele[1][3]=static_cast<float>(top)+static_cast<float>(height)/2.0f;
38 }

 

  其中lookat矩阵是从世界空间转换到视角空间的矩阵,perspective矩阵是从视角空间转换到裁剪空间的矩阵,viewport是从ndc空间转换到屏幕坐标的矩阵,要注意的是中间其实还有一步从裁剪空间坐标转移到ndc空间的变换,方法很简单,只需要给x、y、z、w都除以w即可,因此我没有单写它的矩阵,但大家千万不要忘了这一步。

 

  在三维世界中,相机是一个非常重要的物体,它决定了视口的视野。由于一般情况下游戏引擎中的相机以对象的形式呈现,因此我把这里的相机单独做成了一个类。

 1 #ifndef MAINCAMERA_H
 2 #define MAINCAMERA_H
 3 #include"vector3d.h"
 4  
 5 class maincamera
 6 {
 7 public:
 8     Vector3D pos,goal,up;
 9     float fov,asp,near,far;
10 public:
11     maincamera();
12     maincamera(Vector3D mpos,Vector3D mgoal,Vector3D mup,float mfov,float masp,float mnear,float mfar);
13     void rotateY(float angle);
14 };

 

  首先相机作为一种对象(游戏物体),成员参数必须包括它在世界空间中的位置(pos)和旋转角度(这里使用的goal和up,分别表示相机看向的点以及相机自身的z轴方向,通过这两个向量可以唯一确定下来相机的旋转角度)。此外,在空间变换中我们知道:相机空间向裁剪空间变换时,其裁剪矩阵由相机的张角(fov)、asp(宽高比)、near(近裁剪面距离)、far(远裁剪面距离)来决定,因此这四个变量也必须要定义。
  成员函数比较简单,构造函数种可以对相机的transform和属性参数进行设置,这里定义了一个rotateY函数,作用就是绕着Y轴旋转angle的角度,每帧调用rotateY就可以起到一种环绕浏览的效果。

 1 #include "maincamera.h"
 2 #include "vector4d.h"
 3 #include "matrix.h"
 4 #include "stdio.h"
 5  
 6 maincamera::maincamera()
 7 {
 8     pos=Vector3D(0,4,-8);
 9     goal=Vector3D(0,0,0);
10     up=Vector3D(0,1,0);
11     fov=45*3.14/180.f;
12     asp=1280/767.f;
13     near=1.f;
14     far=50.f;
15 }
16 maincamera::maincamera(Vector3D mpos, Vector3D mgoal, Vector3D mup, float mfov, float masp, float mnear, float mfar)
17 {
18     pos=mpos;
19     goal=mgoal;
20     up=mup;
21     fov=mfov;
22     asp=masp;
23     near=mnear;
24     far=mfar;
25 }
26  
27 void maincamera::rotateY(float angle)
28 {
29     Vector4D pos4(pos.x,pos.y,pos.z,1);
30     Matrix rot;
31     rot.normalize();
32     rot.rotationY(angle);
33     pos4=rot*pos4;
34     pos.setX(pos4.x);
35     pos.setY(pos4.y);
36     pos.setZ(pos4.z);
37 }

 

c++光栅化软渲染器(四)三维渲染篇

原文:https://www.cnblogs.com/puluomi/p/14605238.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!