Skip to main content
gamedev.net
🔒 Locked

HLSL Normal Mapping

Started by feal87 Apr 10, 2009 at 10:50 AM 5 replies 3.2k views
Original Post
feal87
feal87
I'm trying from a while to get a simple Normal Mapping shader to work without any success...somebody have some ideas? Here it is the shader (it works with instancing for drawing lots of meshes) :

matrix View;
matrix Projection;
Texture2D g_texture;
Texture2D g_bumpmap;

float AmbientIntensity = 1;
float4 AmbientColor : AMBIENT = float4(0,0,0,1);
float3 LightDirection : Direction = float3(0,1,1);

struct VS_INPUT
{
    float3 Pos : POSITION;
    float3 Norm : NORMAL;
    float2 Tex : TEXCOORD0;
    float3 Tangent : TANGENT;
    float3 Binormal : BINORMAL;
    float3 InstancePosition : COLOR0;
    float3 InstanceRotation : COLOR1;
    float3 InstanceScale : COLOR2;
    float4 color : COLOR3;
};

SamplerState samLinear
{
   MinFilter = Linear;
   MagFilter = Linear;
   MipFilter = Linear;   
    AddressU = Clamp;
    AddressV = Clamp;
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD0;
    float3 Light : TEXCOORD2;
};

matrix RotationXMatrix(float inp)
{
	float coseno = cos(inp);
	float seno = sin(inp);
	matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
					  0.0f, coseno, seno, 0.0f,
					  0.0f, -seno, coseno, 0.0f,
					  0.0f, 0.0f, 0.0f, 1.0f };
	return result;
}

matrix RotationZMatrix(float inp)
{
	float coseno = cos(inp);
	float seno = sin(inp);
	matrix result = { coseno, seno, 0.0f, 0.0f,
					  -seno, coseno, 0.0f, 0.0f,
					  0.0f, 0.0f, 1.0f, 0.0f,
					  0.0f, 0.0f, 0.0f, 1.0f };
	return result;
}

matrix RotationYMatrix(float inp)
{
	float coseno = cos(inp);
	float seno = sin(inp);
	matrix result = { coseno, 0.0f, -seno, 0.0f,
					  0.0f, 1.0f, 0.0f, 0.0f,
					  seno, 0.0f, coseno, 0.0f,
					  0.0f, 0.0f, 0.0f, 1.0f };
	return result;
}

matrix ScaleMatrix(float3 inp)
{
	matrix result = { inp.x, 0.0f, 0.0f, 0.0f,
					  0.0f, inp.y, 0.0f, 0.0f,
					  0.0f, 0.0f, inp.z, 0.0f,
					  0.0f, 0.0f, 0.0f, 1.0f };
	return result;
}

matrix TranslationMatrix(float3 inp)
{
	matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
					  0.0f, 1.0f, 0.0f, 0.0f,
					  0.0f, 0.0f, 1.0f, 0.0f,
					  inp.x, inp.y, inp.z, 1.0f };
	return result;
}

VS_OUTPUT VS( VS_INPUT input )
{
    VS_OUTPUT output = (VS_OUTPUT)0;
	
	matrix scale = ScaleMatrix(input.InstanceScale);
	matrix transl = TranslationMatrix(input.InstancePosition);
	matrix rotationx = RotationXMatrix(input.InstanceRotation.x);
	matrix rotationy = RotationYMatrix(input.InstanceRotation.y);
	matrix rotationz = RotationZMatrix(input.InstanceRotation.z);

	matrix world = mul(mul(mul(mul( scale, transl ), rotationx), rotationy),rotationz);
	
    output.Pos = mul( float4(input.Pos,1), world);
    output.Pos = mul( output.Pos, View );
    output.Pos = mul( output.Pos, Projection );

    output.Tex = input.Tex;
	float3x3 worldToTangentSpace;
	worldToTangentSpace[0] = mul(input.Tangent,world);
	worldToTangentSpace[1] = mul(input.Binormal,world);
	worldToTangentSpace[2] = mul(input.Norm,world);
	
    output.Light = mul(worldToTangentSpace,LightDirection);	
	
    return output;
}

