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

DX11着色器仅绑定未使用常量缓冲区时正常执行问题求助

DX11着色器常量缓冲区异常问题

只有将像素着色器中寄存器b1的常量缓冲区设置为指定的ConstantBuffer结构体时,着色器才能正常工作。排查8小时后发现,ConstantBuffer中的time变量数据似乎混入了CameraBuffer的变量中。已使用__declspec(align(16))处理内存对齐,且自认为数据填充正确,但问题依旧。

C++代码实现

// A buffer for lighting
__declspec(align(16))
struct CameraBuffer {
    Vec3f position{};
    Vec3f direction{};
    Vec2f pad{};
};

// The buffer required for proper results, even though it shouldn't be required.
__declspec(align(16))
struct ConstantBuffer {
    float time;
    float period;
    float amplitude;
};

// Method for drawing a sphere
void DXGLApp::drawMaterialSphere(Vec3f position, dxgl::SP_DXGLMaterial material) {
    // transform data
    dxgl::buffer::TransformBuffer tbuff1{};
    tbuff1.world.setIdentity();
    tbuff1.world.setTranslation(position);
    tbuff1.view = m_camera->view();
    tbuff1.proj = m_camera->proj();
    m_cbLandscape->update(&tbuff1);

    // setting vertex data
    render()->stageInput()->setInputLayout(m_layout);
    render()->stageInput()->setVertexBuffers(1, &m_mesh1->getVertexBuffer());
    render()->stageInput()->setIndexBuffer(m_mesh1->getIndexBuffer());

    // setting shaders
    render()->stageShader()->VS_setShader(m_vs);
    render()->stageShader()->PS_setShader(m_ps);

    // setting cbuffers
    render()->stageShader()->VS_setCBuffer(0, 1, m_cbLandscape->get());
    render()->stageShader()->PS_setCBuffer(0, 1, m_cbCamera->get());

    // This cbuffer, 'm_cbPostProcess' is not used in the currently bound shader,
    // yet the results produced without it are incorrect.
    render()->stageShader()->PS_setCBuffer(1, 1, m_cbPostProcess->get());

    // sets texture slots
    render()->stageShader()->PS_setMaterial(0, 6, material);

    // draw
    render()->stageInput()->drawIndexedTriangleList(m_mesh1->getIndices().size(), 0, 0);

    // unbind
    //render()->stageShader()->VS_setShader(0);
    //render()->stageShader()->PS_setShader(0);
    //render()->stageShader()->VS_setCBuffer(0, 0, 0);
    //render()->stageShader()->PS_setCBuffer(0, 0, 0);
}

void update(long double delta) {
    // updating m_cbCamera
    dxgl::buffer::CameraBuffer camBuff{};
    camBuff.position = m_camera->world().getTranslation();
    camBuff.direction = m_camera->world().getZDirection();
    m_cbCamera->update(&camBuff);

    // updating m_cbPostProcess
    ConstantBuffer dvbuff{};
    dvbuff.time = t / 4.0f;
    dvbuff.period = 0;// 8.0f;
    dvbuff.amplitude = 0;// 0.0125f;
    m_cbPostProcess->update(&dvbuff);
}

着色器代码实现

顶点着色器

struct VS_Input {
    float4 position: POSITION;
    float2 texcoord: TEXCOORD;
    float3 normal:   NORMAL;
    float3 tangent:  TANGENT;
};

struct PS_Input {
    float4 position: SV_POSITION;
    float2 texcoord: TEXCOORD;
    float3 normal:   NORMAL;
    float3 tangent:  TANGENT;

    float3 pixelPosition: POSITION;
};

cbuffer transform: register(b0) {
    row_major float4x4 world;
    row_major float4x4 view;
    row_major float4x4 proj;
};

PS_Input main(VS_Input input) {
    PS_Input output = (PS_Input)0;

    output.position = mul(input.position, world);
    output.position = mul(output.position, view);
    output.position = mul(output.position, proj);

    output.pixelPosition = mul(input.position, world);

    output.texcoord = input.texcoord;

    output.normal = mul(input.normal, world);
    output.tangent = mul(input.tangent, world);

    return output;
}

像素着色器

struct PS_Input {
    float4 position: SV_POSITION;
    float2 texcoord: TEXCOORD;
    float3 normal:   NORMAL;
    float3 tangent:  TANGENT;

    float3 pixelPosition: POSITION;
};

cbuffer camera: register(b0) {
    float4 cameraPosition;
    float4 cameraDirection;
}

float PI = 3.14159265359f;

SamplerState textureSampler: register(s0);

Texture2D tex_normalMap:    register(t0);
Texture2D tex_heightMap:    register(t1);
Texture2D tex_albedoMap:    register(t2);
Texture2D tex_metallicMap:  register(t3);
Texture2D tex_roughnessMap: register(t4);
Texture2D tex_aoMap:        register(t5);

