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

DirectX11粒子系统:Compute Shader可访问CBufffer,Pixel Shader值未初始化

问题:DirectX11粒子系统中图形管线着色器无法读取CBUFFER值

在学习DirectX11开发粒子系统时,遇到了一个奇怪的问题:C++中定义了与HLSL的cbuffer完全对应的结构体,Compute Shader可以正常访问cbuffer中的变量,但Pixel Shader、Geometry Shader等图形管线内的着色器无法读取初始化后的值——本该显示白色的方块呈现黑色,只有手动修改Pixel Shader中颜色的w值为1才能看到内容。


代码实现细节

C++中的CBUFFER定义

CBUFFER(ParticleSystemCB, CBSLOT_PARTICLESYSTEM)
{
    lu::math::Color startTint;
    lu::math::Color endTint;
    lu::math::Quaternion startRot;
    lu::math::Quaternion endRot;
    float lifeTime;
    float elapsedTime;
    float deltaTime;

    float startSize;
    float endSize;
    float startSpeed;
    float endSpeed;
    
    int elementCount;
};

HLSL中的cbuffer定义

cbuffer ParticleSystem : register(b3)
{
    float4  particleStartTint;
    float4  particleEndTint;
    float4  particleStartRotation;
    float4  particleEndRotation;
    float   particleLifetime;
    float   particleElapsedTime;
    float   particleDeltaTime;
    
    float   particleStartSize;
    float   particleEndSize;
    float   particleStartSpeed;
    float   particleEndSpeed;
    
    uint elementCount;
}

渲染与绑定代码

ParticleSystem::Render方法

graphics::StructedBuffer* mParticleBuffer;
graphics::StructedBuffer* mSharedBuffer;
std::shared_ptr<ParticleShader> mParticleShader;

void ParticleSystem::Render()
{
    Owner()->GetComponent<Transform>()->BindConstantBuffer();
    mParticleShader->OnExecute();//binds and dispatches compute shader
    mParticleShader->SetParticles(mParticleBuffer, this);
    mParticleShader->SetSharedBuffer(mSharedBuffer);

    mParticleBuffer->BindSRV(eShaderStage::VS, 14);
    mParticleBuffer->BindSRV(eShaderStage::GS, 14);
    mParticleBuffer->BindSRV(eShaderStage::PS, 14);

    GetMaterial()->Binds();
    GetMesh()->RenderInstanced(1000);

    mParticleBuffer->clear();
}

ParticleShader::SetParticles方法

void ParticleShader::SetParticles(StructedBuffer* particleBuffer, ParticleSystem* ps)
{
    mParticleBuffer = particleBuffer;
    ConstantBuffer* cb = renderer::constantBuffer[(UINT)eCBType::ParticleSystem];

    renderer::ParticleSystemCB data = {};
    data.startTint = ps->mStartTint;
        //and other data Initializations

    cb->SetData(&data);
    cb->Bind(eShaderStage::CS);
}

着色器代码片段

Compute Shader(可正常读取)

RWStructuredBuffer<Particle> ParticleBuffer : register(u0);
RWStructuredBuffer<ParticleShared> ParticleSharedBuffer : register(u1);

void InitializeParticle(int id)
{
//correctly assigned
    ParticleBuffer[id].lifeTime = particleLifetime;
}

Pixel Shader(无法正确读取)

float4 main(GSOut In) : SV_TARGET
{
    color = particleStartTint;
    color.w = 1;

    return color;
}

已确认的信息

  • HLSL代码无语法错误(通过ID3DBlob检查)
  • cbuffer插槽号正确(register(b3)与CBSLOT_PARTICLESYSTEM对应)
  • C++与HLSL的结构体布局完全匹配
  • Compute Shader绑定后可正常读取cbuffer数据
  • Pixel Shader在cbuffer绑定后仍无法读取值

解决方案

问题的核心是cbuffer的绑定范围不全:当前代码只将ParticleSystemCB绑定到了Compute Shader(cb->Bind(eShaderStage::CS);),但图形管线中的VS、GS、PS并没有绑定这个cbuffer,导致这些着色器无法访问其中的变量。

修改SetParticles方法,将cbuffer绑定到所有需要的着色器阶段即可:

void ParticleShader::SetParticles(StructedBuffer* particleBuffer, ParticleSystem* ps)
{
    mParticleBuffer = particleBuffer;
    ConstantBuffer* cb = renderer::constantBuffer[(UINT)eCBType::ParticleSystem];

    renderer::ParticleSystemCB data = {};
    data.startTint = ps->mStartTint;
    // 完成其他数据初始化...

    cb->SetData(&data);
    // 绑定到Compute Shader
    cb->Bind(eShaderStage::CS);
    // 同时绑定到图形管线的着色器阶段
    cb->Bind(eShaderStage::VS);
    cb->Bind(eShaderStage::GS);
    cb->Bind(eShaderStage::PS);
}

如果你的引擎封装支持多阶段批量绑定,也可以简化为:

// 假设Bind方法接受多个ShaderStage的位或组合
cb->Bind(eShaderStage::CS | eShaderStage::VS | eShaderStage::GS | eShaderStage::PS);

另外需要确认渲染顺序:确保在GetMaterial()->Binds()之前完成所有cbuffer的绑定,避免材质的绑定操作覆盖当前的cbuffer设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:12:11