将定向光从 OpenGL 移植到 DirectX11

Porting Directional Light from OpenGL to DirectX11

我正在将我的 GLSL 定向光着色器从 OpenGL 移植到 DirectX11。

我的 LightDirection 是 (1,0,0)(图中从左到右)

GLSL 中的着色器如下所示:

#version 330 core

uniform sampler2D DiffuseMap;
uniform sampler2D NormalMap;
uniform sampler2D PositionMap;
uniform sampler2D DepthMap;

uniform vec3 LightDirection;
uniform vec3 LightColor;
uniform vec2 Resolution;

vec2 CalcTexCoord()
{
   return gl_FragCoord.xy / Resolution;
}


void main()
{
    vec4 norm = texture2D( NormalMap, CalcTexCoord());

    float Factor = dot(norm.xyz,-LightDirection);

    vec4 lights = vec4(LightColor*Factor,1);

    gl_FragColor = lights;
}

结果如下:

从左侧发出的光将砖块染成蓝色。

我将代码移植到 HLSL:

cbuffer MatrixBuffer
{
    matrix Scale;
    matrix Rotation;
    matrix Translation;
    matrix View;
    matrix Projection;

    float3 LightDirection;
    float3 LightColor;
    float2 Resolution;
};
tbuffer textureBuffer
{
    Texture2D DiffuseMap;
    Texture2D NormalMap;
    Texture2D PositionMap;
    Texture2D DepthMap;
};

SamplerState TextureSampler;


struct VertexShaderInput
{
    float3 Position : POSITION0;
    float2 UV       : TEXCOORD0;
    float3 Color    : COLOR0;
    float3 Normal   : NORMAL;
};

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
    float2 UV       : TEXCOORD0;
    float3 Color    : COLOR0;
    float3 Normal   : NORMAL;
};

struct PixelShaderOutput
{
    float4 color: SV_TARGET0;
};

float2 CalcTexCoord(float4 Position)
{
    return Position.xy / Resolution;
}

VertexShaderOutput VS_MAIN(VertexShaderInput input)
{
    VertexShaderOutput Output = (VertexShaderOutput)0;

    float4 pos = float4(input.Position.xyz, 1);


    float4x4 Model = mul(mul(Scale, Rotation), Translation);
    float4x4 MVP = mul(mul(Model, View), Projection);

    Output.Position = mul(pos, MVP);

    Output.UV = input.UV;

    Output.Color = input.Color;

    Output.Normal = input.Normal;

    return Output;
}

PixelShaderOutput PS_MAIN(VertexShaderOutput input)
{
    PixelShaderOutput output;

    float4 norm = NormalMap.Sample(TextureSampler, input.UV);

    float Factor = dot(norm.xyz,-LightDirection);

    float4 lights = float4(LightColor*Factor, 1);

    output.color = lights;

    return output;
}


technique10 Main
{
    pass p0
    {
        SetVertexShader(CompileShader(vs_5_0, VS_MAIN()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_5_0, PS_MAIN()));
    }
};

结果如下:

我得出结论,错误是因为我不能否定我的法线。

如果我绘制法线贴图,它们看起来完全一样

但是绘制法线否定的结果是:

现在我该如何解决这个问题,才能正确绘制我的积木?

所以我现在解决了这个问题。

问题是当在 HLSL 中采样纹理时,范围只能从 0 到 1。但是纹理保存在 -1 到 1 的范围内。OpenGL 以某种方式处理这个,但 DirectX 不t.

要修复它,只需将其转换为 0 到 1 的范围,并在需要时将其转换回来。

从-1和1到0-1:

output.normalMap = (float4(input.Normal,1) +1)/2;

从 0-1 到 -1 和 1:

float4 norm = (NormalMap.Sample(SampleType, UV) *2 )-1;