float4 PS( VS_OUTPUT input ) : SV_Target
{
	float3 Normal = (2 * (g_bumpmap.Sample(samLinear,input.Tex))) - 1.0;
	
	float3 LightDir = normalize(input.Light);
	float Diffuse = saturate(dot(LightDir,Normal));
		
	float4 texCol = g_texture.Sample(samLinear,input.Tex);
	
	float4 Ambient = AmbientIntensity * AmbientColor;
				
	texCol *= Diffuse;
	return Ambient + texCol;
}

technique Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_3_0, VS() ) );
        SetPixelShader( CompileShader( ps_3_0, PS() ) );
	ZEnable = true;
	ZWriteEnable = true;
	ZFunc = LessEqual;
        AlphaBlendEnable = false;
	CullMode = None;
    }
}


With this image as texture and map. And this is the result : If i change the row "texCol *= Diffuse;" to "texCol += Diffuse;" the mesh appear to be mapped, but without any colour. What i'm doing wrong? Any clue? :( [Edited by - feal87 on April 10, 2009 12:07:20 PM]
feal87
feal87
It seems that if i use tex2d instead of the sample functionality it work...somebody know why? What's the difference between them?
Jason Z
Jason Z
Is this D3D10 or D3D9? After looking at the D3D documentation, it shows that the texture.Sample method is only supported for ps_4_0 and ps_4_1. Your technique is targetting ps_3_0, so try to recompile it with the newer shader model target.

I would recommend using PIX to check what the texture looks like, then you can step through the shader code to see if you are actually getting (0,0,0,0) from your texture sample. But it could be that you are just using features that aren't supported on this target...
Jason Zink :: DirectX MVP   Direct3D 11 engine on CodePlex: Hieroglyph 3 Direct3D Books: 
InvalidPointer
InvalidPointer
Erm, first off I believe you actually need to *assign* a texture to your sampler, which you don't do.

I.e. you should have something like
sampler normalMapSampler = sampler_state{   MinFilter = Linear;   MagFilter = Linear;   MipFilter = Linear;      AddressU = Clamp;   AddressV = Clamp;   texture = <g_bumpmap>;};sampler diffuseMapSampler = sampler_state{   MinFilter = Linear;   MagFilter = Linear;   MipFilter = Linear;      AddressU = Clamp;   AddressV = Clamp;   texture = <g_texture>;};


Then just use something like this:
float4 diffuseCol = tex2D(diffuseMapSampler, texCoords);float4 normal = tex2D(normalMapSampler, texCoords);// do your decode/tangent-space conversion here

in the actual shader.

Also, that has got to be one of the weirdest instancing implementations I've seen. Aren't there streams designed explicitly for this purpose? There's also no reason why you should be calculating this stuff in a shader. Offload it back onto the CPU and pass it in.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
feal87
feal87
The system works fine even without setting the texture. It just doesn't like the sample functionality, maybe its only DX10. I'll try it later with DX10 (my engine is cross-system :D)

Mhn...the matrix calculation is done on the GPU, because on my case the CPU is the bottleneck and i need to optimize to draw lots of objects. ;) (i just send one time the mesh and N time the instance data (position, rotation, scale) where N is the number of instances.)

Thanks anyway for the input. :)
Jason Z
Jason Z
Quote:
Original post by feal87
The system works fine even without setting the texture. It just doesn't like the sample functionality, maybe its only DX10. I'll try it later with DX10 (my engine is cross-system :D)

Mhn...the matrix calculation is done on the GPU, because on my case the CPU is the bottleneck and i need to optimize to draw lots of objects. ;) (i just send one time the mesh and N time the instance data (position, rotation, scale) where N is the number of instances.)

Thanks anyway for the input. :)

For certain that sampling syntax is DX10 - are you sure the effect is compiling correctly? Is there any D3D diag. output when you run the application?
Jason Zink :: DirectX MVP   Direct3D 11 engine on CodePlex: Hieroglyph 3 Direct3D Books: 

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.