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

如何在Vulkan游戏引擎中从帧缓冲读取自定义实体ID数据

Vulkan鼠标拾取:解决片段着色器输出无匹配附件问题

我正在Vulkan游戏引擎中实现鼠标拾取功能,需要从帧缓冲读取存储实体ID的特定附件。目前已成功读取RGBA数据,但片段着色器输出的实体ID没有对应的帧缓冲附件,触发了验证层警告。

片段着色器代码

#version 450 core

struct VertexInput
{
    vec4 Color;
    vec2 TexCoord;
    float TilingFactor;
};

// Inputs
layout(location = 0) in VertexInput Input;
layout(location = 3) in flat uint in_TexIndex;
layout(location = 4) in flat int in_EntityID;

layout(binding = 1) uniform sampler2D u_Samplers[10];

// Outputs
layout(location = 0) out vec4 o_Color;
layout(location = 1) out int o_EntityID; // 需要存储的实体ID

void main()
{
    o_EntityID = in_EntityID;
    o_Color = Input.Color * texture(u_Samplers[in_TexIndex], Input.TexCoord * Input.TilingFactor);
} 

触发的验证层警告

Validation layer: Validation Warning: [ UNASSIGNED-CoreValidation-Shader-OutputNotConsumed ] Object 0: handle = 0x5dbcf90000000065, type = VK_OBJECT_TYPE_SHADER_MODULE; | MessageID = 0x609a13b | fragment shader writes to output location 1 with no matching attachment

解决思路与步骤

核心问题

警告的本质是片段着色器向location=1输出数据,但当前渲染使用的帧缓冲没有对应位置的颜色附件,导致输出没有接收目标。


1. 创建存储实体ID的图像资源

需要创建一个整数格式的单通道图像,避免实体ID因浮点精度丢失:

  • 格式选择:匹配着色器输出类型,用VK_FORMAT_R32_SINT(对应int类型)或VK_FORMAT_R32_UINT(对应uint类型)
  • 图像用法:必须包含VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT(作为颜色附件),如果需要CPU读取,加上VK_IMAGE_USAGE_TRANSFER_SRC_BIT
  • 内存属性:基础需求是VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT(GPU可访问);若要CPU读取,额外添加VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

2. 创建对应图像视图

为上述图像创建图像视图,格式与图像保持一致,视图类型设为VK_IMAGE_VIEW_TYPE_2D。

3. 更新渲染通道(Render Pass)

在渲染通道的颜色附件描述中添加第二个条目:

  • 设置location=1,对应着色器的输出位置
  • 格式与图像/图像视图一致
  • 加载操作:选VK_ATTACHMENT_LOAD_OP_CLEAR(每次渲染前清空,避免残留旧ID)
  • 存储操作:选VK_ATTACHMENT_STORE_OP_STORE(保留数据供后续读取)
  • 初始布局:VK_IMAGE_LAYOUT_UNDEFINED
  • 最终布局:若要CPU读取,设为VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;若仅GPU内使用,设为VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL

同时,在子通道描述的pColorAttachments数组中,添加这个新附件的引用。

4. 更新帧缓冲(Framebuffer)

将新创建的图像视图添加到帧缓冲的附件列表中,位置要和渲染通道中第二个颜色附件的索引对应。

5. 关联图形管线

确保你的图形管线使用的是更新后的渲染通道,管线会自动关联渲染通道的附件与着色器输出位置。

6. 读取实体ID数据

  • GPU内读取:可在后续着色器中直接采样这个颜色附件
  • CPU读取:发起图像拷贝操作,将GPU内存中的图像数据复制到CPU可见内存,再读取鼠标对应坐标的像素值(注意Vulkan图像坐标原点通常为左上角,需和屏幕坐标做转换)

额外注意事项

  • 如果实体ID是无符号整数,需将着色器中的int改为uint,对应格式切换为VK_FORMAT_R32_UINT
  • 若使用多采样,图像和附件都要设置对应采样数
  • 清空附件时,清除值要设为无效实体ID(比如-1或0),方便区分未渲染区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:20:45