Page 1 of 1

[fixed]Normal- + Specular-Map Shader shows up flat

Posted: Fri Aug 07, 2009 12:22 pm
by Ronin
Hi,

We've implemented our own normal + specular shader and it shows up real strange:

Image

Interestingly, when the sun direction in tangent space is _not_ normalized within the pixel shader, the diffuse component shows up smoothly, the specular is still "flat". However, that can't be right.

The mesh is converted to tangents using:

Code: Select all

getMeshManipulator()->createMeshWithTangents(mesh->getMesh(0), false, false, false);
Changing any of the options of creatMesh... does not lead to a different result.

Here's the used shader code, for insight:
Vertex:

Code: Select all

float3 fvSunDir;
float3 fvEyePosition;
float4x4 matWorld;
float4x4 ModelViewProjectionMatrix;
float4x4 rotObjInv;

struct VS_INPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal :   NORMAL0;
   float4 tangent : TEXCOORD1;
   float4 binormal : TEXCOORD2;
};

struct VS_OUTPUT 
{
   float4 Position :        POSITION0;
   float2 Texcoord :        TEXCOORD0;
   float3 ViewDirection :   TEXCOORD1;
   float3 SunTangent :	TEXCOORD2;
};

VS_OUTPUT main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.Position         = mul(Input.Position, ModelViewProjectionMatrix);
   Output.Texcoord         = Input.Texcoord;
   
   float3x3 TBNMatrix = float3x3(
		normalize(Input.tangent.xyz), 
		normalize(Input.binormal.xyz), 
		normalize(Input.Normal));
   Output.SunDirection     = (mul((fvSunDir), rotObjInv));
   Output.SunTangent = (mul(TBNMatrix, Output.SunDirection));
 
   float4 fvObjectPosition = mul( Input.Position, matWorld );
   Output.ViewDirection    = mul(TBNMatrix, fvEyePosition -fvObjectPosition);
  
   return( Output );
}
Pixel:

Code: Select all

float4 fvAmbient;
float4 fvSpecular;
float4 fvDiffuse;
float4 f4SunColor;
float fSunIntensity;
float fSpecularPower;
float fShininess;
sampler2D tex0;   // diffuse
sampler2D tex1;   // spec
sampler2D tex2;   // normal

struct PS_INPUT 
{
    float2 Texcoord :        TEXCOORD0;
    float3 ViewDirection :   TEXCOORD1;
    float3 SunTangent :		 TEXCOORD2;   
};

float4 main( PS_INPUT Input ) : COLOR0
{
    float3 fvViewDirection  = normalize(Input.ViewDirection);	
    float3 fvSunTangent	= normalize(Input.SunTangent);
    
    // Textures
    float4 fvBaseColor      = tex2D(tex0, Input.Texcoord);
    float4 fvSpecularColor  = tex2D(tex1, Input.Texcoord);
    float3 fvNormalMapped = normalize((2.0f * tex2D(tex2, Input.Texcoord).rgb - 1.0f));
   
    // Sun Stuff
    float fNLSun = saturate(dot(fvNormalMapped, fvSunTangent ));
    float fRDotV2 = 0;
    if(fNLSun > 0.f)
    {
        float3 half = normalize((fvSunTangent + fvViewDirection) * 0.5f);
        fRDotV2 = saturate(dot(fvNormalMapped, half));
    }
    
	float my = saturate(fShininess * 0.001 + 0.4);
	float my2 = fSpecularPower * 0.001 + 150;
	float4 spec = fvSpecular + fvSpecularColor;

    float4 fvTotalAmbient   = fvAmbient; 
    float4 fvTotalDiffuse   = fvDiffuse * saturate(fNLSun * fSunIntensity);
    float4 fvTotalSpecular  = fShininess * spec * pow(fRDotV2 * fSunIntensity, fSpecularPower);

    return(saturate(fvBaseColor * (fvTotalAmbient + fvTotalDiffuse) + fvTotalSpecular));
}

