简体   繁体   English

点光源错误Directx 11

[英]Point Lighting Error Directx 11

I'm new to Directx 11, and I programmed a distance dependent point light shader that works pretty well for rotated and translated objects, but after I tried scaling my models, the lighting got dimmer if I scaled the model larger, and the lighting got brighter if I scaled the model smaller. 我是Directx 11的新手,我编写了一个距离相关的点光着色器,它对于旋转和翻译的对象非常有效,但是在我尝试缩放模型之后,如果我将模型缩放得更大,那么照明就变得更暗了如果我将模型缩小,则更亮。 I thought it might be the normals, but I made sure to multiply them by the inverse transpose of the world matrix, and I made sure to normalize them in the pixel shader after they are interpolated. 我认为它可能是法线,但我确保将它们乘以世界矩阵的逆转置,并确保在插值后在像素着色器中对它们进行归一化。 Here is the shader code: 这是着色器代码:

Texture2D txDiffuse : register( t0 );
SamplerState samAnisotropic
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 4;
};

cbuffer ConstantBuffer : register( b0 )
{
    matrix World;
    matrix View;
    matrix Projection;
    matrix WorldInvTrans;
    float3 LightPos;
    float pad1;
    float3 EyePos;
    float pad2;
    float3 At;
    float pad3;
    float showNorms;
}


struct VS_INPUT
{
    float4 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 TexCoor : TEXCOORD0; 
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float3 Norm : NORMAL;
    float3 LightDir : POSITION0;
    float3 EyeVector : POSITION1;
    float2 TexCoor : TEXCOORD0;
    float distance : FLOAT0;
    float showNorms : FLOAT1;

};

PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos = mul( input.Pos, World );
    output.LightDir = normalize( LightPos - output.Pos );
    output.EyeVector = normalize( EyePos - At );
    output.distance = distance( LightPos, output.Pos);
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );
    output.Norm = mul( input.Norm, WorldInvTrans );
    output.TexCoor = input.TexCoor;
    output.showNorms = showNorms;

    return output;
}

float4 PS( PS_INPUT input) : SV_Target
{
    input.Norm = normalize( input.Norm );

    float specTerm = 0;

    float3 ReflVector = normalize( reflect( input.LightDir, input.Norm ) );

    [flatten]
    if ( dot( ReflVector, input.EyeVector ) >= 0 )
    {
        specTerm = pow(  dot( ReflVector, input.EyeVector ) , 50 );
    }
    float diffuseTerm = saturate( dot( input.LightDir, input.Norm ) );
    float4 ambient = float4( 0.25f, 0.25f, 0.25f, 1.0f );
    float4 lightColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
    return ( (ambient + (diffuseTerm + specTerm) / (pow( input.distance, 1 ) * 0.025f)) * lightColor * txDiffuse.Sample( samAnisotropic, input.TexCoor ) ) * ( 1 - input.showNorms ) + float4( input.Norm, 1.0f ) * input.showNorms;
}

I was still suspicious that the normals weren't correct, so I edited the last line in my pixel shader to shade the model based on the normal vectors if showNorms = 1.0f. 我仍然怀疑法线是不正确的,所以我编辑了像素着色器中的最后一行,如果showNorms = 1.0f,则根据法线向量对模型进行着色。 The normals looked like they were transformed correctly. 法线似乎正确转换。 Still suspicious, I replaced my model with a plane on the XZ axis, and scaled it up 50 times. 仍然可疑,我用XZ轴上的平面替换了我的模型,并将其缩放了50次。 When I rendered it, the lighting was still dim, but the plane was green when I set showNorms to 1.0f, which must mean that the normals are all pointing in the upwards Y direction. 当我渲染它时,光线仍然暗淡,但是当我将showNorms设置为1.0f时,飞机是绿色的,这必然意味着法线都指向向上的Y方向。 If I'm transforming my normals correctly and normalizing them, what could be causing these lighting errors? 如果我正确地改变我的法线并将它们标准化,那么可能导致这些灯光错误的原因是什么?

If this helps, here is my code when I set the constant buffers for the plane: 如果这有帮助,那么当我为平面设置常量缓冲区时,这是我的代码:

//Render Plane
    mWorld = XMMatrixIdentity();
    cb1.mWorld = XMMatrixTranspose( XMMatrixMultiply( XMMatrixMultiply( mWorld, XMMatrixScaling( 50.0f, 1.0f, 50.0f ) ), XMMatrixTranslation( 0.0f, -5.0f, 0.0f ) ) );
    XMMATRIX A = cb1.mWorld;
    A.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);

det = XMMatrixDeterminant(A);
cb1.mWorldInvTrans = XMMatrixInverse(&det, A);

g_pImmediateContext->UpdateSubresource( g_pcBufferShader1, 0, NULL, &cb1, 0, 0 );

Edit: I changed the code a little bit to fix the specTerm: 编辑:我更改了代码以修复specTerm:

Texture2D txDiffuse : register( t0 );
SamplerState samAnisotropic
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 4;
};

cbuffer ConstantBuffer : register( b0 )
{
    matrix World;
    matrix View;
    matrix Projection;
    matrix WorldInvTrans;
    float3 LightPos;
    float pad1;
    float3 EyePos;
    float pad2;
    float3 At;
    float pad3;
    float showNorms;
}


struct VS_INPUT
{
    float4 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 TexCoor : TEXCOORD0; 
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float3 Norm : NORMAL;
    float3 LightDir : POSITION0;
    float3 EyeVector : POSITION1;
    float2 TexCoor : TEXCOORD0;
    float distance : FLOAT0;
    float showNorms : FLOAT1;

};

PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos = mul( input.Pos, World );
    output.LightDir = LightPos - output.Pos;
    output.EyeVector = EyePos - At;
    output.distance = distance( LightPos, output.Pos );
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );
    output.Norm = mul( input.Norm, WorldInvTrans );
    output.TexCoor = input.TexCoor;
    output.showNorms = showNorms;

    return output;
}

float4 PS( PS_INPUT input) : SV_Target
{
    input.Norm = normalize( input.Norm );
    input.LightDir = normalize( input.LightDir );
    input.EyeVector = normalize( input.EyeVector );

    float specTerm = 0;

    float3 ReflVector = normalize( reflect( -input.LightDir, input.Norm ) );

    [flatten]
    if ( dot( ReflVector, input.EyeVector ) >= 0 )
    {
        specTerm = pow(  dot( ReflVector, input.EyeVector ) , 50 );
    }
    float diffuseTerm = saturate( dot( input.LightDir, input.Norm ) );
    float4 ambient = float4( 0.25f, 0.25f, 0.25f, 1.0f );
    float4 lightColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
    return ( (ambient + (diffuseTerm + specTerm) / (pow( input.distance, 1 ) * 0.025f)) * lightColor * txDiffuse.Sample( samAnisotropic, input.TexCoor ) ) * ( 1 - input.showNorms ) + float4( input.Norm, 1.0f ) * input.showNorms;
}

I think you should try to normalize the LightDir vector in the pixel shader as well. 我认为你应该尝试在像素着色器中规范化LightDir矢量。 If the plane is really large it may happen, that after the interpolation of these two vectors, the vector you get in the pixel shader is not normalized. 如果平面非常大,可能会发生这种情况,即在插入这两个矢量之后,您在像素着色器中得到的矢量不会被标准化。 This error is likely to increase as the scale goes up. 随着规模的增加,这个错误可能会增加。 Give it a try. 试试看。 The picture below shows this problem. 下图显示了这个问题。

光矢量插值问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM