Jump to content
  • Advertisement
Sign in to follow this  
mslaf

OpenGL Problem with incorrect offset in 'parallax offset'

This topic is 2570 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm having difficulties trying to find out why the simple parallax offset is wrong. It's obvious that it depends on the Camera vector but for some reason, the UV translation is bad.

On a simple (subdivided) cube the effect is fine on the one side of it, while the offsets on the other sides (perpendicular to the correct one) is incorrect:

Side with PO rendered correctly:

poproblem1.jpg

Sides with PO rendered incorrectly:

poproblem2.jpg

poproblem3.jpg

Correct:

poproblemok.jpg

Incorrect:

poproblembad1.jpg
poproblembad2.jpg

Shader code:
/*****************************************************************************
Transformation matrices:
*****************************************************************************/

_float4x4 gWorldInverseTranspose : WorldInverseTranspose < string UIWidget="None"; >;
_float4x4 gWorldViewProjection : WorldViewProjection < string UIWidget="None"; >;
_float4x4 gViewInverse : ViewInverse < string UIWidget="None"; >;
_float4x4 gWorld : World < string UIWidget="None"; >;

// Left for the compatibility with the FX Composer, XSI, 3ds max and others:

#define WorldITXf gWorldInverseTranspose
#define WvpXf gWorldViewProjection
#define WVPXf gWorldViewProjection
#define WorldXf gWorld
#define ViewIXf gViewInverse

/*****************************************************************************
Vertex data structure:
*****************************************************************************/

struct VertexShaderParameters
{
_float3 Position : POSITION;
_float2 UV1 : TEXCOORD0;
_float2 UV2 : TEXCOORD1;
_float4 Normal : NORMAL;
_float4 Tangent : TANGENT0;
_float4 Binormal : BINORMAL0;
};

/*****************************************************************************
Pixel shader data structure:
*****************************************************************************/

struct PixelShaderParameters
{
_float4 Position : POSITION;
_float2 UV1 : TEXCOORD0;
_float2 UV2 : TEXCOORD1;
_float3 WorldNormal : TEXCOORD2;
_float3 WorldView : TEXCOORD5;
_float3 WorldPosition : TEXCOORD6;
_float3 WorldTangent : TEXCOORD3;
_float3 WorldBinormal : TEXCOORD4;
};

/*****************************************************************************
Vertex Shader:
*****************************************************************************/

PixelShaderParameters vs_main( VertexShaderParameters Input )
{
PixelShaderParameters Output;

_float4 lPosition = _float4( Input.Position.xyz, 1 );
Output.Position = mul( gWorldViewProjection, lPosition );
Output.UV1 = Input.UV1;
Output.UV2 = Input.UV2;
Output.WorldNormal = mul( gWorldInverseTranspose, Input.Normal ).xyz;
Output.WorldTangent = mul( gWorldInverseTranspose, Input.Tangent ).xyz;
Output.WorldBinormal = mul( gWorldInverseTranspose, Input.Binormal ).xyz;
Output.WorldPosition = mul( gWorld, lPosition ).xyz;
Output.WorldView = normalize( _float3( gViewInverse[0].w, gViewInverse[1].w, gViewInverse[2].w ) - Output.WorldPosition );

return Output;
}
/*****************************************************************************
Pixel Shader:
*****************************************************************************/

_float4 ps_main( PixelShaderParameters Input ) : COLOR
{
/*************************************************************************
Initialze shared parametes:
*************************************************************************/

_float3 lNormalizedWorldNormal = normalize( Input.WorldNormal );
_float3 lNormalizedWorldView = Input.WorldView; // already normalized in VS
_float3 lNormalizedTangent = normalize( Input.WorldTangent );
_float3 lNormalizedBitangent = normalize( Input.WorldBinormal );

/*************************************************************************
Initialize paralax offset for UV1:
*************************************************************************/

_float2 lUV1 = Input.UV1;
if ( g_EnableParallaxMap )
{
_float fOffset;
if ( g_ParallaxInNormalMapAlpha )
fOffset = tex2D( NormalMap, lUV1 ).a;
else
fOffset = tex2D( ParallaxMap, Input.UV1 ).r;

fOffset *= ( g_ParallaxScale * PARALLAXOFFSET_MULTIPLIER );
fOffset -= PARALLAXOFFSET_MULTIPLIER / 2.0f;

lUV1.xy += lNormalizedWorldView.xy * fOffset;
}

/*************************************************************************
Initialize light vectors:
*************************************************************************/
(...)


Code is for CGFX for opengl ouput, using the 'latest' profile. Everything else like shading, specular reflections, environment and normal mapping is correct. Only the UV offset is wrong.

What I have made wrong?

EDIT1: Did I miss to multiply the WorldView by 3x3 matrix build from tangent, binormal and normal in VS and use it instead of lNormalizedWorldView in PS?

EDIT2: I did:) Problem solved.

PixelShaderParameters vs_main( VertexShaderParameters Input )
{
PixelShaderParameters Output;

_float4 lPosition = _float4( Input.Position.xyz, 1 );
Output.Position = mul( gWorldViewProjection, lPosition );
Output.UV1 = Input.UV1;
Output.UV2 = Input.UV2;
Output.WorldNormal = mul( gWorldInverseTranspose, Input.Normal ).xyz;
Output.WorldTangent = mul( gWorldInverseTranspose, Input.Tangent ).xyz;
Output.WorldBinormal = mul( gWorldInverseTranspose, Input.Binormal ).xyz;
Output.WorldPosition = mul( gWorld, lPosition ).xyz;
Output.WorldView = normalize( _float3( gViewInverse[0].w, gViewInverse[1].w, gViewInverse[2].w ) - Output.WorldPosition );
Output.CameraVector = mul( Output.WorldView, transpose( _float3x3( Output.WorldTangent, Output.WorldBinormal, Output.WorldNormal ) ) );

return Output;
}

(...)

/*****************************************************************************
Pixel Shader:
*****************************************************************************/

_float4 ps_main( PixelShaderParameters Input ) : COLOR
{
/*************************************************************************
Initialze shared parametes:
*************************************************************************/

_float3 lNormalizedWorldNormal = normalize( Input.WorldNormal );
_float3 lNormalizedWorldView = Input.WorldView; // already normalized in VS: normalize( Input.WorldView );
_float3 lNormalizedTangent = normalize( Input.WorldTangent );
_float3 lNormalizedBitangent = normalize( Input.WorldBinormal );

/*************************************************************************
Initialize paralax offset for UV1:
*************************************************************************/

_float2 lUV1 = Input.UV1;
if ( g_EnableParallaxMap )
{
_float fOffset;
if ( g_ParallaxInNormalMapAlpha )
fOffset = tex2D( NormalMap, lUV1 ).a;
else
fOffset = tex2D( ParallaxMap, Input.UV1 ).r;

fOffset *= ( g_ParallaxScale * PARALLAXOFFSET_MULTIPLIER );
fOffset -= PARALLAXOFFSET_MULTIPLIER / 2.0f;

lUV1.xy += normalize( Input.CameraVector ).xy * fOffset;
}






Share this post


Link to post
Share on other sites
Advertisement
Just a quick reply, I may have missed some details, but I remember when I implemented parallax some time ago I've a similar problem.
And by a quick glance of your shader, I see the following line:
lUV1.xy += normalize( Input.CameraVector ).xy * fOffset;
So you're using the camera x and y as offset, what about the z?
If I'm assuming correctly (I did not read the shader with more attention), that means the offset is very dependant of the camera position/view vector.
Last time I asked about it before they said me that this was a inherent flaw of the parallax algoritm, and that it only worked nicely with correctly tuned offset vectors.
Do not assume I'm correct though, this is just something straight from my memory, maybe someone else can give you a better answer :)

Share this post


Link to post
Share on other sites
@Relfos

I seems to work fine, not perfecet but I only need it for a preview in XSI, so it's fine for me. I've named the variable CameraVector but in fact it's a viewing direction, converted from tangent to texture space, as it described here.

@GeneralQuery

This my own texture; created from the picture taken in École militaire in Paris;) If you ask about normal/parallax quality, then the whole trick is about painting the heightmap over such texture before doing normal map. This is purely manual process and thus extremely time consuming, but it gives the best possible results:

Crazybump:
bump1.jpg

np_uebad.jpg

vs manual painting:
bump2.jpg

np_uegood.jpg

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!