Освещение C++ DirectX в проблеме с пиксельным шейдером

У меня есть проблема, которую я не могу понять. Я только что добавил точечный источник света в свой проект, и текстуры стали полностью черными. Понятия не имею почему.

Я думаю, что это может быть либо норма, которая не обновляется правильно, либо это может быть расчет s.x, s.y и s.z.

Я был бы очень рад, если бы у кого-то было время взглянуть на это и помочь мне. Спасибо.

Так. Вот мой пиксельный шейдер:

Texture2D txDiffuse : register(t0);
SamplerState sampState;
cbuffer PointLight : register(b0)
{
    float3 Pos;
    float diff;
    float amb;
    float spec;
    float range;
    float intensity;
};
struct VS_IN
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD;
    float4 Norm : NORMAL;
    float4 Pos2 : POSITION;
};
float4 PS_main(VS_IN input) : SV_Target
{
    float3 s = txDiffuse.Sample(sampState, input.Tex).xyz;

    float3 lightPos = Pos;

    float3 lightVector = lightPos - input.Pos2;
    lightVector = normalize(lightVector);
    float nDotL = dot(lightVector, input.Norm);

    float diff1 = 0.8;
    float amb1 = 0.1;

    s.x = (s.x * diff * nDotL + s.x * amb);
    s.y = (s.y * diff * nDotL + s.y * amb);
    s.z = (s.z * diff * nDotL + s.z * amb);



    return float4(s, 0.0);

};

Геометрический шейдер:

cbuffer worldMatrix : register(b0)
{
    matrix world;
}
cbuffer viewMatrix : register(b1)
{
    matrix view;
}
cbuffer projectionMatrix : register(b2)
{
    matrix projection;
}
struct VS_IN
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD;
};
struct VS_OUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD;
    float4 Norm : NORMAL;
    float4 Pos2 : POSITION;
};

[maxvertexcount(6)]
void main(triangle VS_IN input[3] : SV_POSITION, inout TriangleStream< VS_OUT > output2)
{

    matrix wvp = mul(projection, mul(world, view));
    matrix worldView = mul(world, view);


    float4 normal = float4(cross(input[1].Pos - input[0].Pos, input[2].Pos - input[0].Pos), 0.0f);
    normal = normalize(normal);

    float4 rotNorm = mul(worldView, normal);
    rotNorm = normalize(rotNorm);

    VS_OUT output[3];
    for (uint i = 0; i < 3; i++)
    {
        output[i].Pos = input[i].Pos;
        output[i].Pos = mul(wvp, input[i].Pos);
        output[i].Tex = input[i].Tex;
        output[i].Norm = rotNorm;
        output[i].Pos2 = mul(worldView, output[i].Pos);
        output2.Append(output[i]);
    }
    output2.RestartStrip();

    VS_OUT outputcopy[3];
    for (uint i = 0; i < 3; i++)
    {
        outputcopy[i].Pos = input[i].Pos + (normal);
        outputcopy[i].Pos = mul(wvp, outputcopy[i].Pos);
        outputcopy[i].Tex = input[i].Tex;
        outputcopy[i].Norm = rotNorm;
        outputcopy[i].Pos2 = mul(worldView, outputcopy[i].Pos);
        output2.Append(outputcopy[i]);
    }

    output2.RestartStrip();
}

Код для инициализации точечного источника света:

struct PointLight
{
    Vector3 Pos;
    float diff;
    float   amb;
    float   spec;
    float   range;
    float   intensity;

};
PointLight* pointLight = nullptr;
PointLight PL =
    {
    Vector3(0.0f, 0.0f, -3.0f),
    0.8f,
    0.2f,
    0.0f,
    100.0f,
    1.0f
    };

    pointLight = &PL;

    D3D11_BUFFER_DESC lightBufferDesc;
    memset(&lightBufferDesc, 0, sizeof(lightBufferDesc));
    lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    lightBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    lightBufferDesc.StructureByteStride = 0;
    lightBufferDesc.MiscFlags = 0;
    lightBufferDesc.ByteWidth = sizeof(PointLight);

    D3D11_SUBRESOURCE_DATA pointLightData;
    memset(&pointLightData, 0, sizeof(pointLightData));
    pointLightData.pSysMem = &PL;

    gDevice->CreateBuffer(&lightBufferDesc, &pointLightData, &lightBuffer);

и в render() я запускаю

gDeviceContext->PSSetConstantBuffers(0, 1, &lightBuffer);

person Rickard    schedule 29.02.2016    source источник
comment
Могут ли быть проблемы с выравниванием/дополнением в вашем точечном буфере? Я не уверен, что правила в С++ и в языке шейдеров одинаковы.   -  person jcoder    schedule 29.02.2016


Ответы (1)


Текстура будет черной, если s.x, s.y, s.z равны нулю.

s.x = (s.x * diff * nDotL + s.x * amb);
s.y = (s.y * diff * nDotL + s.y * amb);
s.z = (s.z * diff * nDotL + s.z * amb);

Попробуйте изменить diff и amb на ненулевую константу, чтобы вы могли быть уверены, правильно ли вы установили буфер констант. Если после того, как вы их измените, он по-прежнему будет черным, то это должно быть nDotL и/или сэмплированная текстура равна нулю. Затем попробуйте с ненулевой константой для образца текстуры. Если они по-прежнему заставляют текстуру выглядеть черной, то виновником является ваш расчет вектора света.

person Zamrony P. Juhara    schedule 01.03.2016