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

Vulkan粒子系统透明度异常问题排查求助

粒子系统透明度异常问题排查求助

我正在修改同事开发的粒子系统,原本通过计算管线手动混合/设置像素进行渲染,现改为2D图形渲染方式,但遇到了奇怪的透明度问题:当粒子alpha值高于约0.2时,图像渲染正常;但低于该值时,粒子会显示为纯白色。

我已排查了多数可能的错误来源——确认已启用混合功能,混合操作配置如下:

VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;

渲染后的异常效果:
渲染后的粒子

粒子纹理在GIMP中显示正常,调整片段着色器以显示alpha值时,结果符合预期:
着色器显示alpha值

顶点着色器和片段着色器代码如下:

#version 450

layout(binding = 0) uniform UniformBufferObject {
    mat4 proj;
} ubo;

layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec2 inTexCoord;
layout(location = 2) in vec4 inColor;

layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec2 fragTexCoord;

void main()
{
    gl_Position = ubo.proj * vec4(inPosition, 0.0, 1.0);
    fragColor = inColor;
    fragTexCoord = inTexCoord;
}

//----------------------------------------

#version 450

layout(binding = 1) uniform sampler2D texSampler;

layout(location = 0) in vec4 fragColor;
layout(location = 1) in vec2 fragTexCoord;

layout(location = 0) out vec4 outColor;

void main()
{
    outColor = texture(texSampler, fragTexCoord);
}

渲染代码片段:

CommandBufferBeginInfo const beginInfo{};
VK_CHECK_RESULT(vkBeginCommandBuffer(vkCommandBuffer_, &beginInfo));

RenderPassBeginInfo renderPassInfo{};
renderPassInfo.renderPass = *renderPass_;
renderPassInfo.framebuffer = framebuffer_->getVulkanFramebuffer();
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent.width = uint32_t(windowSize_.x);
renderPassInfo.renderArea.extent.height = uint32_t(windowSize_.y);

constexpr VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(vkCommandBuffer_, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(vkCommandBuffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_);

const VkBuffer vertexBuffers[] = { backgroundVertexBuffer_->getVulkanBuffer(),  particleVertexBuffer_->getVulkanBuffer() };
const VkDescriptorSet descriptorSets[] = { *backgroundDescriptorSet_, *particleDescriptorSet_ };
constexpr VkDeviceSize offsets[] = { 0 };
vkCmdBindIndexBuffer(vkCommandBuffer_, indexBuffer_->getVulkanBuffer(), 0, VK_INDEX_TYPE_UINT16);

// Draw Background
vkCmdBindVertexBuffers(vkCommandBuffer_, 0, 1, &vertexBuffers[0], offsets);
vkCmdBindDescriptorSets(vkCommandBuffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout_, 0, 1,
&descriptorSets[0], 0, nullptr);
vkCmdDrawIndexed(vkCommandBuffer_, uint32_t(std::size(Quad::indices)), 1, 0, 0, 0);

// Draw particles.
vkCmdBindVertexBuffers(vkCommandBuffer_, 0, 1, &vertexBuffers[1], offsets);
vkCmdBindDescriptorSets(vkCommandBuffer_, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout_, 0, 1,
&descriptorSets[1], 0, nullptr);
for (auto i = 0u; i < effect_->getParticleCount(); ++i)
{
    vkCmdDrawIndexed(vkCommandBuffer_, uint32_t(std::size(Quad::indices)), 1, 0, int32_t(i) * 4, 0);
}

vkCmdEndRenderPass(vkCommandBuffer_);
VK_CHECK_RESULT(vkEndCommandBuffer(vkCommandBuffer_));

当前没有使用深度缓冲,也没有深度子通道,但这似乎无法解释我看到的现象。不确定还有哪些可能的原因,恳请提供排查建议。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:13:14