将定向光从OpenGL移植到DirectX11

时间:2015-04-30 13:50:07

标签: opengl directx glsl hlsl

我正在将我的GLSL Directional Light Shader从OpenGL移植到DirectX11。

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

GLSL中的Shader看起来像这样:

#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;
}

这导致: enter image description here

砖块的颜色为蓝色,来自左侧的光线。

我将代码移植到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()));
    }
};

结果如下: enter image description here

我得出结论,错误是因为我无法否定我的常规。

如果我绘制我的法线贴图,它们看起来完全相同 enter image description here

但是否定法线否定了这一结果: enter image description here

现在我该如何解决问题,以便正确绘制砖块?

1 个答案:

答案 0 :(得分:0)

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

问题在于,当在HLSL中对Texture进行采样时,范围只能从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;