0

I am porting my GLSL Directional Light Shader from OpenGL to DirectX11.

My LightDirection is (1,0,0) (from left to right in the pictures)

The Shader in GLSL looks like this:

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

This results in this: enter image description here

The bricks are colored blue from a light which comes from the left side.

I ported the code to 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()));
    }
};

Which results in this: enter image description here

I came to the conclusion, that the error is because I can't negate my normals.

If I draw my normal maps, they look both exactly the same enter image description here

But drawing the normals negated results in this: enter image description here

Now how do I fix the problem, so that my bricks are drawn correctly?

PuRe
  • 179
  • 2
  • 13
  • 1
    Check your input layout to ensure you are actually getting the normal data into the shader. – Chuck Walbourn Apr 30 '15 at 18:20
  • They are drawn onto a texture, which is displayed in the picture before the last one. – PuRe Apr 30 '15 at 19:06
  • What format are you using for your NormalMap? Is it the same between OGL and DX? – GuyRT May 01 '15 at 06:16
  • Likely an input mapping problem. Use GPU capture tool (Diagnostics, Nsight, etc) to verify that the normal data is actually coming in. If that isn't the problem, you can use the GPU tool to debug a pixel, and figure out what data is missing/incorrect. – MuertoExcobito May 01 '15 at 11:32
  • Your normal map lookup is completely different for each implementation ... DirectX is looking up the UV based on the passed in UV coordinates where OpenGL is using the window relative coordinates to look up the normal information ... – Goz May 01 '15 at 15:56
  • Normal datas are coming in. The Problem seems to be float4 norm = NormalMap.Sample(TextureSampler, input.UV). because negative values aren't sampled, which works in OpenGL but not in DirectX. – PuRe May 04 '15 at 13:11

1 Answers1

0

So I fixed this now.

The problem is that when sampling a Texture in HLSL, the range can only go from 0 to 1. But the texture is saved in a range from -1 to 1. Somehow OpenGL works with this, but DirectX doesn't.

To fix it, simple transform it to a range from 0 to 1 and when needed transform it back.

From -1 and 1 to 0-1:

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

From 0-1 to -1 and 1:

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