Normalization cube map issues

Started by
3 comments, last by Jason Z 18 years, 7 months ago
I am having one heck of a time getting a normalization cube map to work. I have a working .fx (directx only, but similar to cgfx) that I am trying to speed up a bit. So I am trying to take out one of the normalize() functions and use a cube map lookup instead. The problem is, the normals come out extremely multi-colored (when viewed as rgb) and totally different than the actual world space normals before normalization (also when viewed as rgb). The cube map is generated by an nVidia routine that I can post if you would like. Here is the effect that I am using - it is a gooch shader with outlines added. The normalization is done in the PS_Colored function on the IN.normal vector. Does anyone see an obvious problem?
//-----------------------------------------------------------------------------
// Gooch.fx
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Parameters
//-----------------------------------------------------------------------------
float4x4 Transform : WorldViewProjection;
float4x4 ModelWorld : World;
float4 LightCol = float4(1,1,1,1);
float4 LightPos = float4(0,500,-500,0);
float4 CameraPosition : ViewPosition;
float4 Material = float4( 1.0f, 1.0f, 1.0f, 1.0f);

float4 cool : Scratch1 = float4( 0.2f, 0.2f, 0.8f, 1.0f );
float4 warm : Scratch0 = float4( 1.0f, 1.0f, 0.2f, 1.0f );

texture DiffuseTexture : ColorMap0; 
//-----------------------------------------------------------------------------
samplerCUBE Sampler = sampler_state
{
    Texture   = (DiffuseTexture);
    MipFilter = Linear;
    MinFilter = Linear;
    MagFilter = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
    AddressW = Wrap;
};

//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct vertex
{
    float3 position	: POSITION;
    float3 normal   : NORMAL;
};
//-----------------------------------------------------------------------------
struct fragment
{
    float4 position : POSITION;
	float3 normal   : TEXCOORD0;
	float3 eye      : TEXCOORD1;
    float3 light	: TEXCOORD2;
};
//-----------------------------------------------------------------------------
struct outline_fragment
{
    float4 position : POSITION;
};
//-----------------------------------------------------------------------------
struct pixel
{
	float4 color    : COLOR;
};
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Diffuse lighting function
//-----------------------------------------------------------------------------
float DiffuseCalculation(float3 L, float3 N)
{
    float Intensity = max(dot(N, L), 0);
	return Intensity;
};
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Specular lighting function
//-----------------------------------------------------------------------------
float SpecularCalculation( float3 H, float3 N, float fShininess )
{
	float Intensity = pow(max(dot(N,H), 0), fShininess);
	return Intensity;
};
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Vertex shaders
//-----------------------------------------------------------------------------
fragment VS_Colored( vertex IN )
{
    fragment OUT;

	float4 WorldPos = mul( float4(IN.position, 1), ModelWorld );
	float3 P = WorldPos.xyz; 
	float3 N = normalize(mul(IN.normal, (float3x3)ModelWorld));
	float3 L = normalize(LightPos.xyz - P);
	float3 E = CameraPosition.xyz;
	float3 V = normalize(E - P);

	OUT.position = mul( float4(IN.position, 1), Transform );
	OUT.normal = N;
	OUT.light = L;
	OUT.eye = V;
	
	return OUT;
}
//-----------------------------------------------------------------------------
outline_fragment VS_Outline( vertex IN )
{
    outline_fragment OUT;

	float4 ClipPos = mul( float4(IN.position, 1), Transform );
	float ratio = saturate((ClipPos.z / ClipPos.w) * 0.05f);

	float3 P = IN.position + ratio * normalize(IN.normal);
	
	OUT.position = mul( float4(P, 1), Transform );
	
	return OUT;
}
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Pixel Shader
//-----------------------------------------------------------------------------
pixel PS_Colored( fragment IN )
{
    pixel OUT;

	float3 N = texCUBE( Sampler, IN.normal ).xyz;
	
	float NdotL = saturate( DiffuseCalculation( IN.light, N ) );
	
	float4 color = NdotL * warm + (1 - NdotL) * cool;

	float3 H = normalize(IN.light + IN.eye);

	float NdotH = SpecularCalculation( H, N, 100 );
	float3 specular = float3( NdotH, NdotH, NdotH );

	OUT.color.rgb = max( color.rgb, specular );
	
	OUT.color.rgb = N;
	OUT.color.a = 1.0f;

    return OUT;
}
//-----------------------------------------------------------------------------
pixel PS_Outline( outline_fragment IN )
{
    pixel OUT;

	OUT.color.rgb = float3( 0.0, 0.0, 0.0 );
	OUT.color.a = 1.0f;

    return OUT;
}

//-----------------------------------------------------------------------------
// Techniques
//-----------------------------------------------------------------------------

technique LitTexturedSpecular
{
    pass P0
    {
		ZEnable = true;

		VertexShader = compile vs_1_1 VS_Colored();
		PixelShader  = compile ps_2_0 PS_Colored();
    }
  
    pass P1
    {
		ZEnable = true;

		CullMode = CW;
		VertexShader = compile vs_1_1 VS_Outline();
		PixelShader  = compile ps_2_0 PS_Outline();
    }

}
I was wondering what type of texture addressing you use for these types of lookups? I really can't figure it out - if anyone has a link or a demo of using these types of cube maps, I would really appreciate any help.
Advertisement
Hmmmm. After further review, I realized that I was not expanding the texCUBE result (x*2 - 1), and that the results are all the color from the positive x face of the cube map. Has anyone seen anything like this before? Even after range expanding my normals it is still not working correctly.

Thanks for any help you can provide.
Assuming you're using a generating a normalizer by calling D3DXFillCubeTexture, with a callback like this;

VOID WINAPI FillCubeNormalizer (D3DXVECTOR4* pOut, const D3DXVECTOR3* pTexCoord, const D3DXVECTOR3* pTexelSize, LPVOID pData){  D3DXVECTOR3 v (*pTexCoord);  D3DXVec3Normalize (&v, pTexCoord);  *pOut = D3DXVECTOR4 (v.x * 0.5f + 0.5f, v.y * 0.5f + 0.5f, v.z * 0.5f + 0.5f, 1.0f);}

then you should un-bias the normalized result:
float3 N = (texCUBE( Sampler, IN.normal ).xyz - 0.5) * 2.0;


The fill normalizer callback came from ati, but i could not duplicate the cube normalizer that came with rendermonkey. it was close, but the faces were in a different order.

I bet you are loading a cubemap with the 2d texture loader function. It will let you do this, but not warn you.

instead of D3DXCreateTextureFromFile, use D3DXCreate*Cube*TextureFromFile.
Sim, you nailed it on the head. I was using my regular texture loading routine instead of the Cube version. It almost seems logical now :)

Thanks again for your help!

This topic is closed to new replies.

Advertisement