Jump to content
  • Advertisement
Sign in to follow this  
Kest

Ambience with normal mapping

This topic is 4842 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

I've managed to hack together a system to normal map using dot product3. Take a look. The room on the left has been normal mapped: Image Hosted by ImageShack.us Please forgive the crude textures. I'm not an artist. So far, all of the code for this is in the vertex shader. But it only works in object space. That means the normal map texture needs to be specifically created for the orientation of the model. The models can be rotated and such, but the texture coordinates can't be backwards or flipped (a double sided wall wouldn't be able to use the same normal texture on both sides). This is a problem, so I'll most likely have to take UV coords into account later on. Anyway, as you can see, everything is very dark. I'm having trouble adding ambient lighting into the diffuse colors, since the diffuse is what is used to calculate the lighting directions. For example, for x, 0 is left facing, 128 is front/up facing, and 256 is right facing. Anyone know how I could add the ambience into this? I could multiply, but the result wouldn't be the same as for unbumped rendering. Here's the current hacked together shader I'm using:
vStage2Output vsMethod_Hack(vNormInput IVertex)
{
	vStage2Output OVertex;
	float4 Pos;

	// Transform Vertex into World space
	Pos = mul( float4(IVertex.Pos.xyz, 1.0f), WorldMatrix);

	float3 ldir;
	ldir.x = -( (LightDir.x * WorldMatrix._11) + (LightDir.y * WorldMatrix._12) + (LightDir.z * WorldMatrix._13) );
	ldir.y = -( (LightDir.x * WorldMatrix._21) + (LightDir.y * WorldMatrix._22) + (LightDir.z * WorldMatrix._23) );
	ldir.z = -( (LightDir.x * WorldMatrix._31) + (LightDir.y * WorldMatrix._32) + (LightDir.z * WorldMatrix._33) );
	ldir = normalize( ldir );

	OVertex.Diffuse.x = ( ldir.x + 1.0f ) * 0.5;
	OVertex.Diffuse.y = ( -ldir.z + 1.0f ) * 0.5;
	OVertex.Diffuse.z = ( ldir.y + 1.0f ) * 0.5;
	OVertex.Diffuse.w = MatAmbient.w;

	// Transform Vertex into Projection space
	OVertex.Pos = mul( float4(Pos.xyz, 1.0f), ViewProj);

	// Set Texture Coordinate
	OVertex.Tex1 = IVertex.Tex.xy;
	OVertex.Tex2 = IVertex.Tex.xy;

	return OVertex;
}

The large bit of code using the world matrix and light direction is just rotating the light with an inverse of the world. The swapping of z and y at the diffuse calculation is part of my UV hack, but I still have no idea why I needed to flip z's value :D Any help is appreciated

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Please forgive the crude textures. I'm not an artist.

Looks perfectly reasonable to me - definitely better than my attempts at "programmer art" [smile]

Quote:
But it only works in object space. <-- SNIP --> so I'll most likely have to take UV coords into account later on.

Check out the various articles on tangent space bump mapping - it's a fairly common thing discussed by some of the articles I've got. The basic trick, as I currently understand it, is to transform your normals based on the orientation of the surface they're being applied to, whilst the theory may not be entirely straight forward the implementations I've seen are pretty simple.


Anyway, to answer your question - by "Ambience" do you just mean the ambient term in the diffuse lighting equation. The same effect you'd get by setting D3DRS_AMBIENT with the fixed function lighting/material system?

If so, that would just require you to add a constant to the outputted diffuse colour -

OVertex.Diffuse.x = ( ldir.x + 1.0f ) * 0.5;
OVertex.Diffuse.y = ( -ldir.z + 1.0f ) * 0.5;
OVertex.Diffuse.z = ( ldir.y + 1.0f ) * 0.5;
OVertex.Diffuse.w = MatAmbient.w;
OVertex.Diffuse.xyz += 0.2f;


Should do the trick...


hth
Jack

Share this post


Link to post
Share on other sites
Quote:
Original post by jollyjeffers
Looks perfectly reasonable to me - definitely better than my attempts at "programmer art" [smile]

The normal maps are hand drawn. I was also figuring out how the color components worked with direction values as I was painting, so the whole thing got a bit waxed. Thanks for the compliment, though :)

Quote:
Check out the various articles on tangent space bump mapping - it's a fairly common thing discussed by some of the articles I've got. The basic trick, as I currently understand it, is to transform your normals based on the orientation of the surface they're being applied to, whilst the theory may not be entirely straight forward the implementations I've seen are pretty simple.

I've got it all working except the influence that the UV data has. Currently, my normal map colors must be in object space. If I were to rotate the texture on the face, the normals on the map stay the same. By the way, anyway you would happen to have a URL to one of those *pretty simple* articles? Or are they here? I'll look around :)

Quote:
OVertex.Diffuse.xyz += 0.2f;

Should do the trick...

I believe that would simply move the light into the positive realm of the normal map. For example, since left is represented by x==0, x += 0.2 would add light to the right direction and remove it from the left. Unless I'm misunderstanding something?

I appreciate your help

Share this post


Link to post
Share on other sites
Quote:
Original post by Kest
Quote:
Check out the various articles on tangent space bump mapping - it's a fairly common thing discussed by some of the articles I've got. The basic trick, as I currently understand it, is to transform your normals based on the orientation of the surface they're being applied to, whilst the theory may not be entirely straight forward the implementations I've seen are pretty simple.

