Simle HLSL cubemap reflection

Started by
27 comments, last by GLForce 15 years ago
I recently started to play around with HLSL shaders. I'm currently trying to make real simple water, with bump mapping and cubempa reflection. Now my problem is with that actual cubemap reflection. The code is pretty simple, and for once I undertsand it all. However, it seems to procude strange results. I find it quite annoying because nobody seems to have problems and I do, and I just can't point the source. So I wondered if any of you pros could help me ;). I've put two screenshots to show the results. I apply the shader on a simple square made from 4 vertices with their normal upward (0, 1, 0). This screen shot shows how the cubemap projection on the plane just mess up when the camera is positionned according to particular angles. http://img21.imageshack.us/img21/6876/screen1tso.th.jpg The second one shows the main problem, it seems that something's wrong with the coords interpolation between the opposite corners. There is clearly (easier to see when its moving) a seem between the two triangles. http://img21.imageshack.us/img21/238/screen2uhk.th.jpg I've put the HLSL code here, you'll see that it's quite simple.

float4x4 WorldViewProj : WORLDVIEWPROJ;
float4x4 World : WORLD;
float ElapsedTime;
float3 Eye;

texture ReflectionTexture;

samplerCUBE ReflectionSampler : TEXUNIT3 = sampler_state
{
	Texture = (ReflectionTexture);
	MIPFILTER = LINEAR;
	MINFILTER = LINEAR;
	MAGFILTER = LINEAR;
};


struct VS_IN
{
	float4 Position : POSITION;
	float3 Normal : NORMAL;
	float2 Texture : TEXCOORD0;
};

struct VS_OUT
{
	float4 Position : POSITION;
	float3 Texture0 : TEXCOORD0;
};

struct PS_OUT
{
	float4 Color : COLOR0;
};

VS_OUT vs_func(in VS_IN In)
{
	VS_OUT Out;

	Out.Position = mul(In.Position, WorldViewProj);

	float3 WorldPos = mul(In.Position, World).xyz;

	float3 WEye = mul(World, Eye);

	float3 V = normalize(WorldPos - Eye);

	float3 Normal = normalize(mul(World, In.Normal));
	
	Out.Texture0 = reflect(V, Normal);

	return Out;
}

PS_OUT ps_func(in VS_OUT In)
{
	PS_OUT Out;
	
	float4 color = texCUBE(ReflectionSampler, In.Texture0);

	Out.Color = color;
	
	return Out;
}

technique Technique0
{
	pass p0
	{
		FogEnable = FALSE;
		Lighting = FALSE;

		Sampler[0]= (ReflectionSampler);
		
		VertexShader = compile vs_1_1 vs_func();
		PixelShader  = compile ps_2_0 ps_func();
	}
}

