概述
MipMap(纹理金字塔)是一种纹理处理技术,它预先生成一系列分辨率逐渐降低的纹理图像。
MipMap 的基本概念
原始纹理(级别 0): 256 x 256
第一级 Mip(级别 1): 128 x 128
第二级 Mip(级别 2): 64 x 64
第三级 Mip(级别 3): 32 x 32
第四级 Mip(级别 4): 16 x 16
...直到 1x1
在 Vulkan 中创建带 MipMap 的纹理:
// 计算 MipMap 级别
uint32_t mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
// 创建图像时指定 MipMap 级别
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = mipLevels; // 指定 MipMap 级别数量
imageInfo.arrayLayers = 1;MipMap 的生成过程
void generateMipmaps(VkImage image, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) {
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
for (uint32_t i = 1; i < mipLevels; i++) {
// 设置图像布局转换障碍
VkImageMemoryBarrier barrier = {};
// ... 设置 barrier 参数
// 执行 blit 操作来生成下一级 MipMap
VkImageBlit blit = {};
blit.srcOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {mipWidth, mipHeight, 1};
blit.dstOffsets[0] = {0, 0, 0};
blit.dstOffsets[1] = {mipWidth > 1 ? mipWidth / 2 : 1,
mipHeight > 1 ? mipHeight / 2 : 1,
1};
vkCmdBlitImage(commandBuffer,
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit,
VK_FILTER_LINEAR);
mipWidth = mipWidth > 1 ? mipWidth / 2 : 1;
mipHeight = mipHeight > 1 ? mipHeight / 2 : 1;
}
endSingleTimeCommands(commandBuffer);
}MipMap 的主要用途
性能优化
- 减少内存带宽使用
- 减少采样计算量
- 避免远处纹理的采样混叠
视觉质量
- 减少远处纹理的闪烁
- 提供更平滑的层级过渡
- 改善整体视觉效果
MipMap 级别的选择
// 在采样器创建时设置 MipMap 参数
VkSamplerCreateInfo samplerInfo = {};
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; // MipMap 层级间的插值方式
samplerInfo.minLod = 0.0f; // 最小 LOD 级别
samplerInfo.maxLod = static_cast<float>(mipLevels); // 最大 LOD 级别
samplerInfo.mipLodBias = 0.0f; // LOD 偏移值实际应用场景
远景渲染
// 根据距离选择合适的 MipMap 级别
float distance = length(cameraPos - objectPos);
float lodLevel = log2(distance / baseDistance);LOD 过渡
// 在着色器中手动控制 LOD 级别
vec4 color = textureLod(sampler2D tex, vec2 coord, float lod);内存占用分析
总内存 = 原始大小 * (4/3)
例如:
256x256 原始纹理 = 65,536 像素
128x128 = 16,384 像素
64x64 = 4,096 像素
...
总像素 = 65,536 + 16,384 + 4,096 + ... ≈ 87,381 像素
使用注意事项
性能考虑
- 根据实际需求选择是否生成 MipMap
- 权衡内存使用和渲染质量
- 考虑生成 MipMap 的计算开销
质量控制
- 选择合适的过滤模式
- 调整 LOD 偏移以控制细节级别
- 注意边界情况的处理
MipMap 是图形渲染中非常重要的优化技术,它通过预先生成不同分辨率的纹理版本,在保证渲染质量的同时提高了性能。理解和正确使用 MipMap 对于开发高质量的图形应用至关重要。