I'm having some trouble reading the values from my Normal map in my lighting fragment shader.

The relevant part of the shader code is as follows:

Texture2D NormalGB : register(t0);
Texture2D DiffuseGB : register(t1);
Texture2D SpecularGB : register(t2);
Texture2D PositionGB : register(t3);

SamplerState NormalSampler : register(s0);

void GetGBValues(
    in int2 screenPosition,
    out float3 normal,
    out float3 diffuseAlbedo,
    out float3 specularAlbedo,
    out float specularPower,
    out float3 position)

    int3 screenPos3 = int3(screenPosition, 0);
    normal = normalize(NormalGB.Sample(NormalSampler, screenPosition).xyz); // HERE
    diffuseAlbedo = DiffuseGB.Load(screenPos3).xyz;
    float4 specularValues = SpecularGB.Load(screenPos3);
    specularAlbedo = specularValues.xyz;
    specularPower = specularValues.w * 50.0f;
    position = PositionGB.Load(screenPos3).xyz;

However, in 9 frames out of 10, normal is set to {0. 0, 0}. I've tried the code under the reference driver too, and get the same issue.

What's really weird is that if I change the line marked // HERE to a simple .Load call, the code works perfectly (except the obvious fact that I get no interpolation of normals). The sampler that is bound at time of the draw call (according to the graphics debugger) is:

D3D11 Sampler State (obj:18)
BorderColor (0.000f, 0.000f, 0.000f, 0.000f) 
ComparisonFunc D3D11_COMPARISON_NEVER 
MaxAnisotropy 4 
MaxLOD 340282346638528860000000000000000000000.000f 
MinLOD 0.000f 
MipLODBias 0.000f 

Device obj:3 

And finally, the normal-map (rendered to a texture by the previous pass):

enter image description here


1 Answer 1


screenPosition is not at the right scale for texture coordinate lookup. Texture2D::Sample expects texture coordinates (0..1) while Texture2D::Load expects texel coordinates (0..[Width or Height]-1). So you're probably sampling way off the edge of the texture and either hitting the border color, or clamping to the edge which happens to be black.

As a temporary solution, you can simply scale screenPosition by some fixed amount, e.g. NormalGB.Sample(NormalSampler, screenPosition * 0.01f).

The right solution though is to add an additional float2 texture coordinate input, usually associated with the TEXCOORD semantic name. This should be set in your vertex data to have values between 0 and 1, which are then interpolated in the pixel shader.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .