将平行光从OpenGL移植到DirectX11

将平行光从OpenGL移植到DirectX11,opengl,directx,glsl,hlsl,Opengl,Directx,Glsl,Hlsl,我正在将我的GLSL平行光着色器从OpenGL移植到DirectX11 我的光照方向是(1,0,0)(图中从左到右) GLSL中的着色器如下所示: #version 330 core uniform sampler2D DiffuseMap; uniform sampler2D NormalMap; uniform sampler2D PositionMap; uniform sampler2D DepthMap; uniform vec3 LightDirection; uniform v

我正在将我的GLSL平行光着色器从OpenGL移植到DirectX11

我的光照方向是(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不能

要修复它,只需将其转换为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;

检查输入布局,以确保将法线数据实际输入着色器。它们被绘制到纹理上,该纹理显示在最后一个纹理之前的图片中。法线贴图使用什么格式?OGL和DX之间是否相同?可能是输入映射问题。使用GPU捕获工具(Diagnostics、Nsight等)验证正常数据是否实际进入。如果这不是问题,您可以使用GPU工具调试像素,并找出丢失/不正确的数据。对于每个实现,您的常规地图查找完全不同。。。DirectX根据传入的UV坐标查找UV,OpenGL使用窗口相对坐标查找法线信息。。。