Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I recently started using custom shader. Shader can do diffuse and specular lighting and normal mapping. But normal mapping is causing really ugly artifacts (some sort of pixeling noise) for textures in greater distance.

It looks like this: enter image description here Image link

This is HLSL code:

// Matrix
float4x4 World : World;
float4x4 View : View;
float4x4 Projection : Projection;

//Textury
texture2D ColorMap;
sampler2D ColorMapSampler = sampler_state
{
    Texture = <ColorMap>;
    MinFilter = Anisotropic;
    MagFilter = Linear;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

texture2D NormalMap;
sampler2D NormalMapSampler = sampler_state
{
    Texture = <NormalMap>;
    MinFilter = Anisotropic;
    MagFilter = Linear;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

// Light
float4 AmbientColor : Color;
float AmbientIntensity;

float3 DiffuseDirection : LightPosition;
float4 DiffuseColor : Color;
float DiffuseIntensity;

float4 SpecularColor : Color;
float3 CameraPosition : CameraPosition;
float Shininess;

// The input for the VertexShader
struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 Normal : NORMAL0;
    float3 Binormal : BINORMAL0;
    float3 Tangent : TANGENT0;
};

// The output from the vertex shader, used for later processing
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 View : TEXCOORD1;
    float3x3 WorldToTangentSpace : TEXCOORD2;
};

// The VertexShader.
VertexShaderOutput VertexShaderFunction(VertexShaderInput input, float3 Normal : NORMAL)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.TexCoord = input.TexCoord;

    output.WorldToTangentSpace[0] = mul(normalize(input.Tangent), World);
    output.WorldToTangentSpace[1] = mul(normalize(input.Binormal), World);
    output.WorldToTangentSpace[2] = mul(normalize(input.Normal), World);

    output.View = normalize(float4(CameraPosition,1.0) - worldPosition);
    return output;
}
// The Pixel Shader
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 color = tex2D(ColorMapSampler, input.TexCoord);

    float3 normalMap = 2.0 *(tex2D(NormalMapSampler, input.TexCoord)) - 1.0;
    normalMap = normalize(mul(normalMap, input.WorldToTangentSpace));
    float4 normal = float4(normalMap,1.0);

    float4 diffuse = saturate(dot(-DiffuseDirection,normal));
    float4 reflect = normalize(2*diffuse*normal-float4(DiffuseDirection,1.0));
    float4 specular = pow(saturate(dot(reflect,input.View)), Shininess);

    return  color * AmbientColor * AmbientIntensity + 
            color * DiffuseIntensity * DiffuseColor * diffuse + 
            color * SpecularColor * specular;
}


// Techniques
technique Lighting
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

Any advice? Thanks!

share|improve this question
    
Just for fun, what happens when the specular term is removed? –  teodron Aug 15 '12 at 16:36

2 Answers 2

I suspect that those artifacts may be specular highlights because when I tried your shader in place of my normal map' shader, the specualar shading was imitating a light shining at a 90 degree angle about the model to where the diffuse shader's light was shining from. So yeah, hopefully it's just spec highlights, so try this:

float4x4 World : World;
float4x4 View : View;
float4x4 Projection : Projection;

//Textury
texture2D ColorMap;
sampler2D ColorMapSampler = sampler_state
{
    Texture = <ColorMap>;
    MinFilter = Anisotropic;
    MagFilter = Linear;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

texture2D NormalMap;
sampler2D NormalMapSampler = sampler_state
{
    Texture = <NormalMap>;
    MinFilter = Anisotropic;
    MagFilter = Linear;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

// Light
float4 AmbientColor : Color;
float AmbientIntensity;

float3 DiffuseDirection : LightPosition;
float4 DiffuseColor : Color;
float DiffuseIntensity;

float4 SpecularColor : Color;
float3 CameraPosition : CameraPosition;
float Shininess;

// The input for the VertexShader
struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 Normal : NORMAL0;
    float3 Binormal : BINORMAL0;
    float3 Tangent : TANGENT0;
};

// The output from the vertex shader, used for later processing
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 View : TEXCOORD1;
    float3x3 WorldToTangentSpace : TEXCOORD2;
};

// The VertexShader.
VertexShaderOutput VertexShaderFunction(VertexShaderInput input, float3 Normal : NORMAL)
{
    VertexShaderOutput output;

    float4x4 WVP = mul(World, mul(View, Projection)); //A Preshader

    output.Position = mul(input.Position, WVP);

    output.TexCoord = input.TexCoord;

    output.WorldToTangentSpace[0] = mul(normalize(input.Tangent), World);
    output.WorldToTangentSpace[1] = mul(normalize(input.Binormal), World);
    output.WorldToTangentSpace[2] = mul(normalize(input.Normal), World);

    output.View = normalize(float4(CameraPosition,1.0) - mul(input.Position, World));
    return output;
}
// The Pixel Shader
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 color = tex2D(ColorMapSampler, input.TexCoord);

    float3 normalMap = 2.0 *(tex2D(NormalMapSampler, input.TexCoord)) - 1.0;
    normalMap = normalize(mul(normalMap, input.WorldToTangentSpace));
    float3 normal = normalize(normalMap);

    float diffuse = saturate(dot(normalize(-DiffuseDirection),normal));
    float3 reflection = reflect(DiffuseDirection,normal);
    float specular = pow(saturate(dot(reflection,input.View)), Shininess);

    return  color * AmbientColor * AmbientIntensity + 
            color * DiffuseIntensity * DiffuseColor * diffuse + 
            color * SpecularColor * specular;
}


// Techniques
technique Lighting
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

Everything up until the Vertex Shader is the same. The VS does exactly the same thing, but I added a pre-shader just because I can. The Pixel Shader is where it's at. I cleaned it up a little, but the big changes are:

float4 reflect = normalize(2*diffuse*normal-float4(DiffuseDirection,1.0));

is now

float3 reflection = reflect(DiffuseDirection,normal);

Apart from the float4 to float3, I replaced the variable name 'reflect' with 'reflection' so I could use the HLSL function: reflect. This cool function means you don't have to write out the equation, just pass the 'incident ray' and the normal and it'll do the rest. It also makes sure that it's done correctly, unlike here. You used diffuse instead of dot(-DiffuseDirection, normal) and in diffuse, you normalized -DiffuseDirection.

It should go without saying that reflect has been changed to reflection in the line below as well.

This code worked for the model I used it on, so I'm hoping this is the fix you're after.

share|improve this answer

It looks like you have mipmapping disabled for at least the normal map texture.

Select your image file in the Content project. In the Properties, expand the Content Processor, and set "Generate Mipmaps" to "True".

I can't spot any issues with your shader at a glance, but I don't normally deal with graphics programming so I'm not sure what my opinion is worth on that subject.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.