计算机图形学中,图形在电脑中是如何表示的?
下面我会用通俗易懂的语言,结合专业术语和示意,详细讲解:
1. 图形的基本类型
在计算机图形学中,常见的图形分为两大类:
- 矢量图形(Vector Graphics):用点、线、面、曲线等几何元素描述图形(如SVG、CAD、3D模型)。
- 位图/光栅图形(Raster Graphics):用像素网格描述图形(如JPG、PNG、屏幕显示)。
2. 位图(Raster)表示
位图就是把图像分成很多小格子(像素),每个像素用数字表示颜色。
- 二维图片:用一个二维数组存储,每个元素是一个像素的颜色值。
- 颜色表示:常见有RGB(红绿蓝)、RGBA(加透明度)、灰度等。
- 例子:一张1920x1080的图片,就是一个1920行、1080列的像素矩阵。
示意:
像素矩阵
[ [R,G,B], [R,G,B], ... ]
[ [R,G,B], [R,G,B], ... ]
...
内存结构举例(C语言伪代码):
struct Pixel {
unsigned char r, g, b, a;
};
Pixel image[1080][1920]; // 1080行,1920列
3. 矢量图形(Vector)表示
矢量图形用数学公式描述图形的形状和位置,不依赖像素。
- 点(Point):用坐标(x, y)或(x, y, z)表示
- 线(Line):用两个点的坐标表示
- 多边形(Polygon):用一组点的坐标表示
- 曲线(Curve):如贝塞尔曲线,用控制点和公式表示
- 3D模型:用顶点(Vertex)、边(Edge)、面(Face)等数据结构描述
示意:
struct Point2D { float x, y; };
struct Line { Point2D p1, p2; };
struct Polygon { Point2D* points; int count; };
3D网格模型常用结构:
struct Vertex { float x, y, z; float nx, ny, nz; float u, v; };
struct Face { int v1, v2, v3; }; // 三角面
Vertex vertices[N];
Face faces[M];
- 顶点(Vertex):位置、法线、纹理坐标等
- 面(Face):通常用顶点索引组成三角形或四边形
4. 图形文件格式
- 位图格式:BMP、PNG、JPG、GIF等
- 矢量格式:SVG、PDF、AI、CAD等
- 3D模型格式:OBJ、FBX、GLTF等
这些文件格式都规定了如何把上述数据结构存储到文件中。
5. 图形在内存中的表示(以3D为例)
3D模型在内存中的典型表示:
- 顶点缓冲区(Vertex Buffer):存储所有顶点数据
- 索引缓冲区(Index Buffer):存储面片的顶点索引
- 纹理(Texture):存储贴图的像素数据
- 材质(Material):存储表面属性
GPU渲染时,这些数据会上传到显卡的显存中,由GPU进行处理和显示。
6. 总结
- 位图:用像素矩阵表示,每个像素有颜色值
- 矢量图:用点、线、面、曲线等几何数据和数学公式表示
- 3D模型:用顶点、面、纹理等结构体数组表示
- 文件格式:规定了如何把这些数据存储和读取
拓展阅读
下面我将继续深入讲解“图形在计算机中的表示”,并结合实际应用,详细说明3D图形数据的内存结构、加载流程、渲染管线中的数据流转,以及常见的矢量图(如SVG)和位图(如PNG)在内存中的解析与使用。
一、3D图形在内存中的详细表示
1. 顶点(Vertex)
每个顶点通常包含:
- 位置(Position):x, y, z
- 法线(Normal):nx, ny, nz(用于光照计算)
- 纹理坐标(UV):u, v(用于贴图)
- 颜色(可选):r, g, b, a
C/C++结构体示例:
struct Vertex {
float x, y, z; // 位置
float nx, ny, nz; // 法线
float u, v; // 纹理坐标
};
2. 面(Face)/索引(Index)
- 3D模型通常用三角形面片(Triangle)拼接而成。
- 每个三角形由3个顶点索引组成。
C/C++结构体示例:
struct Face {
int v1, v2, v3; // 指向顶点数组的索引
};
3. 纹理(Texture)
- 纹理是一个位图(像素矩阵),通常为2D数组。
- 每个像素有颜色值(如RGBA)。
C/C++结构体示例:
struct Texture {
int width, height;
unsigned char* data; // 按行优先存储的像素数据
};
4. 材质(Material)
- 材质描述表面属性,如漫反射颜色、镜面反射、透明度等。
- 可能包含多个纹理(漫反射贴图、法线贴图等)。
二、3D模型的加载流程
以OBJ文件为例:
- 解析文件:读取顶点、法线、纹理坐标、面索引等数据。
- 构建内存结构:将数据填充到
Vertex
、Face
等结构体数组中。 - 上传到GPU:将顶点数据和索引数据上传到显卡的缓冲区(VBO/IBO)。
- 渲染时使用:GPU根据这些数据进行图形绘制。
伪代码流程:
// 1. 读取文件
std::vector<Vertex> vertices;
std::vector<Face> faces;
LoadOBJ("model.obj", vertices, faces);
// 2. 上传到GPU
GLuint vbo, ibo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, faces.size() * sizeof(Face), &faces[0], GL_STATIC_DRAW);
三、渲染管线中的数据流转
- CPU端:准备好顶点、索引、纹理等数据
- 上传到GPU:通过API(如OpenGL、DirectX、Vulkan)上传到显卡
- 顶点着色器:GPU对每个顶点进行变换(如模型、视图、投影变换)
- 光栅化:将三角形转为像素
- 片元着色器:计算每个像素的颜色(结合纹理、光照等)
- 输出到帧缓冲:最终显示在屏幕上
四、矢量图(SVG)在内存中的表示
SVG是一种基于XML的矢量图格式,常见元素有<rect>
、<circle>
、<path>
等。
解析流程:
- 解析XML,构建DOM树
- 每个图形元素转为内存对象(如Rect、Circle、Path类)
- 渲染时,遍历这些对象,调用绘图API(如Canvas、OpenGL)绘制
示例结构体:
struct SVGRect { float x, y, width, height; Color fill; };
struct SVGCircle { float cx, cy, r; Color fill; };
struct SVGPath { std::vector<PathCommand> commands; Color fill; };
五、位图(如PNG)在内存中的表示与使用
- 解码PNG文件:用库(如libpng、stb_image)将PNG文件解码为像素数组
- 像素数组:二维数组,每个元素是RGBA颜色
- 上传到GPU:作为纹理使用
C/C++伪代码:
int width, height, channels;
unsigned char* data = stbi_load("image.png", &width, &height, &channels, 4);
// data是width*height*4字节的像素数组
六、图形数据的通用表示与抽象
在现代图形引擎中,通常会有一套通用的数据结构来描述各种图形对象,便于统一管理和渲染。
常见抽象:
- Mesh(网格):包含顶点、索引、材质
- Texture(纹理):像素数据
- Material(材质):表面属性
- Scene Graph(场景图):节点树结构,描述物体的层级和变换
七、总结
- 所有图形最终都要转化为内存中的数据结构,如数组、结构体、对象等。
- 位图:像素矩阵
- 矢量图:几何对象集合
- 3D模型:顶点、索引、纹理、材质等
- 渲染时,这些数据会上传到GPU,由显卡进行高效处理和显示。