Posted: Fri Aug 07, 2009 1:15 pm
by hybrid
What type of mesh is it? Does it show up smooth when loaded with getMesh and useing standard SOLID material? Try "false, true, true" or "true, true. true" as parameters for createMeshWithTangents.

Posted: Fri Aug 07, 2009 1:29 pm
by Ronin
The Mesh is a plain IMesh and it shows up correct, when rendering as EMT_SOLID. Changing the parameters of createMeshWithTangents does not help.

Posted: Fri Aug 07, 2009 4:37 pm
by hybrid
Well, I meant the mesh file format. Did you check with lighting on to see that the normals are really correct?

Posted: Fri Aug 07, 2009 7:39 pm
by Ronin
We performed some tests using X and OBJ file formats, where both lead to the same problems. The normals are definitely correct, as checked with EMT_SOLID and the lighting flag set to true.

Posted: Sat Aug 08, 2009 12:14 am
by zillion42
I know it doesn't add a flying **** but... I'm kind of curious about the outcome of this thread.

Posted: Sat Aug 08, 2009 9:42 am
by hybrid
Did you check the tangent mesh with EMT_SOLID? That way we can check whether it's a bug in the tangent calculations, or a problem with the shader.

Posted: Tue Aug 11, 2009 3:21 pm
by Ronin
Whith EMT_SOLID the mesh normals are correct, no matter if generated with tangents or not. The error seems to be in the shader code then...

Posted: Tue Aug 11, 2009 4:18 pm
by r2d2
If normal mapping shaders show up flat it's (that's my experience) most often either a tangent problem or a problem with this term: float4 fvTotalDiffuse = fvDiffuse * saturate(fNLSun * fSunIntensity);

Try using an irrlicht light and the irrlicht normal mapping material if it still shows up flat, it's a tangent problem if it doesn't show up flat we have to further investigate your shader, at a first glance i can't see a problem in your shadercode.

Posted: Tue Aug 11, 2009 10:25 pm
by Viz_Fuerte
I happened the same to me.

Guilt was to export the model to a different format from the editor.
I had to change the file format, where you could export the model smoothing.

Fortunately is resolved.

Proof to use, the manipulator mesh of Irrlicht (MeshManipulator), and recalculates the normals. Could work.

Posted: Thu Aug 27, 2009 1:42 pm
by MasterD
Sorry for responding that late, but I got distracted implementing terrain texture splatting :roll:

Unfortunately I was not able to solve this problem. EMT_SOLID / EMT_NORMAL_MAP_SOLID show up flat too (when created with tangents), and smooth with EMT_SOLID (without).

I've visualized the components of the mesh in my shader:

Image

Only when all flags are off, the resulting mesh has smooth normals. If any flag is on, the normals show up flat. The generated tangent/binormal is flat all the time.

Here is the used mesh for reference:
http://www.my rear-engine.de/downloads/delta.x
(Remove the preceding "m" of the domain. I don't want to have webcrawlers getting our mesh too easily)

@Viz_Fuerte: Which mehs format did you use, that helped you and what did you use before?

Posted: Thu Aug 27, 2009 4:17 pm
by bitplane
Since your mesh is in x format, does this patch help at all?

Posted: Thu Aug 27, 2009 7:17 pm
by MasterD
Very very nice!

Never thought to look for help in the "Remaking irrlicht's fairy" thread :D

The quality is greatly improved, however there are some glitches, which may be similar to those referenced in that thread:

Image

The normals, when visualized, are smooth.

Sadly, blender does not import X - files correctly and I cannot use that program as reference or to look for double vertices. However I opened the mesh with the DirectX Viewer (DX SDK) and the shown tangents are quire similar:

Image

I haven't looked at the code in depth and just wanted to ask:
When the artist defines a given polygon(-area) as flat shaded, what does the code do? Will everything be smoothened or will the smoothing groups be preserved? (I think that's the 3Dsmacks term for that, blender does this using an "edge split" modifier)

Posted: Thu Aug 27, 2009 9:47 pm
by hybrid
If you tell the manipulator to keep the normals, they are to be untouched. If you tell it to recalculate the normals, all normals will be smoothed if enabled. At least that's the theory.