空余时间自己动手撸了一个OpenGL(软渲染),也就是不调用平台提供的OpenGL接口(一般使用GPU实现,下面称为标准OpenGL),而是自己写一套OpenGL接口(CPU实现,下面称为我的OpenGL)来实现3D绘制的功能,实现与标准OpenGL相同的效果。目前我自己写的接口是按照OpenGL标准定义的接口来实现的,也就是OpenGL应用程序只用做少量修改,就能在我的OpenGL与标准OpenGL之间切换,我平时也会使用这个办法来验证我的OpenGL与标准OpenGL的效果差异。
当然OpenGL接口很多,图像和纹理格式也非常多,我一个人不可能实现全部的接口和格式,根据二八原则,我们大部分工作只需应用OpenGL 20%的接口就够了,这里我只实现我需要用到的接口和图像格式。我这里优先实现对于我理解计算机图形学或OpenGL渲染管线有用的技术,而有的技术即使很重要,但我认为对我来说不是瓶颈,我先也没有实现,比如三角形的视锥体裁剪虽然很重要,但我现在就还没有实现,不是不会,而是没有这么多时间和精力去做。
1. 先上渲染的效果视频,再来讲技术
下面两个视频都是使用我的OpenGL实现的,并没有调用平台的标准OpenGL。
(1)渲染效果视频
a. 兰伯特漫反射
b. 经典光照 (环境光照 + 兰伯特漫反射 + 镜面反射)
c. 环境光照
图1 渲染效果
(2)深度图效果视频
图2 深度图效果
2. 3D绘制的本质
3D绘制的的本质是,给定一个观察视角,输入一系列3D(或2D)模型信息,经过运算,最后输出一个图像Buffer。OpenGL的本质也是一样,就是根据这些输入的信息,经过计算机图形学方面的知识的加工,最后生成图像的过程。
(1)给定观察视角
以拍照为例,就是你相机摆在什么地方?相机朝向哪儿?你相机的镜头怎样?是广角镜头还是长焦镜头;你相机的成像单元怎么样?底片是多大或画幅多大;你的被拍摄物体摆在什么地方,方向怎样?
(2)描述3D模型信息
还是以拍照为例,你的模特到底长什么样?高矮胖瘦怎样?穿什么衣服?皮肤到底是光滑还是有皱纹?灯光是从哪个地方照过来的?具体到计算机图形学或者是OpenGL,那就是输入顶点坐标/纹理坐标/纹理贴图信息。
(3)输出图像Buffer
从拍照的角度来说,你把相机型号选好,把相机架好,相机参数调好(Shader着色器),模特摆好pose,灯光也摆好,当你把这些信息都确定下来后,拍出的照片也是确定的。OpenGL的工作就是对输入信息进行加工,最后输出图片Buffer,这个图片Buffer我们一般可以认为是一个RGBA之类颜色的二维大数组,另外,按照OpenGL标准,OpenGL只负责计算(绘制)出这个大数组,但并不负责显示出来。
3. 依赖的第三方库
为了能够加速开发我的OpenGL库开发,目前我的OpenGL及相关的OpenGL应用程序使用了如下第三方库。
(1)Assimp模型解析库
目前用在OpenGL应用程序中,用于解析fbx等3D骨骼模型格式文件,将3D模型解析出OpenGL可以使用的顶点/法线/纹理等信息。
(2)glm数学库
OpenGL Mathematics的缩写,提供各种向量和矩阵运算,目前使用在OpenGL应用程序和我的OpenGL实现代码中。
(3)OpenCV库
目前用在OpenGL应用程序中,用来解析jpg/png之类的纹理图片文件,另外也用于把我的OpenGL渲染出来的图像Buffer转成cv::Mat显示在屏幕上。
4. 我的OpenGL实现的功能
目前,我的OpenGL实现了标准OpenGL的如下功能:
(1)图元绘制(目前只实现三角形绘制,没有实现点和线的绘制)
(2)三角形光栅化
(3)三角形纹理坐标/颜色/法线等的重心坐标插值算法
(4)三角形背面剔除
(5)深度缓冲区和深度比较
(6)顶点着色器和片元着色器(使用C++代码实现,并没有真正使用Shader语言)
(7)2D纹理
(8)光照贴图(Cube Map)
(9)多纹理支持
(10)纹理的最近邻采样和线性采样
5. 意义
自己一个人单打独斗写的(基于CPU的)OpenGL实现,从性能和稳定性上,肯定比不上目前NVIDIA和AMD等商业公司实现的成熟OpenGL,我之所以重新发明轮子是基于如下意义。
(1)深刻理解计算机图形学原理
亲手撸一把OpenGL API,实现其API应该实现的功能,使我对于计算机图形学和OpenGL的渲染管线的理解会更加深刻,包括理解为什么OpenGL的渲染管线要这样设计?而不那样设计?
(2)加深对GPU图像绘制性能的理解
其实这里并不只是对于OpenGL性能,对于Vulkan等接口的性能理解也同样适用,亲手撸过一把OpenGL API后,你会相对准确地知道哪些API或是哪些操作会有性能问题。
最后,大家如果对自己实现OpenGL的哪个地方感兴趣,可以在下面留言,我后面的文章会给大家分享。