# 封装的意义
emmm,讲渲染部分比我规划里要长一点.... 伪光照三角形并不能让我满足,回顾一下:
- 第七节抽象了Shader类,提供了shader源码读取、编译、链接 、启动等API 。
- 第八节完善了Shader类对Uniform的操作,补全了投影矩阵与鼠标输入。
但是main.cpp仍然不够简洁!最不爽的就是顶点数据,一个三角形还好,如果我们要绘制复杂图形,那几万行的顶点颜色数据信息太煞风景了。而且在我们接触的引擎中,一般提供的都是sprite、prefab、blueprint等封装好的renderable 。这是一个很常见的概念,比如在许多渲染引擎中Forward Rendering的伪代码如下:
For each light:
For each renderable affected by the light:
framebuffer += renderable * light
如果单纯用OpenGL API来实现游戏引擎的渲染的话,我们需要不断的调用API设置渲染状态、传输几何体信息、通知GPU渲染、清理 反复循环。使用面向对象的方式会更优,抽象出静态物体、动态物体组成场景、灯光、摄像机以及其他。
我们调个软柿子捏,先抽象摄像机吧。
# 摄像机本质
当我们讨论摄像机/观察空间(Camera/View Space)的时候,是我们在讨论以摄像机的透视图作为场景原点时场景中所有可见顶点坐标。观察矩阵把所有的世界坐标变换到观察坐标,这些新坐标是相对于摄像机的位置和方向的。定义一个摄像机,我们需要一个摄像机在世界空间中的位置、观察的方向、一个指向它的右测的向量以及一个指向它上方的向量。细心的读者可能已经注意到我们实际上创建了一个三个单位轴相互垂直的、以摄像机的位置为原点的坐标系。 OpenGL是右手坐标系
移动世界!
# 视图矩阵
LookAt API :描述一台摄像机看向一个目标点,我们需要以下三个量
- 摄像机的位置
- 摄像机看向的目标点位置 ,1+2 决定了摄像机的方向。
- 摄像机向上的方向。
坐标系的逆矩阵,如果是该坐标系正交,则其逆矩阵为其转置矩阵 。