DX11 Shader只有当Constant Buffer设置为unused slot时才能正常执行

问题描述 投票:0回答:1

我有一个问题,如果我将寄存器

b1
的像素着色器常量缓冲区设置为下面的结构,我的着色器代码只能正确执行。我一直在寻找答案,我可能总共花了 8 个小时试图解决这个问题。似乎来自
time
的变量
ConstantBuffer
被放入
CameraBuffer
的任一变量中。我以为
__declspec(align(16))
解决了填充问题。我相信无论如何我也正确地填充了东西。我在我的代码中添加了注释。

// 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);
}

这是我的着色器代码。我正在尝试实施 PBR。

顶点着色器

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
的结果: https://gyazo.com/22bc8169fc5e3e772f4dafac2a78e4ed

结果注释掉: https://gyazo.com/07359dd66e1d4a9dce55677b046c657d

我知道我在这里包含了很多代码,但我认为多总比少好。任何帮助或建议表示赞赏。

c++ rendering directx-11
1个回答
0
投票

问题是我的像素着色器中的变量

PI
不是
static
const
。显然,如果着色器中的变量未声明
static
const
,那么它可能会被覆盖,这显然会导致无法解释的行为,就像我所经历的那样。如果有人能更好地解释这一点,我仍然觉得我没有 100% 理解。

© www.soinside.com 2019 - 2024. All rights reserved.