Basically, I compute the view direction by substracting the eye position (camera position) from the vertex position, both in world space. I use this view direction along with the normal (which i'll recall is always (0,1,0)) to get a reflection vector which is actually used as my 3d coords for the cubemap. So, any idead why that wouldn't work ? P.S. : The cubemap has nothing to do with the skybox, it's normal :P [Edited by - GLForce on April 17, 2009 4:54:05 PM]
"Do, or do not. There is no try." - Yoda
Advertisement
You're doing mul(World, Normal) which is actually transforming your normal by the transpose of your world matrix. Try swapping those two.

Also, if you want to post code here you can use the "code" and "source" tags. See the FAQ.
Well I forgot to say but those kind of operations, mul, I've tried every possible way of doing them there is. This way, the other way you proposed, with an implicit float4 like this, with the explicit way (float4(In.Normal, 1), World), etc.. etc.. I'll try anyway, who knows. Thanks for the reply. Oh and thanks for the code tag, I should have check the FAQ more.

EDIT : Tried it. Same result. I really wonder because any of these changes just doesn't make any difference, that's odd.
"Do, or do not. There is no try." - Yoda
Hi,

There are some mistakes I saw:

1 - Why're you multiplying your eye pos. vector with world matrix? Is that vector in local space? I don't think so, you shouldn't do it.

2 - Why're you multiplying your normal vector with world matrix like that:
float3 Normal = normalize (mul (World, In.Normal));

HLSL matrix structures are not column-major (you're not using Cg, CgFX or GLSL), they are row-major. So, first parameter must be vector, and the second one must be matrix. Also, your normal vector isn't float4, it's float3. One more thing to say: it would be better if you use inverse transpose of world matrix instead of world. So, that line should be changed like this:

float3 Normal = normalize (mul (float4(In.Normal, 0), WorldInvTranspose));

Rest of your code seems correct.
Hope this helps.

Regards,
Rohat.
There's no "hard", and "the impossible" takes just a little time.
Quote:Original post by GLForce
Well I forgot to say but those kind of operations, mul, I've tried every possible way of doing them there is. This way, the other way you proposed, with an implicit float4 like this, with the explicit way (float4(In.Normal, 1), World), etc.. etc.. I'll try anyway, who knows. Thanks for the reply. Oh and thanks for the code tag, I should have check the FAQ more.

EDIT : Tried it. Same result. I really wonder because any of these changes just doesn't make any difference, that's odd.
That is most likely because your world matrix is an identity matrix, i.e. the object is at the origin without any rotation applied. Then the transpose of the matrix is the same thing, making it look like nothing changed. Get in the habit of always putting the point being transformed first, and the transform second - unless you explicitly want to multiply by the transpose!

As others have pointed out, the view position is in world space already so you should not transform it. If your world matrix is identity (which I think it is) then making this chance won't appear to change anything either, but you still need to change it for when you have a non-identity world matrix.

I can't really see problem #2 in the image - its showing up really small for some reason. Try changing your mul statements and the view calculation, then repost your screens and code and we'll take it from there.
Here's the updated code. Not much has changed. For the eye position, I already did the changes, I did wondered why it had to be mutliplied by the world matrix. I probably understood the sample I followed wrong. As for the results, still no change. I'm posting back the second picture (it was actually a thumbnail and not the picture itself), even if it still doesn't show well what I want to show.

float4x4 WorldViewProj : WORLDVIEWPROJ;float4x4 World : WORLD;float4x4 WorldIT : WOLRDIT;float3 Eye;texture ReflectionTexture;samplerCUBE ReflectionSampler : TEXUNIT3 = sampler_state{	Texture = (ReflectionTexture);	MIPFILTER = LINEAR;	MINFILTER = LINEAR;	MAGFILTER = LINEAR;};struct VS_IN{	float4 Position : POSITION;	float3 Normal : NORMAL;	float2 Texture : TEXCOORD0;};struct VS_OUT{	float4 Position : POSITION;	float3 Texture0 : TEXCOORD0;};struct PS_OUT{	float4 Color : COLOR0;};VS_OUT vs_func(in VS_IN In){	VS_OUT Out;	Out.Position = mul(In.Position, WorldViewProj);		float3 WorldPos = mul(In.Position, World).xyz;	float3 V = normalize(WorldPos - Eye);	float3 Normal = normalize(mul(float4(In.Normal,0),WorldIT));		Out.Texture0 = reflect(V, Normal);	return Out;}PS_OUT ps_func(in VS_OUT In){	PS_OUT Out;		float4 color = texCUBE(ReflectionSampler, In.Texture0);	Out.Color = color;		return Out;}technique Technique0{	pass p0	{		FogEnable = FALSE;		Lighting = FALSE;		Sampler[0]= (ReflectionSampler);				VertexShader = compile vs_1_1 vs_func();		PixelShader  = compile ps_2_0 ps_func();	}}


Pic 2
http://img21.imageshack.us/img21/238/screen2uhk.jpg

I seriously think, after seeing it in movment, that the problem comes from the geometry. However, the ting is quite simple : as I said, it's a simple quad going from -10 to 10 on both x and z axis, positionned at y=0, and with an upward normal (0, 1, 0). But from the look of it, and I really have a hard time explaining it because english isin't my first language and the idea itself is quite complex, the interpolation seems wrong. I know it's hard to see in the screenshot, but try to visualize the polygon separation line, going from the lower left corner to the upper right, and that from that line to the corners, the cubemap projection takes differant angles (again, hard to explain). I'll try with a little MS paint schema.

http://img407.imageshack.us/img407/4994/shemam.jpg

Sorry did my best.

Oh and thanks again for all your time and help.
"Do, or do not. There is no try." - Yoda
Hi,

I see that reflection changes along the diagonal. Why don't you check your winding order?

Regards.
There's no "hard", and "the impossible" takes just a little time.
I thought about this one too. The thing is backface culling is activated so if any of the polygons were not correctly winded, it would not be rendered. However, I'll follow your idea and simply try to wind it in different ways, but always in the right way. Logically, it wouldn't make any difference, but you know sometimes... And I finally tested my shader in an existing engine (Virtools), and, as I thought, the shader is all right. It worked on a plane, a cube, even a teapot. So my conclusion is that the geometry is really the problem. That's why I'll try to play with winding. Thanks !
"Do, or do not. There is no try." - Yoda
Are you certain that the cube map is properly loaded as a cube map, and not as a 2D texture? Check which D3DX function you are using to load the map and ensure it is the 'Cube' version. I have made this mistake in the past, and D3D9 will happily continue on with the 2D interface bound as a cube texture!

You might also try to rotate your quad along the z axis to see if any of the other faces of the cube map show up - this could also indicate that the cube map interface is somehow incorrect.
Ahhh very good point. And I didin't even think about it. I've implemented a resources manger in my engine responsible for loading stuff like meshes, textures, etc.. And guess what, I just didin't make anything about cube textures. So result, I was using the same functions to load 2d textures and cube textures. I can't wait to try this as soon as I can (right now i'm supposed to study my final exams, what a pain in the...). Thanks alot, again, you give me confidence in the human kind :P

By the way, I've looked quickly at your articles and the online book, really interesting. I'll make sure to take a deeper look at it (fav'd).
"Do, or do not. There is no try." - Yoda

This topic is closed to new replies.

Advertisement