I've got it all working except the influence that the UV data has. Currently, my normal map colors must be in object space. If I were to rotate the texture on the face, the normals on the map stay the same. By the way, anyway you would happen to have a URL to one of those *pretty simple* articles? Or are they here? I'll look around :)

I don't have the articles to hand, I'm not on my own machine at the moment (I have a few links there). This website has several good articles on it, but the articles search isn't being very friendly right now ([headshake]). The particular reference I was thinking of is a book that I own - Programming Vertex and Pixel Shaders by Wolfgang Engel. I forget the page/chapter reference, but there's a discussion of tangent space bump/normal mapping with particular references to the pro's/con's of using object space mapping (there are situations where object space can be useful).

Quote:
Original post by Kest
Quote:
OVertex.Diffuse.xyz += 0.2f;

Should do the trick...

I believe that would simply move the light into the positive realm of the normal map. For example, since left is represented by x==0, x += 0.2 would add light to the right direction and remove it from the left. Unless I'm misunderstanding something?

I was basing that on your stating that all the work is done in the vertex shader - assuming that you were leaving the actual rasterizing to the default pixel shader?

As such, whatever you output as the diffuse (assuming it has the COLOR semantic attached) will be interpolated across the triangles surface and outputted to the screen. If that is correct, then adding a constant to the outputted colour will add your ambient term to the final image.

Although, it is possible I'm missing something of course [smile]

Jack

Share this post


Link to post
Share on other sites
I'm not too sure I'm getting exactly what you want to do, but I understand you're having trouble handling when your model rotates, since your texture is for a specific orientation of the model.

From what I can read of your VS, you're inputting the light direction in object space, and then transforming it to world space.
Quote:

float3 ldir;
ldir.x = -( (LightDir.x * WorldMatrix._11) + (LightDir.y * WorldMatrix._12) + (LightDir.z * WorldMatrix._13) );
ldir.y = -( (LightDir.x * WorldMatrix._21) + (LightDir.y * WorldMatrix._22) + (LightDir.z * WorldMatrix._23) );
ldir.z = -( (LightDir.x * WorldMatrix._31) + (LightDir.y * WorldMatrix._32) + (LightDir.z * WorldMatrix._33) );
ldir = normalize( ldir );


If so, I think this could be your problem, and if you keep the light direction in object space, you should be safe.
Try this instead of those 5 lines:

float3 ldir = -LightDir;



Hope this helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by jollyjeffers
I was basing that on your stating that all the work is done in the vertex shader - assuming that you were leaving the actual rasterizing to the default pixel shader?

As such, whatever you output as the diffuse (assuming it has the COLOR semantic attached) will be interpolated across the triangles surface and outputted to the screen. If that is correct, then adding a constant to the outputted colour will add your ambient term to the final image.

I'm not using any pixel shaders. The D3DTOP_DOTPRODUCT3 texture stage directly uses the diffuse color of the transformed vertex to compute which color components of the normal map are used to brighten the result. This is the way the hardware is programmed to work through Direct3D.

In other words, the diffuse values no longer represent black=0,0,0 or white=1,1,1. In fact, 1,1,1 represents that all positive directions of the normal map are as bright as possible. 0,0,0 represents that all of the negative directions are as bright as possible. 0.5,0.5,0.5 defines all directions as pure dark. Considering this, adding 0.2 to all diffuse components will result in the texture appearing brighter in the positive directions and darker in the negative directions.

This is why I'm having such a hard time figuring it out. How do I add color to both sides?

edit: Well, you know, I should have just played dumb and tried it. It seems that adding to all three components does brighten the entire result. Light only gets brighter in positive directions when the remaining components have lower values. So I'm sorry I assumed I knew what I was talking about. You were totally right.

Unfortunately, simply adding the same ambience results in it becoming much brighter than normal renders. So I guess I need to reduce the ambience for normal mapped stuff. Does anyone know exactly why? Or any way of obtaining the correct modifier value for the ambience components?

Quote:
Original post by sirob
I'm not too sure I'm getting exactly what you want to do

Just add ambience to the brightness of the entire model.

Quote:
but I understand you're having trouble handling when your model rotates, since your texture is for a specific orientation of the model.

Not exactly. I can rotate the model just fine - and the normal map works exactly like it should. I just can't rotate or flip the texture coordinates on the polys. So I can't recycle a normal map from the floor to a wall - or it's up colors are pointing forward. I can, however, rotate a floor quad to be used as a wall, and it will work fine. This is because the color components of the normal map are drawn in object space. The shader only has access to the object transform, not a UV transform. So I have to figure out some way to get the UV transform info into every single vertex. Fun stuff.

Quote:
From what I can read of your VS, you're inputting the light direction in object space, and then transforming it to world space.

The light is in world space. The code you're seeing is transforming the light direction by the inverse of the world matrix. If you look closely, you'll notice it's not your average matrix-vector multiply. The matrix values are swapped around to actually mimic it being inverted during the multiply. Cool huh? :)

This is what a standard orientate operation would look like. Notice the col/row numbers being flipped:
nx = (x * mat._11) + (y * mat._21) + (z * mat._31);
ny = (x * mat._12) + (y * mat._22) + (z * mat._32);
nz = (x * mat._13) + (y * mat._23) + (z * mat._33);

Anyways, that bit of code is puting the light into object space. That's where the normal map colors exist, and what Direct3D needs. If I had my UV transform (or a transform for both at once), I would also need to do an invert with that.

Thanks to both of you for the help. But I'm still [edit: not so much now] clueless :)

[Edited by - Kest on September 8, 2005 9:36:47 PM]

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!