float3 calculateNormals(PS_Input input) {

    float3 normal = normalize(input.normal);
    float3 tangent = normalize(input.tangent);
    tangent = normalize(input.tangent - dot(input.tangent, input.normal) * input.normal);
    float3 bitangent = normalize(cross(normal, tangent));

    const float3x3 TBN = float3x3(tangent, bitangent, normal);

    float3 normalSample = tex_normalMap.Sample(textureSampler, input.texcoord).rgb;
    normalSample.x = 2.0f * normalSample.r - 1.0f;
    normalSample.y = -2.0f * normalSample.g + 1.0f;
    normalSample.z = normalSample.b;
    normal = mul(normalSample, TBN);

    return normal;
}

float3 fresnelSchlick(float cosTheta, float3 F0) {
    if (cosTheta > 1.0f) {
        cosTheta = 1.0f;
    }
    float p = pow(1.0f - cosTheta, 5.0f);
    return F0 + (1.0f - F0) * p;
}

float DistributionGGX(float3 N, float3 H, float roughness) {
    float a = roughness * roughness;
    float a2 = a * a;
    float NdotH = max(dot(N, H), 0.0f);
    float NdotH2 = NdotH * NdotH;

    float num = a2;
    float denom = (NdotH2 * (a2 - 1.0f) + 1.0f);
    denom = PI * denom * denom;

    return num / denom;
}

float GeometrySchlickGGX(float NdotV, float roughness) {
    float r = (roughness + 1.0f);
    float k = (r * r) / 8.0f;

    float num = NdotV;
    float denom = NdotV * (1.0f - k) + k;

    return num / denom;
}

float GeometrySmith(float3 N, float3 V, float3 L, float roughness) {
    float NdotV = max(dot(N, V), 0.0f);
    float NdotL = max(dot(N, L), 0.0f);
    float ggx2 = GeometrySchlickGGX(NdotV, roughness);
    float ggx1 = GeometrySchlickGGX(NdotL, roughness);

    return ggx1 * ggx2;
}

float3 getPBRLighting(PS_Input input) {
    float3 color = float3(0.0f, 0.0f, 0.0f);
    float3 albedoSample = pow(tex_albedoMap.Sample(textureSampler, input.texcoord).rgb, 2.2333f);
    float metallicSample = tex_metallicMap.Sample(textureSampler, input.texcoord).r;
    float roughnessSample = tex_roughnessMap.Sample(textureSampler, input.texcoord).r;
    float aoSample = tex_aoMap.Sample(textureSampler, input.texcoord).r;

    float3 N = normalize(input.normal);
    float3 V = normalize(cameraPosition - input.pixelPosition);

    float3 F0 = float3(0.04f, 0.04f, 0.04f);
    F0 = lerp(F0, albedoSample, metallicSample);

    float3 lightPositions[6] = {
        float3(-12.0f, 0.0f, -3.0f),
        float3( -6.0f, 0.0f, -3.0f),
        float3(  0.0f, 0.0f, -3.0f),
        float3(  6.0f, 0.0f, -3.0f),
        float3( 12.0f, 0.0f, -3.0f),
        float3( 18.0f, 0.0f, -3.0f),
    };
    float3 lightColor = float3(1.0f, 1.0f, 1.0f);

    // reflectance equation
    float3 Lo = float3(0.0f, 0.0f, 0.0f);
    for (int i = 0; i < 6; i++) {
        // calculate per-light radiance
        float3 L = normalize(lightPositions[i] - input.pixelPosition);
        float3 H = normalize(V + L);
        float distance = length(lightPositions[i] - input.pixelPosition);
        float attenuation = 1.0f / (distance * distance);
        float3 radiance = lightColor * attenuation;

        // cook-torrance brdf
        float NDF = DistributionGGX(N, H, roughnessSample);
        float G = GeometrySmith(N, V, L, roughnessSample);
        float3 F = fresnelSchlick(max(dot(H, V), 0.0f), F0);

        float3 kS = F;
        float3 kD = float3(1.0f, 1.0f, 1.0f) - kS;
        kD *= 1.0f - metallicSample;

        float3 numerator = NDF * G * F;
        float denominator = 4.0f * max(dot(N, V), 0.0f) * max(dot(N, L), 0.0f) + 0.0001f;
        float3 specular = numerator / denominator;

        // add to outgoing radiance Lo
        float NdotL = max(dot(N, L), 0.0f);
        Lo += (kD * albedoSample / PI + specular) * radiance * NdotL;
    }

    float3 ambient = float3(0.01f, 0.01f, 0.01f) * albedoSample * aoSample;
    color = ambient + Lo;
    return color;
}

float4 main(PS_Input input) : SV_TARGET {
    input.normal = calculateNormals(input);

    float3 color = getPBRLighting(input);

    // HDR tone mapping and gamma correction
    float exposure = 10.0f;
    float gamma = 1.0f;
    float3 toneMap = float3(1.0f, 1.0f, 1.0f) - exp((-color) * exposure);
    float3 toneMappedColor = pow(toneMap, float3(gamma, gamma, gamma));

    return float4(toneMappedColor, 1.0f);
}

渲染现象

  • 绑定m_cbPostProcess时,渲染结果正常,PBR光照表现符合预期;
  • 注释掉m_cbPostProcess时,渲染结果异常,光照计算出现明显错误。

所有代码均可正常编译,但始终无法定位常量缓冲区工作异常的根本原因,恳请提供帮助或建议。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:44:52