You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

体素世界无缝纹理问题求助:基于Vulkan的Minecraft复刻项目

Minecraft复刻项目Vulkan精灵表纹理无缝拼接边框问题排查方案

我正在开发一款Minecraft复刻项目,已实现基于噪声高度图的简易无限世界生成,但目前遇到纹理问题:纹理存在明显边框,无法实现无缝拼接。项目采用精灵表将单张纹理传入GPU,通过不同纹理坐标区分不同方块类型,渲染后端使用Vulkan,相关纹理配置代码如下:

VkSamplerCreateInfo sInfo{};
sInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
sInfo.pNext = nullptr;

sInfo.magFilter = VK_FILTER_NEAREST;
sInfo.minFilter = VK_FILTER_LINEAR;
sInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
sInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
sInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
sInfo.anisotropyEnable = VK_TRUE;

VkPhysicalDeviceProperties Props;
vkGetPhysicalDeviceProperties(Engine::Get().GetGpuHandle(), &Props);

sInfo.maxAnisotropy = Props.limits.maxSamplerAnisotropy;
sInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
sInfo.unnormalizedCoordinates = VK_FALSE;
sInfo.compareEnable = VK_FALSE;
sInfo.compareOp = VK_COMPARE_OP_ALWAYS;
sInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
sInfo.mipLodBias = 0.f;
sInfo.minLod = 0.f;
sInfo.maxLod = 1;

VkImageCreateInfo iInfo{};
iInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
iInfo.pNext = nullptr;
iInfo.arrayLayers = 1;
iInfo.extent = { extent.width,extent.height,1 };
iInfo.imageType = VK_IMAGE_TYPE_2D;
iInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
iInfo.mipLevels = 1;
iInfo.samples = samples;
iInfo.flags = 0;
iInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
Info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
iInfo.format = format;
iInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

VkImageViewCreateInfo vInfo{};
vInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
vInfo.pNext = nullptr;
vInfo.image = m_Image;
vInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
vInfo.format = format;
vInfo.flags = 0;
vInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vInfo.subresourceRange.baseMipLevel = 0;
vInfo.subresourceRange.levelCount = 1;
vInfo.subresourceRange.baseArrayLayer = 0;
vInfo.subresourceRange.layerCount = 1;

起初认为是精灵表的问题,更换多张精灵表后问题依旧;尝试调整多种采样器参数组合也未解决。以下是可行的排查和解决思路:

  • 修复纹理创建的参数错误:代码中Info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;存在明显错误——VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL是纹理布局枚举,不是usage枚举。正确的写法应为iInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;,纹理布局需要通过vkCmdPipelineBarrier在后续步骤中转换,错误的usage配置会导致纹理采样行为异常,这很可能是核心问题。

  • 修正纹理坐标的边缘偏移:使用精灵表时,若纹理坐标刚好落在块边缘,线性过滤会采样到相邻纹理块的像素。给每个纹理块的UV坐标添加微小偏移,比如每个方块为N×N像素,那么坐标范围应改为从(x*N + 0.5)/总纹理宽度到((x+1)*N - 0.5)/总纹理宽度(V方向同理),避免采样到边缘外的像素。

  • 调整采样器与mipmap的匹配设置:当前采样器设置了mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,但纹理的mipLevels = 1(无多级渐远纹理),这种不匹配可能导致采样异常。可以将mipmapMode改为VK_SAMPLER_MIPMAP_MODE_NEAREST,同时将maxLod设为0.f,确保采样器只使用基础层级纹理。

  • 给精灵表添加边缘padding:在制作精灵表时,给每个纹理块周围添加1像素的重复边缘(复制纹理块的边缘像素到padding区域),这样即使GPU采样到边缘,插值的也是相同像素,不会出现跨块的边框。

  • 统一过滤模式测试:当前采样器混合使用了NEAREST和LINEAR过滤,可尝试暂时统一为VK_FILTER_NEAREST,观察边框是否消失,以此判断是否是线性过滤的边缘插值导致的问题。

内容的提问来源于stack exchange,提问作者Ishan Chaudhari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:46:35