raylib绘图库--瞿华
2022.7.1
知乎 1、raylib绘图库简介
知乎 2、raylib 2d动画/游戏教程(1)动画基本原理
知乎 3、raylib 2d动画/游戏教程(2)坐标系与颜色系统
知乎 4、raylib 2d动画/游戏教程(3)图像文件与图层
知乎 5、raylib 2d动画/游戏教程(4)raylib-drawing库
知乎 6、raylib 2d动画/游戏教程(5)键盘与鼠标输入
知乎 7、raylib 2d动画/游戏教程(6)游戏手柄输入
知乎 8、raylib 2d动画/游戏教程(7)音乐和音效
知乎 9、raylib绘制中文内容
知乎 10、使用raygui绘制控件
知乎 11、raylib 3d绘图基础教程(1)坐标系和摄像机
知乎 12、raylib 3d绘图基础教程(2)网格(Mesh)
知乎 13、raylib 3d绘图基础教程(3)几何变换
知乎 14、raylib 3d绘图基础教程(4)3d模型的载入与绘制
raylib 3d绘图基础教程(2)网格(Mesh)
细心的读者可能已经注意到了,我们在教程(1)的示例程序中使用了raylib的DrawCube、DrawSphere等函数来绘制基础的几何体。这些函数用起来很方便,但是无法实现更复杂的绘图功能。比如说,换个纯色之外的材质贴图?对集合体进行旋转或者其他变形?它们都做不到。
本节介绍raylib的网格(Mesh)功能,用它我们能够实现更复杂的3d物体绘制。所谓网格,就是三维空间中的若干个点(顶点,vertex),这些点的连线围起来的空间就构成了要绘制的3d物体。
下面的示例程序绘制了一个一边旋转,一边不断改变颜色的长方体:
#include
#include
int main(void)
{
//初始化
const int screenWidth = 640;
const int screenHeight = 480;
//启用反锯齿
SetConfigFlags(FLAG_MSAA_4X_HINT);
//初始化窗口
InitWindow(screenWidth, screenHeight, "Sample");
//初始化摄像机
Camera3D camera = { 0 };
camera.position = (Vector3){ 40.0f, 20.0f, 0.0f };//相机所在位置{x,y,z}
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };//相机朝向位置{x,y,z}
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };//相机正上方朝向矢量
camera.fovy = 40;//相机视野宽度
camera.projection = CAMERA_PERSPECTIVE;//采用透视投影
//创建几何体
Mesh mesh = GenMeshCube(5,5,15);
//设置动画帧率(刷新率,fps)为30帧/秒
SetTargetFPS(30);
//-----
int angle=0;//多边形旋转角度
int colorHue = 0;
//主游戏循环
while (!WindowShouldClose())//关闭窗口或者按ESC键时返回true
{
//每次循环更新一帧
double time = GetTime();
double rotateAngle = time*0.3;
colorHue++;
colorHue%=360;
//创建贴图
Image checked = GenImageChecked(2,2,1,1,ColorFromHSV(colorHue,1,1),LIGHTGRAY);
Texture2D texture = LoadTextureFromImage(checked);
UnloadImage(checked);
//基于贴图创建材质
Material material=LoadMaterialDefault();
material.maps[MATERIAL_MAP_DIFFUSE].texture = texture;
//创建几何变换矩阵
Matrix transform =MatrixRotateY(rotateAngle);
BeginDrawing();
ClearBackground(WHITE);
//以摄像机视角绘制3d内容
BeginMode3D(camera);
//绘制网格
DrawMesh(mesh,material,transform);
EndMode3D();
EndDrawing();
//释放材质和贴图
UnloadMaterial(material);
UnloadTexture(texture);
}
//释放网格
UnloadMesh(mesh);
//关闭窗口
CloseWindow();
return 0;
}
接下来,我们来详细介绍一下代码中各主要部分的功能:
1 创建网格
raylib中提供了若干GenMesh开头的函数,用来创建基本的几何体网格。本例使用GenMeshCube来创建一个长方体的网格。
//创建几何体
Mesh mesh = GenMeshCube(5,5,15);
2 创建材质
材质(material)决定着3d物体绘制时的外观。最常见的材质是贴图(texture)材质,即直接将二维图片显示为3d物体的外观。
在本例中,我们每次绘制长方体网格前,首先创建一张图片贴图,然后用这个贴图创建一个材质:
//创建贴图
Image checked =GenImageChecked(2,2,1,1,ColorFromHSV(colorHue,1,1),LIGHTGRAY);
Texture2D texture =LoadTextureFromImage(checked);
UnloadImage(checked);
因为Image对象会占用内存资源,所以在使用完之后要记得用UnloadImage函数释放它。
创建材质
//基于贴图创建材质
Material material=LoadMaterialDefault();
material.maps[MATERIAL_MAP_DIFFUSE].texture = texture;
3 计算图像变形
和大多数3d绘图库一样,raylib使用一个4x4的矩阵来计算3维空间中物体的变形,称为变换矩阵。为了方便使用,raylib在raymath.h提供了一系列Matrix开头的函数,用来生成变换矩阵。我们需要让几何体绕y轴旋转,所以使用MatrixRotateY函数:
//计算网格物体变形(绕y轴旋转)
Matrix transform =MatrixRotateY(rotateAngle);
4 绘制网格
最后,直接使用DrawMesh函数绘制:
BeginMode3D(camera);
//绘制网格
DrawMesh(mesh,material,MatrixRotateY(rotateAngle));
EndMode3D();
5 资源的释放
我们在绘制时创建的贴图、材质和网格都会占用计算机显存,因此在使用完之后一定要记得释放它们:
//释放材质和贴图
UnloadMaterial(material);
UnloadTexture(texture);
//释放网格
UnloadMesh(mesh);