OpenGL跟Vulkan可以理解为一套规范,并不是实际存在的软件,在Linux上,Mesa就是对它们的实现。
Mesa 是一个开源的图形库,它提供了对 OpenGL 和 Vulkan 等图形 API 的具体实现,充当了应用程序与图形硬件之间的桥梁。
libGL:在类Unix系统(如Linux)上,libGL.so是OpenGL API的标准客户端库和接口。应用程序链接它来调用OpenGL函数。这个 libGL.so文件通常由Mesa项目或显卡厂商的驱动包提供。
Mesa 即提供硬件实现也提供软件实现,但系统没有GPU时,它会自动切换为软件渲染器。
你可以通过命令 glxinfo | grep "OpenGL renderer"来查看当前正在使用的渲染器。输出可能会是 AMD Radeon RX 6700 XT (radeonsi)(硬件加速)或 LLVMpipe (LLVM 13.0.0, 256 bits)(软件渲染)。
下面这些软件渲染库就是基于OpenGL/Vulkan规范实现的
TinyGL衍生(Fabrice Bellard大神写的OpenGL1.1软件实现):
jeason1997/PicoGL: 台湾网友移植的TinyGL,增加了直接写Linux Framebuffer的backend(原TinyGL只支持X窗口)、使用Makefile组织项目、增加了定点数运算支持)
jeason1997/RepicoGL: ESP32 Arduino上移植PicoGL(源自PicoGL/TinyGL简化版软件opengl渲染库)
C-Chads/tinygl:倒数第二个便携式图形库 --- C-Chads/tinygl: The penultimate portable graphics library(TinyGL的升级版,不维护了)
jeason1997/tinygl: 网友改良的TinyGL版本,一个精简可以用于嵌入式的软件OpenGL1.0子集实现(应该是基于C-Chads/tinygl,那个已经不维护了)
tinygl-d1: 将OpenGL的子集实现tinyGL适配到全志D1上来(应该是基于C-Chads/tinygl,全志D1适配版)
lunixbochs/tinygles: Software-rendered OpenGL ES
jeason1997/tinygl.js: TinyGL的JS版,通过Emscripten将C编译成WebAssembly给JS使用 Implementation of OpenGL 1.1 compatible API in JavaScript.
嵌入式:
jeason1997/EmberGL: Arduino嵌入式OpenGL图形库 EmberGL - 2D/3D graphics library featuring a tiled software rasterizer.
jeason1997/tgx: 一个用于Esp32的精简openGL图形库 tgx - a tiny/teensy 3D graphics library
jeason1997/arduinogl: 简单的图形库,只支持黑白 Arduino OpenGL
其他:
jeason1997/PortableGL: 仅一个C头文件实现的OpenGL 3软件渲染器 An implementation of OpenGL 3.x-ish in clean C
hmwill/GLESv20: Vincent ES 2.0 (Software Renderer based on OpenGL ES 2.0 API)
fogleman/fauxgl:用 Go 编写的纯软件 3D 渲染器。 --- fogleman/fauxgl: Software-only 3D renderer written in Go.
h0MER247/swGL:C++ 中 OpenGL 1.3 的多线程软件实现。 --- h0MER247/swGL: A multithreaded software implementation of OpenGL 1.3 in C++.
bit-hack/softgl:软件渲染的 OpenGL 实现 --- bit-hack/softgl: Software Rendered OpenGL implementation
keith2018/SoftGLRender:微型 C++ 软件渲染器/光栅化器,并实现 OpenGL 和 Vulkan 渲染器以进行比较 (比较高级,支持OpenlGL跟Vulkan的软件,并且支持GLSL Shader脚本)
starseeker/osmesa:提供 Mesa3d 7.0.4 swrast 和 osmesa 功能的库。
TTSIOD 渲染器 2.x - 基本 3D 算法 --- TTSIOD Renderer 2.x - Basic 3D algorithms
皮克斯曼 --- Pixman
相关文章:
在ESP32上移植OpenGL实现(一)-腾讯云开发者社区-腾讯云
试一试 TinyGL 的衍生版本 / 计算机图形/GUI/RTOS/FileSystem/OpenGL/DirectX/SDL2 / WhyCan Forum(哇酷开发者社区)
附录,OpenGL 1.0实现规范:
OpenGL 1.0 规范于 1992 年 1 月发布,是 OpenGL 的第一个正式版本,它定义了一套跨平台、独立于硬件的二维和三维图形渲染 API。其核心设计目标是提供可移植性、硬件加速潜力以及简洁的接口。
若要实现一个 OpenGL 1.0 的软件实现(即软件光栅化器),需要严格遵循其规范定义的核心功能和渲染管线。
🖥️ 1. OpenGL 1.0 规范的核心内容
OpenGL 1.0 规范定义了图形渲染的基本框架和操作。其核心内容包括:
-
基本图元绘制:支持绘制点(
GL_POINTS
)、线(GL_LINES
,GL_LINE_STRIP
,GL_LINE_LOOP
)和多边形(GL_POLYGON
,GL_TRIANGLES
,GL_QUADS
等)。所有几何图形都通过指定顶点(glVertex*
)来定义 -
变换系统:包括模型视图变换(
glMatrixMode(GL_MODELVIEW)
,使用glTranslatef
,glRotatef
,glScalef
等)和投影变换(glMatrixMode(GL_PROJECTION)
,如glOrtho
,glFrustum
),用于将物体从三维空间坐标变换到屏幕二维坐标。 -
颜色与着色:支持 RGBA 模式(
glColor*
)和颜色索引模式(使用颜色查找表)。多边形支持平面着色(Flat Shading) 和平滑着色(Smooth Shading/Gouraud Shading)(glShadeModel
) -
光照与材质:支持简单的局部光照模型。可以启用光源(
glEnable(GL_LIGHTING)
,最多支持 8 个光源GL_LIGHT0
到GL_LIGHT7
)并设置其属性(环境光、漫反射光、镜面反射光、位置等)。物体表面的反射特性通过材质(glMaterial*
)定义 -
纹理映射:支持将图像(纹理)贴到几何图形表面。涉及纹理对象的创建(
glGenTextures
,glBindTexture
)、纹理图像的指定(glTexImage2D
)、纹理坐标的指定(glTexCoord*
)以及纹理参数的设置(滤波、环绕方式等)。 -
光栅化与片元操作:将几何图元转换为帧缓冲区中的像素(片元)。包括深度测试(
GL_DEPTH_TEST
)、alpha 混合(glBlendFunc
)、面剔除(GL_CULL_FACE
)、抖动等操作。 -
显示列表:支持将一系列 OpenGL 命令编译成一个可高效重复执行的对象(
glNewList
,glCallList
),用于优化性能。 -
视图与裁剪:定义视口(
glViewport
)和裁剪区域。
⚙️ 2. 实现一个 OpenGL 1.0 软件渲染器的关键步骤
实现一个软件渲染器意味着需要用 CPU 代码模拟整个图形管线,将 OpenGL 命令转换为内存帧缓冲区中的像素值。
-
建立图形上下文与帧缓冲区管理:
-
创建和管理一块内存区域作为帧缓冲区(Framebuffer),用于存储最终渲染出的图像(颜色值)。
-
通常还需要一块 Z 缓冲区(深度缓冲区),用于在渲染过程中进行深度测试,正确处理物体的前后遮挡关系。
-
实现上下文(Context)管理,用于保存当前的所有渲染状态(矩阵堆栈、光照参数、启用状态等)。
-
-
实现几何变换与裁剪:
-
模型视图变换和投影变换:用软件实现矩阵乘法,将所有顶点从物体坐标变换到裁剪坐标。
-
透视除法:将裁剪坐标除以 w 分量,得到标准化设备坐标(NDC)。
-
视口变换:将 NDC 映射到窗口坐标。
-
裁剪:在齐次裁剪空间或之后,根据视景体对图元(点、线、面)进行裁剪。
-
-
实现光栅化算法:
-
这是软件渲染器的核心。需要为每种图元(点、线、三角形)编写扫描转换算法,确定帧缓冲区中哪些像素被该图元覆盖。
-
对于三角形,常用算法包括扫描线算法或基于边缘函数(Edge Function)的方法。需要能正确插值计算三角形内部各像素的属性,如深度(Z值)、颜色、纹理坐标等。
-
-
实现片元处理(逐像素操作):
-
对于每个被图元覆盖的像素(片元),根据当前 OpenGL 状态执行一系列操作:
-
纹理采样:如果启用了纹理映射(
GL_TEXTURE_2D
),根据插值得到的纹理坐标从纹理图像中获取颜色(texel),并应用设定的滤波方式。 -
光照计算:如果启用了光照(
GL_LIGHTING
),根据法线、材质属性、光源位置和视点位置,计算该片元的最终颜色(环境光、漫反射、镜面反射分量之和)。 -
雾效:如果启用了雾(
GL_FOG
),根据片元与视点的距离混合雾的颜色。 -
颜色汇总:将纹理颜色、光照颜色、主颜色等按当前模式混合。
-
深度测试:将当前片元的深度值与 Z 缓冲区中对应位置的深度值进行比较,决定是否丢弃该片元或更新 Z 缓冲区。
-
Alpha 混合:如果启用了混合(
GL_BLEND
),将当前片元颜色与帧缓冲区中已有颜色按照混合函数进行混合。 -
其他操作:如模板测试、抖动等(OpenGL 1.0 对此支持较为基础)。
-
-
实现状态机与管理:
-
OpenGL 是一个巨大的状态机。需要完整实现所有状态的管理,如矩阵堆栈(
glPushMatrix
,glPopMatrix
)、属性堆栈(glPushAttrib
,glPopAttrib
)、所有的启用/禁用状态(glEnable
,glDisable
)以及各种参数设置函数。
-
-
提供 API 接口:
-
提供与 OpenGL 1.0 规范匹配的函数接口。内部实现将这些函数调用转换为对上述软件渲染管线中相应模块的操作。
-
💡 3. 实现时的注意事项与挑战
-
性能:软件渲染完全依赖 CPU,性能是关键挑战。需优化关键算法(如使用定点数、SIMD 指令)。
-
精度:需处理数值精度问题,尤其是在变换和光照计算中。
-
正确性:确保渲染结果与硬件 OpenGL 实现(在相同状态下)尽可能一致,需严格遵循规范。
-
功能完整性:OpenGL 1.0 功能繁多,实现所有功能是项巨大工程。许多早期软件渲染器(如 Mesa 1.0)或 TinyGL 都只实现了其核心功能子集。