论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
搜索
登录
搜索
勇芳
累计撰写
333
篇文章
累计收到
0
条评论
首页
栏目
论坛的首页
勇芳的软件
教程和帮助
VisualFreeBasic编程文档
勇芳系列软件帮助说明教程
留言或交流
登录
自定义幻灯片
推荐
联系勇芳软件
最新文章
2026-3-6
SDL3_API分类参考_表面(CategorySurface)
表面(Surface)子系统(CategorySurface) SDL Surface 是系统内存(RAM) 中的像素缓冲区,适用于处理未存储在 GPU 显存中的图像数据——可便捷地传递、修改图像,无需依赖硬件加速。 SDL_Surface 提供了完善的多格式图像管理能力,以及一套实用的像素数据操作工具集,包括:表面间像素拷贝、图像矩形填充、格式转换等。 SDL 内置了简易的图片加载函数: BMP 加载:SDL_LoadBMP() PNG 加载:SDL_LoadPNG() SDL 本身不支持其他格式(如 JPG/PNG 以外),但可通过外部优秀库扩展(如官方配套的 SDL_image)。 线程安全说明 这些函数整体线程安全:不同线程可操作不同 Surface;禁止两个线程同时修改同一个 Surface。 函数 SDL_AddSurfaceAlternateImage:为 Surface 添加备用图像(多分辨率/格式适配) SDL_BlitSurface:基础表面拷贝(将源 Surface 绘制到目标 Surface,支持裁剪) SDL_BlitSurface9Grid:9宫格模式拷贝 Surface(拉伸时边缘不变形) SDL_BlitSurfaceScaled:缩放拷贝 Surface(自动适配目标尺寸) SDL_BlitSurfaceTiled:平铺拷贝 Surface(重复绘制填满目标区域) SDL_BlitSurfaceTiledWithScale:带缩放的平铺拷贝 Surface SDL_BlitSurfaceUnchecked:无参数校验的快速表面拷贝(性能更高,需确保参数合法) SDL_BlitSurfaceUncheckedScaled:无校验的缩放表面拷贝 SDL_ClearSurface:清空 Surface(用预设颜色填充整个表面) SDL_ConvertPixels:像素格式转换(直接处理像素缓冲区,不依赖 Surface) SDL_ConvertPixelsAndColorspace:像素格式+颜色空间双重转换 SDL_ConvertSurface:转换 Surface 的像素格式(生成新 Surface) SDL_ConvertSurfaceAndColorspace:转换 Surface 的像素格式+颜色空间 SDL_CreateSurface:创建空 Surface(指定尺寸、像素格式) SDL_CreateSurfaceFrom:从已有像素缓冲区创建 Surface(复用内存) SDL_CreateSurfacePalette:为 Surface 创建调色板(索引色格式专用) SDL_DestroySurface:销毁 Surface(释放内存和资源) SDL_DuplicateSurface:复制 Surface(生成独立的新 Surface) SDL_FillSurfaceRect:填充 Surface 中的单个矩形区域 SDL_FillSurfaceRects:批量填充 Surface 中的多个矩形区域 SDL_FlipSurface:翻转 Surface(水平/垂直/180度,参考 SDL_FlipMode) SDL_GetSurfaceAlphaMod:获取 Surface 的透明度调制值(0-255) SDL_GetSurfaceBlendMode:获取 Surface 的混合模式 SDL_GetSurfaceClipRect:获取 Surface 的裁剪矩形(仅绘制矩形内区域) SDL_GetSurfaceColorKey:获取 Surface 的颜色键(透明色) SDL_GetSurfaceColorMod:获取 Surface 的颜色调制值(RGB 偏移) SDL_GetSurfaceColorspace:获取 Surface 的颜色空间(如 sRGB、BT.709) SDL_GetSurfaceImages:获取 Surface 关联的所有备用图像 SDL_GetSurfacePalette:获取 Surface 的调色板(索引色格式) SDL_GetSurfaceProperties:获取 Surface 的属性集合(格式、标志位等) SDL_LoadBMP:从文件加载 BMP 图像到 Surface SDL_LoadBMP_IO:从自定义 IO 流加载 BMP 图像到 Surface SDL_LoadPNG:从文件加载 PNG 图像到 Surface SDL_LoadPNG_IO:从自定义 IO 流加载 PNG 图像到 Surface SDL_LoadSurface:通用图像加载(自动识别格式,需 SDL_image 支持) SDL_LoadSurface_IO:从自定义 IO 流通用加载图像到 Surface SDL_LockSurface:锁定 Surface(获取可读写的像素缓冲区,修改前必须调用) SDL_MapSurfaceRGB:将 RGB 颜色转换为 Surface 格式的像素值(无 Alpha) SDL_MapSurfaceRGBA:将 RGBA 颜色转换为 Surface 格式的像素值 SDL_PremultiplyAlpha:预乘 Alpha 通道(优化混合计算) SDL_PremultiplySurfaceAlpha:为 Surface 预乘 Alpha 通道 SDL_ReadSurfacePixel:读取 Surface 中指定坐标的像素值(整型) SDL_ReadSurfacePixelFloat:读取 Surface 中指定坐标的像素值(浮点型) SDL_RemoveSurfaceAlternateImages:移除 Surface 的所有备用图像 SDL_RotateSurface:旋转 Surface(指定角度,生成新 Surface) SDL_SaveBMP:将 Surface 保存为 BMP 文件 SDL_SaveBMP_IO:将 Surface 保存到自定义 IO 流(BMP 格式) SDL_SavePNG:将 Surface 保存为 PNG 文件 SDL_SavePNG_IO:将 Surface 保存到自定义 IO 流(PNG 格式) SDL_ScaleSurface:缩放 Surface(指定尺寸和缩放模式,生成新 Surface) SDL_SetSurfaceAlphaMod:设置 Surface 的透明度调制值 SDL_SetSurfaceBlendMode:设置 Surface 的混合模式 SDL_SetSurfaceClipRect:设置 Surface 的裁剪矩形 SDL_SetSurfaceColorKey:设置 Surface 的颜色键(指定透明色) SDL_SetSurfaceColorMod:设置 Surface 的颜色调制值(调整整体色调) SDL_SetSurfaceColorspace:设置 Surface 的颜色空间 SDL_SetSurfacePalette:设置 Surface 的调色板(索引色格式) SDL_SetSurfaceRLE:启用/禁用 Surface 的 RLE 压缩(优化透明色渲染) SDL_StretchSurface:拉伸 Surface(适配目标尺寸,旧接口,推荐用 SDL_ScaleSurface) SDL_SurfaceHasAlternateImages:判断 Surface 是否关联了备用图像 SDL_SurfaceHasColorKey:判断 Surface 是否设置了颜色键(透明色) SDL_SurfaceHasRLE:判断 Surface 是否启用了 RLE 压缩 SDL_UnlockSurface:解锁 Surface(完成像素修改后提交,与 Lock 成对使用) SDL_WriteSurfacePixel:向 Surface 指定坐标写入像素值(整型) SDL_WriteSurfacePixelFloat:向 Surface 指定坐标写入像素值(浮点型) 数据类型 SDL_SurfaceFlags:Surface 标志位类型(存储 Surface 的属性,如是否有 Alpha、是否 RLE 压缩) 结构体 SDL_Surface:Surface 核心结构体(包含像素缓冲区、尺寸、格式、调色板等信息) 枚举 SDL_FlipMode:翻转模式枚举(SDL_FLIP_NONE/SDL_FLIP_HORIZONTAL/SDL_FLIP_VERTICAL/SDL_FLIP_BOTH) SDL_ScaleMode:缩放模式枚举(SDL_SCALEMODE_NEAREST/SDL_SCALEMODE_LINEAR 等,控制缩放插值方式) 宏 SDL_MUSTLOCK:判断 Surface 是否必须锁定才能修改像素(返回布尔值) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 错误处理辅助函数 Sub CheckError(byval msg as string) dim as zstring ptr err = SDL_GetError() if (*err <> 0) then SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "%s:%s", msg, err) SDL_ClearError() end if End Sub ' 主程序示例 Dim As SDL_Surface Ptr bmpSurface = NULL, newSurface = NULL Dim As SDL_Rect dstRect Dim As UInteger pixelColor Dim As UByte r, g, b, a ' 1. 初始化 SDL if (SDL_Init(SDL_INIT_VIDEO) < 0) then CheckError("SDL 初始化失败") end 1 end if ' 2. 加载 BMP 图像到 Surface bmpSurface = SDL_LoadBMP("test.bmp") if (bmpSurface = NULL) then CheckError("加载 BMP 失败") SDL_Quit() end 1 end if SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "加载的 BMP 尺寸:%dx%d", bmpSurface->w, bmpSurface->h) ' 3. 创建新 Surface(与源图像同格式,尺寸加倍) newSurface = SDL_CreateSurface(bmpSurface->w * 2, bmpSurface->h * 2, bmpSurface->format->format) if (newSurface = NULL) then CheckError("创建新 Surface 失败") SDL_DestroySurface(bmpSurface) SDL_Quit() end 1 end if ' 4. 填充新 Surface 背景为白色 pixelColor = SDL_MapSurfaceRGB(newSurface, 255, 255, 255) SDL_FillSurfaceRect(newSurface, NULL, pixelColor) CheckError("填充 Surface 失败") ' 5. 拷贝源 Surface 到新 Surface 的指定位置 dstRect.x = 50 : dstRect.y = 50 : dstRect.w = bmpSurface->w : dstRect.h = bmpSurface->h SDL_BlitSurface(bmpSurface, NULL, newSurface, @dstRect) CheckError("Surface 拷贝失败") ' 6. 修改 Surface 像素(读取并改写左上角像素) if (SDL_MUSTLOCK(newSurface)) then if (SDL_LockSurface(newSurface) < 0) then CheckError("锁定 Surface 失败") goto cleanup end if end if ' 读取左上角像素 pixelColor = SDL_ReadSurfacePixel(newSurface, 0, 0) SDL_GetRGBA(pixelColor, newSurface->format, @r, @g, @b, @a) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "左上角像素原始颜色:R=%d, G=%d, B=%d, A=%d", r, g, b, a) ' 改写为红色 pixelColor = SDL_MapSurfaceRGBA(newSurface, 255, 0, 0, 255) SDL_WriteSurfacePixel(newSurface, 0, 0, pixelColor) if (SDL_MUSTLOCK(newSurface)) then SDL_UnlockSurface(newSurface) end if ' 7. 保存修改后的 Surface 为新 BMP if (SDL_SaveBMP(newSurface, "output.bmp") < 0) then CheckError("保存 BMP 失败") end if ' 8. 缩放 Surface(缩小为原尺寸的 50%) Dim As SDL_Surface Ptr scaledSurface = SDL_ScaleSurface(newSurface, _ newSurface->w / 2, newSurface->h / 2, SDL_SCALEMODE_LINEAR) if (scaledSurface <> NULL) then SDL_SavePNG(scaledSurface, "scaled.png") SDL_DestroySurface(scaledSurface) end if ' 9. 清理资源 cleanup: if (bmpSurface <> NULL) then SDL_DestroySurface(bmpSurface) if (newSurface <> NULL) then SDL_DestroySurface(newSurface) SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "程序执行完成") end 0 总结 SDL Surface 是系统内存中的像素缓冲区,核心优势是无需 GPU 即可操作像素,SDL_LoadBMP/SDL_SaveBMP 是最基础的加载/保存函数; FreeBASIC 中使用 Surface 需遵循「锁定-修改-解锁」流程(SDL_LockSurface/SDL_UnlockSurface),SDL_MUSTLOCK 宏可判断是否需要锁定; 关键操作:SDL_BlitSurface(拷贝)、SDL_FillSurfaceRect(填充)、SDL_ConvertSurface(格式转换),修改像素前务必确认 Surface 已锁定,避免内存错误。
2026年-3月-6日
267 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_矩形与点运算(CategoryRect)
矩形与点运算子系统(CategoryRect) SDL 提供的矩形和 2D 点管理辅助函数集,包含整型和浮点型两个版本,覆盖矩形相交、包含、合并等常用几何运算。 函数 SDL_GetRectAndLineIntersection:计算整型矩形与线段的交点(修改线段坐标为交点) SDL_GetRectAndLineIntersectionFloat:计算浮点型矩形与线段的交点(修改线段坐标为交点) SDL_GetRectEnclosingPoints:计算包含所有整型点的最小包围矩形 SDL_GetRectEnclosingPointsFloat:计算包含所有浮点型点的最小包围矩形 SDL_GetRectIntersection:计算两个整型矩形的交集(返回交集矩形) SDL_GetRectIntersectionFloat:计算两个浮点型矩形的交集(返回交集矩形) SDL_GetRectUnion:计算两个整型矩形的并集(返回覆盖两个矩形的最小矩形) SDL_GetRectUnionFloat:计算两个浮点型矩形的并集(返回覆盖两个矩形的最小矩形) SDL_HasRectIntersection:判断两个整型矩形是否相交(返回布尔值) SDL_HasRectIntersectionFloat:判断两个浮点型矩形是否相交(返回布尔值) SDL_PointInRect:判断整型点是否在整型矩形内(包含边界) SDL_PointInRectFloat:判断浮点型点是否在浮点型矩形内(包含边界) SDL_RectEmpty:判断整型矩形是否为空(宽/高≤0 则为空) SDL_RectEmptyFloat:判断浮点型矩形是否为空(宽/高≤0 则为空) SDL_RectsEqual:判断两个整型矩形是否完全相等 SDL_RectsEqualEpsilon:判断两个浮点型矩形是否近似相等(指定误差阈值) SDL_RectsEqualFloat:判断两个浮点型矩形是否完全相等 SDL_RectToFRect:将整型 SDL_Rect 转换为浮点型 SDL_FRect 数据类型 (无) 结构体 SDL_FPoint:浮点型 2D 点结构体(x、y 为单精度浮点) SDL_FRect:浮点型矩形结构体(x、y 为左上角坐标,w、h 为宽高,均为单精度浮点) SDL_Point:整型 2D 点结构体(x、y 为 32 位整型) SDL_Rect:整型矩形结构体(x、y 为左上角坐标,w、h 为宽高,均为 32 位整型) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 主程序示例 Sub PrintRectInfo(rect As SDL_Rect, name As String) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s:x=%d, y=%d, w=%d, h=%d", _ name, rect.x, rect.y, rect.w, rect.h) End Sub Sub PrintFRectInfo(frect As SDL_FRect, name As String) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s:x=%.2f, y=%.2f, w=%.2f, h=%.2f", _ name, frect.x, frect.y, frect.w, frect.h) End Sub ' 主函数 Dim As SDL_Rect rect1, rect2, intersectRect, unionRect Dim As SDL_FRect frect1, frect2, fIntersectRect Dim As SDL_Point point1, point2(0 To 2) Dim As SDL_FPoint fpoint1 Dim As Integer hasIntersect, isPointInRect ' 1. 整型矩形运算示例 rect1 = Type<SDL_Rect>(100, 100, 200, 200) ' 矩形1:(100,100) 宽200 高200 rect2 = Type<SDL_Rect>(150, 150, 200, 200) ' 矩形2:(150,150) 宽200 高200 PrintRectInfo(rect1, "矩形1") PrintRectInfo(rect2, "矩形2") ' 判断矩形是否相交 hasIntersect = SDL_HasRectIntersection(@rect1, @rect2) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "矩形1与矩形2是否相交:%s", IIf(hasIntersect, "是", "否")) ' 计算交集 If (SDL_GetRectIntersection(@rect1, @rect2, @intersectRect)) Then PrintRectInfo(intersectRect, "矩形交集") End If ' 计算并集 SDL_GetRectUnion(@rect1, @rect2, @unionRect) PrintRectInfo(unionRect, "矩形并集") ' 判断点是否在矩形内 point1 = Type<SDL_Point>(120, 120) ' 点1:(120,120) isPointInRect = SDL_PointInRect(@point1, @rect1) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "点(%d,%d)是否在矩形1内:%s", _ point1.x, point1.y, IIf(isPointInRect, "是", "否")) ' 计算包围点集的最小矩形 point2(0) = Type<SDL_Point>(50, 50) point2(1) = Type<SDL_Point>(250, 150) point2(2) = Type<SDL_Point>(150, 250) SDL_GetRectEnclosingPoints(@point2(0), 3, @rect1) ' 计算包含3个点的最小矩形 PrintRectInfo(rect1, "包围3个点的最小矩形") ' 2. 浮点型矩形运算示例 frect1 = Type<SDL_FRect>(100.5, 100.5, 200.0, 200.0) frect2 = Type<SDL_FRect>(150.5, 150.5, 200.0, 200.0) PrintFRectInfo(frect1, "浮点矩形1") PrintFRectInfo(frect2, "浮点矩形2") ' 计算浮点矩形交集 If (SDL_GetRectIntersectionFloat(@frect1, @frect2, @fIntersectRect)) Then PrintFRectInfo(fIntersectRect, "浮点矩形交集") End If ' 判断浮点点是否在浮点矩形内 fpoint1 = Type<SDL_FPoint>(120.5, 120.5) isPointInRect = SDL_PointInRectFloat(@fpoint1, @frect1) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "浮点点(%.2f,%.2f)是否在浮点矩形1内:%s", _ fpoint1.x, fpoint1.y, IIf(isPointInRect, "是", "否")) ' 3. 整型矩形转浮点矩形 Dim As SDL_FRect convFRect SDL_RectToFRect(@rect1, @convFRect) PrintFRectInfo(convFRect, "整型矩形1转换为浮点矩形") ' 4. 判断矩形是否为空 Dim As SDL_Rect emptyRect = Type<SDL_Rect>(0, 0, -100, 100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "空矩形判断:%s", IIf(SDL_RectEmpty(@emptyRect), "是空矩形", "非空矩形")) End 0 总结 SDL 矩形子系统核心是 SDL_Rect(整型)和 SDL_FRect(浮点型)两类结构体,配套函数覆盖相交、包含、合并等所有常用几何运算; FreeBASIC 中使用时,需注意函数参数为结构体指针,SDL_HasRectIntersection/SDL_PointInRect 是最常用的判断类函数,SDL_GetRectIntersection/SDL_GetRectUnion 是核心计算类函数; 浮点型函数(后缀 Float)适用于高精度几何运算,整型函数性能更高,可根据场景选择,SDL_RectToFRect 可快速完成整型到浮点型的转换。
2026年-3月-6日
181 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_混合模式(CategoryBlendmode)
混合模式子系统(CategoryBlendmode) 混合模式用于定义两种颜色的混合规则:SDL 既提供满足基础需求的标准混合模式,也支持创建自定义混合模式(可指定对颜色分量执行的数学运算规则)。 函数 SDL_ComposeCustomBlendMode:组合自定义混合模式(指定源因子、目标因子、混合运算,生成自定义 SDL_BlendMode) 数据类型 SDL_BlendMode:混合模式类型(包含标准模式和自定义模式的句柄) 结构体 (无) 枚举 SDL_BlendFactor:混合因子枚举(定义源/目标颜色的加权系数,如 SDL_BLENDFACTOR_SRC_ALPHA、SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA) SDL_BlendOperation:混合运算枚举(定义源颜色和目标颜色的计算方式,如 SDL_BLENDOPERATION_ADD、SDL_BLENDOPERATION_SUBTRACT) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 主程序示例 Dim As SDL_Window Ptr window = NULL Dim As SDL_Renderer Ptr renderer = NULL Dim As SDL_Texture Ptr texture1 = NULL, texture2 = NULL Dim As SDL_Rect rect1, rect2 Dim As SDL_BlendMode customBlendMode ' 自定义混合模式 Dim As Integer quit = 0 Dim As SDL_Event evt ' 初始化函数 Function InitBlendModeDemo() As Integer ' 初始化 SDL 视频子系统 If (SDL_Init(SDL_INIT_VIDEO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL 初始化失败:%s", SDL_GetError()) Return 0 End If ' 创建窗口和渲染器 window = SDL_CreateWindow("SDL 混合模式示例", _ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _ 800, 600, SDL_WINDOW_SHOWN) renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED) If (window = NULL Or renderer = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_RENDER, "创建窗口/渲染器失败:%s", SDL_GetError()) Return 0 End If ' 创建两个半透明矩形纹理 ' 纹理1:红色半透明 texture1 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, _ SDL_TEXTUREACCESS_TARGET, 200, 200) SDL_SetRenderTarget(renderer, texture1) SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128) ' 红,半透明 SDL_RenderClear(renderer) SDL_SetRenderTarget(renderer, NULL) ' 纹理2:绿色半透明 texture2 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, _ SDL_TEXTUREACCESS_TARGET, 200, 200) SDL_SetRenderTarget(renderer, texture2) SDL_SetRenderDrawColor(renderer, 0, 255, 0, 128) ' 绿,半透明 SDL_RenderClear(renderer) SDL_SetRenderTarget(renderer, NULL) ' 定义绘制位置(重叠) rect1.x = 200 : rect1.y = 150 : rect1.w = 200 : rect1.h = 200 rect2.x = 300 : rect2.y = 250 : rect2.w = 200 : rect2.h = 200 ' 1. 使用标准混合模式(SDL_BLENDMODE_BLEND) SDL_SetTextureBlendMode(texture1, SDL_BLENDMODE_BLEND) SDL_SetTextureBlendMode(texture2, SDL_BLENDMODE_BLEND) ' 2. 创建自定义混合模式(加法混合:源*1 + 目标*1) customBlendMode = SDL_ComposeCustomBlendMode( _ SDL_BLENDFACTOR_ONE, ' 源因子:源颜色完全保留 SDL_BLENDFACTOR_ONE, ' 目标因子:目标颜色完全保留 SDL_BLENDOPERATION_ADD, ' 混合运算:加法 SDL_BLENDFACTOR_ONE, ' Alpha 源因子 SDL_BLENDFACTOR_ONE, ' Alpha 目标因子 SDL_BLENDOPERATION_ADD ' Alpha 混合运算 ) Return 1 End Function ' 渲染函数 Sub RenderFrame(useCustomBlend As Integer) ' 清空背景为白色 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) SDL_RenderClear(renderer) ' 根据参数切换混合模式 If (useCustomBlend) Then SDL_SetTextureBlendMode(texture1, customBlendMode) SDL_SetTextureBlendMode(texture2, customBlendMode) SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "使用自定义加法混合模式") Else SDL_SetTextureBlendMode(texture1, SDL_BLENDMODE_BLEND) SDL_SetTextureBlendMode(texture2, SDL_BLENDMODE_BLEND) SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "使用标准混合模式") End If ' 绘制两个重叠纹理 SDL_RenderTexture(renderer, texture1, NULL, @rect1) SDL_RenderTexture(renderer, texture2, NULL, @rect2) ' 提交渲染结果 SDL_RenderPresent(renderer) End Sub ' 清理资源 Sub Cleanup() If (texture1 <> NULL) Then SDL_DestroyTexture(texture1) If (texture2 <> NULL) Then SDL_DestroyTexture(texture2) If (renderer <> NULL) Then SDL_DestroyRenderer(renderer) If (window <> NULL) Then SDL_DestroyWindow(window) SDL_Quit() End Sub ' 主程序 If (InitBlendModeDemo() = 0) Then Cleanup() End 1 End If Dim As Integer useCustom = 0 ' 主循环 While (quit = 0) While (SDL_PollEvent(@evt)) Select Case evt.type Case SDL_QUITEVENT quit = 1 Case SDL_KEYDOWN ' 按空格键切换混合模式 If (evt.key.keysym.sym = SDLK_SPACE) Then useCustom = Not useCustom End If End Select Wend ' 渲染帧(切换混合模式) RenderFrame(useCustom) ' 控制帧率 SDL_Delay(16) Wend Cleanup() End 0 总结 SDL 混合模式核心是 SDL_BlendMode 类型,标准模式(如 SDL_BLENDMODE_BLEND)满足基础需求,自定义模式需通过 SDL_ComposeCustomBlendMode 组合混合因子和运算规则; FreeBASIC 中使用时,需先通过 SDL_SetTextureBlendMode/SDL_SetRenderDrawBlendMode 为纹理/渲染器设置混合模式,再执行绘制操作; 混合因子(SDL_BlendFactor)定义源/目标颜色的权重,混合运算(SDL_BlendOperation)定义颜色的计算方式(加法/减法等),二者共同决定最终混合效果。
2026年-3月-6日
246 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_像素管理(CategoryPixels)
像素管理子系统(CategoryPixels) SDL 提供一套完整的像素管理工具集,核心聚焦于像素格式的处理——即解析一组二进制位具体代表的颜色含义。 如果你仅需将像素理解为红、绿、蓝(RGB)及透明度(Alpha)的组合,相关操作会非常直观,且这种程度的认知足以满足多数游戏开发需求。 但像素的实际定义远比这复杂: 颜色空间:像素是特定颜色空间中颜色的表示形式,SDL 主要支持两种颜色类型: RGB:由红、绿、蓝三色通道叠加形成屏幕显示的颜色(参考:https://en.wikipedia.org/wiki/RGB_color_model); YCbCr(也称 YUV):由亮度分量 Y、红色色度偏移 Cb、蓝色色度偏移 Cr 组成,利用人眼对亮度更敏感的特性,Cb/Cr 分量常被压缩且分辨率低于 Y 分量(参考:https://en.wikipedia.org/wiki/YCbCr)。 色度位置:YCbCr 压缩时,Y 分量保持全分辨率,单个 Cb/Cr 像素代表一块 Y 像素的平均色度,色度位置定义了该色度信息在像素块中的来源位置; 颜色范围:定义像素值转换为显示颜色时的有效数值范围——全范围使用像素位的完整数值区间,窄范围因历史原因仅使用部分区间; 原色与白点:基于标准 XYZ 色彩空间定义当前颜色空间的颜色基准(参考:https://en.wikipedia.org/wiki/CIE_1931_color_space); 传输特性(OETF):将线性数学空间的颜色转换为非线性输出信号的方式(参考:https://en.wikipedia.org/wiki/Rec._709#Transfer_characteristics); 矩阵系数:用于 YCbCr 与 RGB 颜色空间的相互转换。 函数 SDL_CreatePalette:创建调色板对象(用于索引色像素格式) SDL_DestroyPalette:销毁调色板对象(释放资源) SDL_GetMasksForPixelFormat:根据像素格式获取 RGBA 掩码(解析像素各通道的二进制位) SDL_GetPixelFormatDetails:获取像素格式的详细信息(包含颜色空间、位深等) SDL_GetPixelFormatForMasks:根据 RGBA 掩码反查对应的像素格式 SDL_GetPixelFormatName:获取像素格式的名称字符串(如 "SDL_PIXELFORMAT_RGBA8888") SDL_GetRGB:从像素值中提取 RGB 分量(无 Alpha) SDL_GetRGBA:从像素值中提取 RGBA 全部分量 SDL_MapRGB:将 RGB 颜色值转换为指定像素格式的像素值(无 Alpha) SDL_MapRGBA:将 RGBA 颜色值转换为指定像素格式的像素值 SDL_MapSurfaceRGB:将 RGB 颜色值转换为 SDL_Surface 对应格式的像素值(无 Alpha) SDL_MapSurfaceRGBA:将 RGBA 颜色值转换为 SDL_Surface 对应格式的像素值 SDL_SetPaletteColors:设置调色板中的颜色数组(批量更新索引色) 数据类型 (无) 结构体 SDL_Color:颜色结构体(整数格式,RGBA 各分量 0-255) SDL_FColor:浮点颜色结构体(浮点格式,RGBA 各分量 0.0-1.0) SDL_Palette:调色板结构体(存储索引色对应的颜色数组) SDL_PixelFormatDetails:像素格式详情结构体(包含颜色类型、位深、掩码等) 枚举 SDL_ArrayOrder:数组型像素格式的通道顺序(如 RGB、BGR) SDL_BitmapOrder:位图像素的位序(高位优先/低位优先) SDL_ChromaLocation:YCbCr 色度位置枚举(定义色度采样点) SDL_ColorPrimaries:颜色原色枚举(如 BT.709、BT.2020) SDL_ColorRange:颜色范围枚举(全范围/窄范围) SDL_Colorspace:颜色空间枚举(包含颜色类型、范围、原色等组合) SDL_ColorType:颜色类型枚举(RGB/YCbCr) SDL_MatrixCoefficients:颜色转换矩阵系数枚举(YCbCr↔RGB 转换用) SDL_PackedLayout:打包像素格式的布局枚举(如 32 位 RGBA 各通道位分配) SDL_PackedOrder:打包像素格式的通道顺序枚举 SDL_PixelFormat:像素格式枚举(如 RGBA8888、YV12 等) SDL_PixelType:像素类型枚举(整型/浮点型/索引色等) SDL_TransferCharacteristics:传输特性枚举(如 BT.709、sRGB) 宏 SDL_ALPHA_OPAQUE:不透明 Alpha 值(整数,255) SDL_ALPHA_OPAQUE_FLOAT:不透明 Alpha 值(浮点,1.0) SDL_ALPHA_TRANSPARENT:完全透明 Alpha 值(整数,0) SDL_ALPHA_TRANSPARENT_FLOAT:完全透明 Alpha 值(浮点,0.0) SDL_BITSPERPIXEL:计算像素格式的每像素位数(如 RGBA8888 为 32) SDL_BYTESPERPIXEL:计算像素格式的每像素字节数(如 RGBA8888 为 4) SDL_COLORSPACECHROMA:从颜色空间枚举中提取色度位置 SDL_COLORSPACEMATRIX:从颜色空间枚举中提取矩阵系数 SDL_COLORSPACEPRIMARIES:从颜色空间枚举中提取颜色原色 SDL_COLORSPACERANGE:从颜色空间枚举中提取颜色范围 SDL_COLORSPACETRANSFER:从颜色空间枚举中提取传输特性 SDL_COLORSPACETYPE:从颜色空间枚举中提取颜色类型 SDL_DEFINE_COLORSPACE:定义自定义颜色空间枚举值 SDL_DEFINE_PIXELFORMAT:定义自定义像素格式枚举值 SDL_DEFINE_PIXELFOURCC:通过 FOURCC 码定义像素格式 SDL_ISCOLORSPACE_FULL_RANGE:判断颜色空间是否为全范围 SDL_ISCOLORSPACE_LIMITED_RANGE:判断颜色空间是否为窄范围 SDL_ISCOLORSPACE_MATRIX_BT2020_NCL:判断颜色空间矩阵是否为 BT.2020 NCL SDL_ISCOLORSPACE_MATRIX_BT601:判断颜色空间矩阵是否为 BT.601 SDL_ISCOLORSPACE_MATRIX_BT709:判断颜色空间矩阵是否为 BT.709 SDL_ISPIXELFORMAT_10BIT:判断像素格式是否为 10 位深度 SDL_ISPIXELFORMAT_ALPHA:判断像素格式是否包含 Alpha 通道 SDL_ISPIXELFORMAT_ARRAY:判断像素格式是否为数组型(如 planar YUV) SDL_ISPIXELFORMAT_FLOAT:判断像素格式是否为浮点型 SDL_ISPIXELFORMAT_FOURCC:判断像素格式是否为 FOURCC 定义 SDL_ISPIXELFORMAT_INDEXED:判断像素格式是否为索引色(调色板) SDL_ISPIXELFORMAT_PACKED:判断像素格式是否为打包型(如 RGBA8888) SDL_PIXELFLAG:像素格式标志位(内部宏) SDL_PIXELLAYOUT:提取像素格式的布局信息 SDL_PIXELORDER:提取像素格式的通道顺序 SDL_PIXELTYPE:提取像素格式的类型(整型/浮点型等) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 主程序示例 Dim As SDL_Palette Ptr palette = NULL ' 调色板 Dim As SDL_Color colors(0 To 1) ' 调色板颜色数组 Dim As UInteger pixelValue ' 转换后的像素值 Dim As UByte r, g, b, a ' 提取的 RGBA 分量 Dim As SDL_PixelFormatDetails fmtInfo ' 像素格式详情 ' 1. 创建并设置调色板(索引色示例) colors(0) = Type<SDL_Color>(0, 0, 0, 255) ' 索引 0:黑色 colors(1) = Type<SDL_Color>(255, 255, 255, 255) ' 索引 1:白色 palette = SDL_CreatePalette(2, @colors(0)) If (palette = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "创建调色板失败:%s", SDL_GetError()) End 1 End If ' 2. 像素格式转换示例(RGBA8888 格式) ' 将 RGBA(255, 0, 0, 128) 转换为 RGBA8888 像素值 pixelValue = SDL_MapRGBA(SDL_PIXELFORMAT_RGBA8888, 255, 0, 0, 128) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "RGBA(255,0,0,128) 转换为 RGBA8888 像素值:0x%X", pixelValue) ' 从像素值反解 RGBA 分量 SDL_GetRGBA(pixelValue, SDL_PIXELFORMAT_RGBA8888, @r, @g, @b, @a) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "反解像素值得到:R=%d, G=%d, B=%d, A=%d", r, g, b, a) ' 3. 获取像素格式详情 If (SDL_GetPixelFormatDetails(SDL_PIXELFORMAT_RGBA8888, @fmtInfo)) Then SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "RGBA8888 位深:%d 位", fmtInfo.bits_per_pixel) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "RGBA8888 字节数:%d 字节", fmtInfo.bytes_per_pixel) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "是否含 Alpha:%s", IIf(SDL_ISPIXELFORMAT_ALPHA(SDL_PIXELFORMAT_RGBA8888), "是", "否")) End If ' 4. 获取像素格式掩码 Dim As UInteger rmask, gmask, bmask, amask SDL_GetMasksForPixelFormat(SDL_PIXELFORMAT_RGBA8888, @rmask, @gmask, @bmask, @amask) SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "RGBA8888 掩码:R=0x%X, G=0x%X, B=0x%X, A=0x%X", rmask, gmask, bmask, amask) ' 5. 清理资源 If (palette <> NULL) Then SDL_DestroyPalette(palette) End 0 总结 SDL 像素管理子系统核心是像素格式的转换与解析,SDL_MapRGBA/SDL_GetRGBA 是最常用的函数,用于 RGB 颜色与像素值的双向转换; FreeBASIC 中使用时,需明确目标像素格式(如 SDL_PIXELFORMAT_RGBA8888),宏 SDL_BITSPERPIXEL/SDL_BYTESPERPIXEL 可快速计算像素位深/字节数; 调色板(SDL_Palette)仅用于索引色像素格式,RGB/YCbCr 等真彩色格式无需调色板,需注意不同颜色空间(RGB/YCbCr)的转换依赖矩阵系数。
2026年-3月-6日
240 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_2D渲染(CategoryRender)
2D渲染子系统(CategoryRender) SDL 2D 渲染功能的头文件,该 API 专为简化 2D 图形绘制设计,核心特性如下: 支持绘制基础图元:单点像素、单像素线条、填充矩形、纹理图像、2D 多边形; 图元绘制模式:不透明、混合、叠加(加法)模式; 纹理绘制能力:支持不透明/混合/叠加模式,可添加颜色色调、透明度调制,也支持线性插值拉伸; 设计目标:专注加速简单 2D 操作;若需 3D 多边形、粒子特效等高级功能,建议使用 SDL 的 OpenGL/Direct3D 支持、SDL3 GPU API 或第三方 3D 引擎。 ⚠️ 注意:所有渲染函数必须在主线程调用,详情参考:https://github.com/libsdl-org/SDL/issues/986 函数 SDL_AddVulkanRenderSemaphores:为 Vulkan 渲染添加信号量同步 SDL_ConvertEventToRenderCoordinates:将事件中的坐标转换为渲染坐标系 SDL_CreateGPURenderer:创建基于 GPU 的渲染器(高性能渲染) SDL_CreateGPURenderState:创建 GPU 渲染状态(配置渲染管线) SDL_CreateRenderer:创建默认渲染器(自动选择硬件/软件渲染) SDL_CreateRendererWithProperties:按自定义属性创建渲染器 SDL_CreateSoftwareRenderer:创建纯软件渲染器(无硬件加速) SDL_CreateTexture:创建纹理对象(存储图像数据) SDL_CreateTextureFromSurface:从 SDL_Surface 创建纹理(常用图像加载后转换) SDL_CreateTextureWithProperties:按自定义属性创建纹理 SDL_CreateWindowAndRenderer:一键创建窗口和渲染器(简化初始化) SDL_DestroyGPURenderState:销毁 GPU 渲染状态 SDL_DestroyRenderer:销毁渲染器(释放资源) SDL_DestroyTexture:销毁纹理(释放图像资源) SDL_FlushRenderer:刷新渲染器队列(强制执行待渲染命令) SDL_GetCurrentRenderOutputSize:获取当前渲染输出的像素尺寸 SDL_GetDefaultTextureScaleMode:获取默认的纹理缩放模式 SDL_GetGPURendererDevice:获取 GPU 渲染器关联的设备句柄 SDL_GetNumRenderDrivers:获取系统支持的渲染驱动数量 SDL_GetRenderClipRect:获取渲染裁剪矩形(仅绘制矩形内区域) SDL_GetRenderColorScale:获取渲染颜色缩放系数 SDL_GetRenderDrawBlendMode:获取当前渲染绘制的混合模式 SDL_GetRenderDrawColor:获取当前渲染绘制的颜色(整数格式,0-255) SDL_GetRenderDrawColorFloat:获取当前渲染绘制的颜色(浮点格式,0.0-1.0) SDL_GetRenderDriver:获取指定索引的渲染驱动信息 SDL_GetRenderer:获取窗口关联的渲染器 SDL_GetRendererFromTexture:获取纹理所属的渲染器 SDL_GetRendererName:获取渲染器名称(如 "direct3d11"、"opengl") SDL_GetRendererProperties:获取渲染器的属性集合 SDL_GetRenderLogicalPresentation:获取渲染逻辑显示模式(适配不同分辨率) SDL_GetRenderLogicalPresentationRect:获取渲染逻辑显示矩形 SDL_GetRenderMetalCommandEncoder:获取 Metal 渲染的命令编码器(macOS/iOS) SDL_GetRenderMetalLayer:获取 Metal 渲染层(macOS/iOS) SDL_GetRenderOutputSize:获取渲染器输出的尺寸 SDL_GetRenderSafeArea:获取渲染安全区域(避免屏幕刘海/圆角遮挡) SDL_GetRenderScale:获取渲染缩放比例 SDL_GetRenderTarget:获取当前渲染目标(默认是窗口,也可设为纹理) SDL_GetRenderTextureAddressMode:获取纹理寻址模式(如重复、 clamp) SDL_GetRenderViewport:获取当前渲染视口 SDL_GetRenderVSync:获取垂直同步(VSync)状态 SDL_GetRenderWindow:获取渲染器关联的窗口 SDL_GetTextureAlphaMod:获取纹理透明度调制值(整数格式) SDL_GetTextureAlphaModFloat:获取纹理透明度调制值(浮点格式) SDL_GetTextureBlendMode:获取纹理的混合模式 SDL_GetTextureColorMod:获取纹理颜色调制值(整数格式) SDL_GetTextureColorModFloat:获取纹理颜色调制值(浮点格式) SDL_GetTexturePalette:获取纹理的调色板(针对调色板纹理) SDL_GetTextureProperties:获取纹理的属性集合 SDL_GetTextureScaleMode:获取纹理的缩放模式 SDL_GetTextureSize:获取纹理的像素尺寸 SDL_LockTexture:锁定纹理(获取像素缓冲区,可修改纹理数据) SDL_LockTextureToSurface:锁定纹理并转换为 SDL_Surface(便于像素操作) SDL_RenderClear:清空渲染目标(用当前绘制颜色填充) SDL_RenderClipEnabled:检查渲染裁剪是否启用 SDL_RenderCoordinatesFromWindow:将窗口坐标转换为渲染坐标 SDL_RenderCoordinatesToWindow:将渲染坐标转换为窗口坐标 SDL_RenderDebugText:渲染调试文本(简单文字输出) SDL_RenderDebugTextFormat:渲染格式化调试文本(支持占位符) SDL_RenderFillRect:填充单个矩形 SDL_RenderFillRects:批量填充多个矩形 SDL_RenderGeometry:渲染几何图形(基于顶点/索引数据) SDL_RenderGeometryRaw:渲染原始几何数据(无封装,高性能) SDL_RenderLine:绘制单条线段 SDL_RenderLines:批量绘制多条线段 SDL_RenderPoint:绘制单个点 SDL_RenderPoints:批量绘制多个点 SDL_RenderPresent:提交渲染结果(将后台缓冲区显示到窗口) SDL_RenderReadPixels:读取渲染目标的像素数据 SDL_RenderRect:绘制矩形边框 SDL_RenderRects:批量绘制多个矩形边框 SDL_RenderTexture:绘制纹理(基础接口) SDL_RenderTexture9Grid:9宫格绘制纹理(适配拉伸不变形) SDL_RenderTexture9GridTiled:9宫格平铺绘制纹理 SDL_RenderTextureAffine:仿射变换绘制纹理(平移/旋转/缩放) SDL_RenderTextureRotated:旋转绘制纹理 SDL_RenderTextureTiled:平铺绘制纹理 SDL_RenderViewportSet:设置渲染视口(批量配置) SDL_SetDefaultTextureScaleMode:设置默认的纹理缩放模式 SDL_SetGPURenderState:设置 GPU 渲染状态 SDL_SetGPURenderStateFragmentUniforms:设置 GPU 渲染状态的片元着色器统一变量 SDL_SetGPURenderStateSamplerBindings:设置 GPU 渲染状态的采样器绑定 SDL_SetGPURenderStateStorageBuffers:设置 GPU 渲染状态的存储缓冲区 SDL_SetGPURenderStateStorageTextures:设置 GPU 渲染状态的存储纹理 SDL_SetRenderClipRect:设置渲染裁剪矩形 SDL_SetRenderColorScale:设置渲染颜色缩放系数 SDL_SetRenderDrawBlendMode:设置渲染绘制的混合模式 SDL_SetRenderDrawColor:设置渲染绘制的颜色(整数格式) SDL_SetRenderDrawColorFloat:设置渲染绘制的颜色(浮点格式) SDL_SetRenderLogicalPresentation:设置渲染逻辑显示模式 SDL_SetRenderScale:设置渲染缩放比例 SDL_SetRenderTarget:设置渲染目标(可渲染到纹理) SDL_SetRenderTextureAddressMode:设置纹理寻址模式 SDL_SetRenderViewport:设置渲染视口 SDL_SetRenderVSync:设置垂直同步(开启/关闭) SDL_SetTextureAlphaMod:设置纹理透明度调制(整数格式) SDL_SetTextureAlphaModFloat:设置纹理透明度调制(浮点格式) SDL_SetTextureBlendMode:设置纹理的混合模式 SDL_SetTextureColorMod:设置纹理颜色调制(整数格式) SDL_SetTextureColorModFloat:设置纹理颜色调制(浮点格式) SDL_SetTexturePalette:设置纹理的调色板 SDL_SetTextureScaleMode:设置纹理的缩放模式 SDL_UnlockTexture:解锁纹理(完成像素修改后提交) SDL_UpdateNVTexture:更新 NV12/NV21 格式纹理数据 SDL_UpdateTexture:更新纹理像素数据(通用接口) SDL_UpdateYUVTexture:更新 YUV 格式纹理数据 数据类型 SDL_GPURenderState:GPU 渲染状态的句柄类型(指向渲染管线配置) SDL_Renderer:渲染器句柄类型(核心渲染上下文) 结构体 SDL_GPURenderStateCreateInfo:创建 GPU 渲染状态的参数结构体 SDL_Texture:纹理对象结构体(存储图像数据和属性) SDL_Vertex:顶点结构体(包含位置、颜色、纹理坐标等) 枚举 SDL_RendererLogicalPresentation:渲染逻辑显示模式枚举(适配不同屏幕比例) SDL_TextureAccess:纹理访问权限枚举(静态/动态/渲染目标) SDL_TextureAddressMode:纹理寻址模式枚举(重复、 clamp、镜像等) 宏 SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE:调试文本字体的字符尺寸(像素) SDL_GPU_RENDERER:标识 GPU 渲染器的常量 SDL_SOFTWARE_RENDERER:标识软件渲染器的常量 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 全局变量 Dim As SDL_Window Ptr window = NULL Dim As SDL_Renderer Ptr renderer = NULL Dim As SDL_Texture Ptr texture = NULL Dim As SDL_Rect rect1, rect2 ' 绘制矩形 Dim As Integer quit = 0 Dim As SDL_Event evt ' 初始化 SDL 渲染系统 Function InitRendering() As Integer ' 初始化 SDL If (SDL_Init(SDL_INIT_VIDEO) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL 初始化失败:%s", SDL_GetError()) Return 0 End If ' 创建窗口和渲染器(一键创建) If (SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_SHOWN, @window, @renderer) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_RENDER, "创建窗口/渲染器失败:%s", SDL_GetError()) Return 0 End If ' 设置渲染器绘制颜色(红色,不透明) SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255) ' 创建测试纹理(32位RGBA,100x100,动态访问) texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, _ SDL_TEXTUREACCESS_STREAMING, 100, 100) If (texture = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_RENDER, "创建纹理失败:%s", SDL_GetError()) Return 0 End If ' 设置纹理颜色调制(绿色调) SDL_SetTextureColorMod(texture, 0, 255, 0) ' 定义绘制矩形 rect1.x = 100 : rect1.y = 100 : rect1.w = 200 : rect1.h = 150 ' 填充矩形 rect2.x = 400 : rect2.y = 200 : rect2.w = 100 : rect2.h = 100 ' 纹理绘制位置 Return 1 End Function ' 渲染帧 Sub RenderFrame() ' 清空渲染目标(用红色填充) SDL_RenderClear(renderer) ' 绘制填充矩形(蓝色) SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255) SDL_RenderFillRect(renderer, @rect1) ' 绘制纹理 SDL_RenderTexture(renderer, texture, NULL, @rect2) ' 绘制线段(白色) SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) SDL_RenderLine(renderer, 0, 0, 800, 600) ' 提交渲染结果到窗口 SDL_RenderPresent(renderer) End Sub ' 清理资源 Sub Cleanup() If (texture <> NULL) Then SDL_DestroyTexture(texture) If (renderer <> NULL) Then SDL_DestroyRenderer(renderer) If (window <> NULL) Then SDL_DestroyWindow(window) SDL_Quit() End Sub ' 主程序 If (InitRendering() = 0) Then Cleanup() End 1 End If ' 主循环 While (quit = 0) ' 处理事件 While (SDL_PollEvent(@evt)) If (evt.type = SDL_QUITEVENT) Then quit = 1 End If Wend ' 渲染一帧 RenderFrame() ' 控制帧率(约60FPS) SDL_Delay(16) Wend ' 清理资源 Cleanup() End 0 总结 SDL 2D 渲染子系统核心是 SDL_Renderer(渲染器)和 SDL_Texture(纹理),所有绘制操作需通过渲染器完成,且必须在主线程调用; FreeBASIC 中使用时,先通过 SDL_CreateWindowAndRenderer 初始化窗口和渲染器,再调用 SDL_RenderXXX 绘制图元/纹理,最后用 SDL_RenderPresent 提交画面; 纹理是高效绘制图像的核心,支持颜色/透明度调制、缩放/旋转等变换,SDL_CreateTextureFromSurface 是加载图像到纹理的常用方式。
2026年-3月-6日
220 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_版本(CategoryVersion)
版本子系统(CategoryVersion) 用于查询 SDL 版本信息的功能集,可分别获取应用编译时依赖的头文件版本和运行时链接的库文件版本。 函数 SDL_GetRevision:获取 SDL 库的版本修订号(字符串形式,如 git 提交哈希) SDL_GetVersion:获取运行时链接的 SDL 库的版本号(填充 SDL_version 结构体,包含主/次/微版本) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_MAJOR_VERSION:提取版本号中的主版本号(如 3.1.2 中的 3) SDL_MICRO_VERSION:提取版本号中的微版本号(如 3.1.2 中的 2) SDL_MINOR_VERSION:提取版本号中的次版本号(如 3.1.2 中的 1) SDL_REVISION:SDL 库的编译时修订号(宏定义,静态值) SDL_VERSION:将主/次/微版本号填充到 SDL_version 结构体中(编译时使用) SDL_VERSION_ATLEAST:判断当前 SDL 版本是否≥指定版本(如 SDL_VERSION_ATLEAST(3,0,0)) SDL_VERSIONNUM:将主/次/微版本号合并为一个整数(便于版本比较,格式:主版本1000 + 次版本100 + 微版本) SDL_VERSIONNUM_MAJOR:从合并后的版本整数中提取主版本号 SDL_VERSIONNUM_MICRO:从合并后的版本整数中提取微版本号 SDL_VERSIONNUM_MINOR:从合并后的版本整数中提取次版本号 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 主程序示例 Dim As SDL_version linkedVersion ' 存储运行时链接的 SDL 版本 Dim As ZString Ptr revisionStr ' 存储修订号字符串 ' 1. 获取运行时 SDL 库版本 SDL_GetVersion(@linkedVersion) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "运行时 SDL 版本:%d.%d.%d", _ linkedVersion.major, linkedVersion.minor, linkedVersion.patch) ' 2. 获取 SDL 修订号 revisionStr = SDL_GetRevision() If (revisionStr <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL 修订号:%s", revisionStr) Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL 修订号:未知") End If ' 3. 编译时版本检查(宏使用) #If SDL_VERSION_ATLEAST(3, 0, 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "编译时依赖 SDL 3.x 及以上版本") #Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "编译时依赖 SDL 版本低于 3.0.0") #End If ' 4. 版本号数值比较 Dim As UInteger versionNum = SDL_VERSIONNUM(linkedVersion.major, linkedVersion.minor, linkedVersion.patch) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "版本号数值:%d", versionNum) ' 检查是否满足最低版本要求(如 3.1.0) If (versionNum >= SDL_VERSIONNUM(3, 1, 0)) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "满足 3.1.0 及以上版本要求") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "版本过低,至少需要 SDL 3.1.0") End If ' 5. 提取版本号各部分(宏示例) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "主版本号:%d", SDL_MAJOR_VERSION(linkedVersion)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "次版本号:%d", SDL_MINOR_VERSION(linkedVersion)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "微版本号:%d", SDL_MICRO_VERSION(linkedVersion))
2026年-3月-6日
204 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_断言(CategoryAssert)
断言子系统(CategoryAssert) SDL 提供的增强型断言宏,功能远超常规的 assert 宏,核心特性如下: 利用 sizeof 运算符特性:禁用的断言会从编译代码中完全移除,且仅在断言中引用的变量不会触发“未使用变量”的编译器警告; 避免悬空 else 问题:支持 if (x) SDL_assert(y); else do_something(); 这类写法,行为稳定; 跨平台一致性:不依赖各平台编译器/C 运行时的实现,所有平台行为统一; 多级别断言:提供 SDL_assert、SDL_assert_release、SDL_assert_paranoid 等不同级别,而非“全有或全无”的单一选项; 丰富的失败响应:断言失败时支持重试、触发调试器、终止程序、单次忽略、永久忽略等操作; 可视化提示:默认尝试弹出对话框提示用户(若平台支持),也可自定义回调函数处理断言失败; 重试机制:断言失败后可重试(比如网络故障修复后重新验证条件); 忽略选项:支持单次忽略或永久忽略某类无害的断言失败; 统计能力:向应用程序提供所有断言失败的统计数据和详细信息; 环境变量控制:自动化脚本可通过环境变量控制默认断言处理器行为; 静态分析友好:Clang 静态分析会将 SDL 断言视为“恒真”(假设调试构建能检测断言错误),减少误报。 使用方式:编译调试版本时,在代码中按需添加断言检测逻辑即可! 函数 SDL_GetAssertionHandler:获取当前设置的自定义断言处理函数 SDL_GetAssertionReport:获取所有断言失败的报告(返回 SDL_AssertData 链表) SDL_GetDefaultAssertionHandler:获取 SDL 默认的断言处理函数 SDL_ReportAssertion:手动触发断言报告(底层接口,一般无需直接调用) SDL_ResetAssertionReport:清空所有断言失败的报告数据 SDL_SetAssertionHandler:设置自定义的断言失败处理函数(替换默认逻辑) 数据类型 SDL_AssertionHandler:断言处理函数的函数指针类型(自定义断言处理时需实现) 结构体 SDL_AssertData:存储单个断言失败的详细信息(断言表达式、文件、行号、失败次数等) 枚举 SDL_AssertState:定义断言失败后的处理状态(重试、终止、单次忽略、永久忽略等) 宏 SDL_assert:基础断言宏(调试版本启用,发布版本禁用) SDL_assert_always:强制启用的断言(无论编译模式,始终生效) SDL_ASSERT_FILE:获取断言所在文件路径(内部宏) SDL_ASSERT_LEVEL:定义断言启用级别(控制不同级别断言是否生效) SDL_assert_paranoid:偏执级断言(仅在开启极致调试时启用,用于细粒度检测) SDL_assert_release:发布版本断言(仅在发布版本中启用,检测严重问题) SDL_AssertBreakpoint:触发调试器断点(断言失败时调用) SDL_disabled_assert:禁用断言的占位宏(编译时会被移除) SDL_enabled_assert:启用断言的核心宏(内部实现) SDL_FILE:等价于 FILE,获取当前文件路径 SDL_FUNCTION:等价于 func,获取当前函数名 SDL_LINE:等价于 LINE,获取当前行号 SDL_NULL_WHILE_LOOP_CONDITION:检测 while 循环条件为 NULL 的断言(专用宏) SDL_TriggerBreakpoint:同 SDL_AssertBreakpoint,触发调试断点 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 自定义断言处理函数示例 Function CustomAssertHandler Cdecl (ByVal data As SDL_AssertData Ptr, ByVal userdata As Any Ptr) As SDL_AssertState ' 打印断言失败详情 SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "断言失败:") SDL_LogError(SDL_LOG_CATEGORY_ASSERT, " 文件:%s", data->file) SDL_LogError(SDL_LOG_CATEGORY_ASSERT, " 行号:%d", data->line) SDL_LogError(SDL_LOG_CATEGORY_ASSERT, " 函数:%s", data->function_) SDL_LogError(SDL_LOG_CATEGORY_ASSERT, " 表达式:%s", data->condition) SDL_LogError(SDL_LOG_CATEGORY_ASSERT, " 失败次数:%d", data->trigger_count) ' 这里返回“重试”,也可根据需求返回 SDL_ASSERT_ABORT/SDL_ASSERT_IGNORE 等 Return SDL_ASSERT_RETRY End Function ' 主程序示例 Dim As Integer testValue = -1 ' 设置自定义断言处理器 SDL_SetAssertionHandler(@CustomAssertHandler, NULL) ' 示例1:基础断言(调试模式生效) SDL_assert(testValue > 0) ' testValue=-1,断言失败 ' 示例2:始终生效的断言 SDL_assert_always(testValue <> 0) ' 即使发布版本也会触发 ' 示例3:发布版本断言(仅在 release 模式生效) SDL_assert_release(testValue < 100) ' 表达式为真,断言通过 ' 示例4:获取并打印断言报告 Dim As SDL_AssertData Ptr report = SDL_GetAssertionReport() If (report <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_ASSERT, "断言失败总数:%d", report->trigger_count) SDL_ResetAssertionReport() ' 清空报告 End If ' 恢复默认断言处理器 SDL_SetAssertionHandler(SDL_GetDefaultAssertionHandler(), NULL)
2026年-3月-6日
221 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_日志(CategoryLog)
日志(CategoryLog) SDL 提供的轻量级日志系统,支持为日志消息设置优先级和分类: 日志的 SDL_LogPriority(日志优先级)用于标识消息的重要程度; 日志的 SDL_LogCategory(日志分类)用于标识消息所属的功能域。 每个日志分类都有预设的最低优先级阈值:只有当消息的优先级大于或等于该阈值时,这条日志才会被实际输出。 SDL 自身的日志默认输出优先级低于默认阈值,因此默认情况下不会主动打印 SDL 内部日志。 你可以通过以下方式动态调整日志输出的详细程度: 编程方式:调用 SDL_SetLogPriority() 或 SDL_SetHint(SDL_HINT_LOGGING, ...); 环境变量:设置 SDL_LOGGING 环境变量(格式为逗号分隔的 分类=级别 键值对),用于定义 SDL 应用的默认日志级别。 日志分类取值说明 可以是数字编号,或以下预定义字符串: app(应用层)、error(错误)、assert(断言)、system(系统)、audio(音频)、video(视频)、render(渲染)、input(输入)、test(测试); * 表示所有未单独指定的分类。 日志级别取值说明 可以是数字级别,或以下预定义字符串: trace(追踪)、verbose(详细)、debug(调试)、info(信息)、warn(警告)、error(错误)、critical(严重); quiet 表示禁用该分类的日志输出。 若省略分类,将为所有分类设置统一的日志级别。 如果未设置 SDL_HINT_LOGGING 提示,默认日志级别等价于: app=info,assert=warn,test=verbose,*=error 不同平台的日志输出目标 Windows:调试输出流(Debug Output); Android:系统日志(Logcat); 其他平台:标准错误输出(stderr)。 日志使用注意事项 无需在日志消息末尾添加换行符(\n),函数会自动补充; 为保证跨平台行为一致,不要在单条日志中包含换行符(比如试图一次调用输出多行),这种用法可能导致平台相关的异常行为,建议每行日志单独调用一次函数,且消息中不含换行; 每个日志调用都是原子操作,多线程日志输出时不会出现消息截断的问题。 函数 SDL_GetDefaultLogOutputFunction:获取 SDL 默认的日志输出回调函数 SDL_GetLogOutputFunction:获取当前生效的日志输出回调函数 SDL_GetLogPriority:获取指定日志分类的当前最低输出优先级 SDL_Log:输出一条默认优先级(info)、默认分类(app)的日志(支持格式化字符串) SDL_LogCritical:输出一条“严重”优先级的日志(默认分类为 app) SDL_LogDebug:输出一条“调试”优先级的日志(默认分类为 app) SDL_LogError:输出一条“错误”优先级的日志(默认分类为 app) SDL_LogInfo:输出一条“信息”优先级的日志(默认分类为 app) SDL_LogMessage:输出指定分类、指定优先级的日志(核心通用接口,支持格式化) SDL_LogMessageV:基于 va_list 可变参数列表输出指定分类/优先级的日志(底层实现) SDL_LogTrace:输出一条“追踪”优先级的日志(默认分类为 app) SDL_LogVerbose:输出一条“详细”优先级的日志(默认分类为 app) SDL_LogWarn:输出一条“警告”优先级的日志(默认分类为 app) SDL_ResetLogPriorities:重置所有日志分类的优先级为默认值 SDL_SetLogOutputFunction:设置自定义的日志输出回调函数(替换默认输出逻辑) SDL_SetLogPriorities:批量设置所有日志分类的最低输出优先级(按位掩码) SDL_SetLogPriority:设置指定日志分类的最低输出优先级 SDL_SetLogPriorityPrefix:设置是否在日志中添加优先级前缀(如 [CRITICAL]、[WARN]) 数据类型 SDL_LogOutputFunction:日志输出回调函数的函数指针类型(自定义日志输出时需实现) 结构体 (无) 枚举 SDL_LogCategory:定义日志分类的枚举(如应用、音频、视频、错误等) SDL_LogPriority:定义日志优先级的枚举(如追踪、调试、信息、警告、错误、严重等) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库) #Include "SDL.bi" ' 示例1:基础日志输出 SDL_Log("应用启动,版本:%s", "1.0.0") ' 默认 info 级别、app 分类 SDL_LogWarn(SDL_LOG_CATEGORY_AUDIO, "音频设备初始化警告:设备数量 = %d", 0) ' 音频分类 警告级别 SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "窗口创建失败:%s", SDL_GetError()) ' 视频分类 错误级别 SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "系统资源不足,程序即将退出") ' 系统分类 严重级别 ' 示例2:调整日志输出级别(让视频分类输出所有级别日志) SDL_SetLogPriority(SDL_LOG_CATEGORY_VIDEO, SDL_LOG_PRIORITY_TRACE) ' 示例3:输出低优先级日志(仅当视频分类级别调整后才会显示) SDL_LogTrace(SDL_LOG_CATEGORY_VIDEO, "视频驱动初始化:检测到 %d 个显示器", SDL_GetNumVideoDisplays()) ' 示例4:重置所有日志优先级为默认值 SDL_ResetLogPriorities()
2026年-3月-6日
254 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_错误处理(CategoryError)
错误处理(CategoryError) SDL 提供的轻量级错误消息处理函数集。 绝大多数应用程序只会通过一个核心函数与这些 API 交互:当几乎所有 SDL 函数调用返回失败时,你可以通过 SDL_GetError() 获取该错误对应的人类可读字符串描述。 这些错误字符串是按线程独立维护的,应用程序也可以自定义错误信息(这在基于 SDL 构建供其他应用使用的库时非常常用),只需调用 SDL_SetError() 即可设置自定义错误信息。 一种常见的使用模式是:设计一个返回布尔值的函数(true 表示成功,false 表示失败),当内部操作失败时执行如下逻辑: ' FreeBASIC 示例代码 If (something_went_wrong) Then ' 设置错误信息并返回失败 SDL_SetError("该操作因以下原因失败:错误码 = %d", errcode) Return False End If 另一种常见做法是:如果已知触发失败的底层操作已经调用了 SDL_SetError(),则直接返回 false 即可,错误信息会自动向上传递。 函数 SDL_ClearError:清空当前线程的错误信息 SDL_GetError:获取当前线程的错误描述字符串 SDL_OutOfMemory:抛出“内存不足”错误并返回 0(常用于内存分配失败场景) SDL_SetError:设置自定义错误信息(支持格式化字符串) SDL_SetErrorV:基于 va_list 可变参数列表设置错误信息(底层实现函数) 数据类型 (无) 结构体 (无) 枚举 (无) 宏 SDL_InvalidParamError:快速设置“无效参数”错误(参数:参数名) SDL_Unsupported:快速设置“功能不支持”错误
2026年-3月-6日
202 阅读
0 评论
VisualFreeBasic编程文档
2026-3-6
SDL3_API分类参考_对象属性(CategoryProperties)
对象属性(CategoryProperties) 属性(Property)是一种可以在运行时通过名称创建和获取的变量。 所有属性都属于一个属性组(属性组ID:SDL_PropertiesID)。 属性组可通过 SDL_CreateProperties 函数创建,通过 SDL_DestroyProperties 函数销毁。 可通过以下函数向属性组添加/获取属性: SDL_SetPointerProperty / SDL_GetPointerProperty:操作 void* 指针类型 SDL_SetStringProperty / SDL_GetStringProperty:操作字符串类型 SDL_SetNumberProperty / SDL_GetNumberProperty:操作有符号64位整数类型 SDL_SetFloatProperty / SDL_GetFloatProperty:操作浮点类型 SDL_SetBooleanProperty / SDL_GetBooleanProperty:操作布尔类型 可通过 SDL_ClearProperty 从属性组中移除属性。 函数/类型/枚举/宏 翻译 + 简要说明 英文名称 中文翻译 简要说明 SDL_ClearProperty 清除属性 从属性组中移除指定名称的属性 SDL_CopyProperties 复制属性 将一个属性组的所有属性复制到另一个属性组 SDL_CreateProperties 创建属性组 新建一个空的属性组并返回其ID SDL_DestroyProperties 销毁属性组 释放属性组及其所有属性占用的内存 SDL_EnumerateProperties 枚举属性 遍历属性组中所有属性并调用回调函数 SDL_GetBooleanProperty 获取布尔属性 从属性组中读取布尔类型属性值 SDL_GetFloatProperty 获取浮点属性 从属性组中读取浮点类型属性值 SDL_GetGlobalProperties 获取全局属性组 获取SDL全局属性组的ID SDL_GetNumberProperty 获取数值属性 从属性组中读取64位有符号整数属性值 SDL_GetPointerProperty 获取指针属性 从属性组中读取指针类型属性值 SDL_GetPropertyType 获取属性类型 获取指定属性的类型(SDL_PropertyType) SDL_GetStringProperty 获取字符串属性 从属性组中读取字符串类型属性值 SDL_HasProperty 检查属性存在性 判断属性组中是否存在指定名称的属性 SDL_LockProperties 锁定属性组 加锁属性组以保证线程安全 SDL_SetBooleanProperty 设置布尔属性 向属性组写入布尔类型属性值 SDL_SetFloatProperty 设置浮点属性 向属性组写入浮点类型属性值 SDL_SetNumberProperty 设置数值属性 向属性组写入64位有符号整数属性值 SDL_SetPointerProperty 设置指针属性 向属性组写入指针类型属性值 SDL_SetPointerPropertyWithCleanup 设置带清理的指针属性 写入指针属性并指定清理回调函数 SDL_SetStringProperty 设置字符串属性 向属性组写入字符串类型属性值 SDL_UnlockProperties 解锁属性组 释放属性组的线程锁 SDL_CleanupPropertyCallback 属性清理回调函数类型 释放指针属性时的回调函数类型定义 SDL_EnumeratePropertiesCallback 属性枚举回调函数类型 枚举属性时的回调函数类型定义 SDL_PropertiesID 属性组ID类型 标识属性组的唯一ID类型 SDL_PropertyType 属性类型枚举 定义所有支持的属性类型(指针/字符串/数值等) SDL_PROP_NAME_STRING 属性名字符串宏 用于标准化属性名称的宏定义 FreeBASIC 示例代码 ' 编译前需确保已链接SDL2库 ' 编译命令示例:fbc -s console -lSDL2 properties_demo.bas #include "SDL.bi" ' 错误检查宏 #define CHECK_ERROR(ret, msg) if (ret <> 0) then print msg & " 失败,错误:" & *SDL_GetError() : goto cleanup Sub DemoProperties() Dim As SDL_PropertiesID props = SDL_CreateProperties() If (props = 0) Then Print "创建属性组失败,错误:" & *SDL_GetError() Return End If Print "成功创建属性组,ID:" & props ' 1. 设置/获取字符串属性 Dim As Integer ret = SDL_SetStringProperty(props, "window.title", "SDL属性示例") CHECK_ERROR(ret, "设置字符串属性") Dim As ZString Ptr title = SDL_GetStringProperty(props, "window.title", "默认标题") Print "读取窗口标题:" & *title ' 2. 设置/获取数值属性(64位整数) ret = SDL_SetNumberProperty(props, "window.width", 800) CHECK_ERROR(ret, "设置数值属性") Dim As Int64 width = SDL_GetNumberProperty(props, "window.width", 640) Print "读取窗口宽度:" & width ' 3. 设置/获取布尔属性 ret = SDL_SetBooleanProperty(props, "fullscreen", SDL_TRUE) CHECK_ERROR(ret, "设置布尔属性") Dim As SDL_bool fullscreen = SDL_GetBooleanProperty(props, "fullscreen", SDL_FALSE) Print "读取全屏状态:" & IIf(fullscreen = SDL_TRUE, "开启", "关闭") ' 4. 检查属性是否存在 If (SDL_HasProperty(props, "window.height") = SDL_FALSE) Then Print "属性 window.height 不存在,设置默认值 600" ret = SDL_SetNumberProperty(props, "window.height", 600) CHECK_ERROR(ret, "设置默认高度") End If ' 5. 枚举所有属性(自定义回调函数) Print vbCrLf & "枚举所有属性:" Sub EnumerateCallback cdecl (ByVal userdata As Any Ptr, ByVal name As Const ZString Ptr, ByVal type_ As SDL_PropertyType) As SDL_bool Print "属性名:" & *name & ",类型:" & type_ Return SDL_TRUE ' 继续枚举 End Sub SDL_EnumerateProperties(props, @EnumerateCallback, Null) ' 6. 清除单个属性 ret = SDL_ClearProperty(props, "fullscreen") CHECK_ERROR(ret, "清除全屏属性") If (SDL_HasProperty(props, "fullscreen") = SDL_FALSE) Then Print vbCrLf & "已成功清除 fullscreen 属性" End If cleanup: ' 销毁属性组 If (props <> 0) Then SDL_DestroyProperties(props) Print vbCrLf & "已销毁属性组" End If End Sub ' 主程序 SDL_Init(SDL_INIT_VIDEO) DemoProperties() SDL_Quit() Print vbCrLf & "按任意键退出..." Sleep
2026年-3月-6日
250 阅读
0 评论
VisualFreeBasic编程文档
4
5
6
7
8