views:

421

answers:

3

hiya. I'm looking for the simplest, easiest and fastest technique to render 2D textured quads with per-pixel normals. what i mean is a 3D world where the camera is fixed and all the texture quads are facing to the same direction (the camera), and between them there will be light points, and i want the textures to have per-pixel normal values so they'll lit as if they were 3D models.

most techniques i found on the net are way too complicated and heavy cause they refer to real 3D models, while all i need is simple 2d quads.

does anyone knows an appropriate technique or can post a useful tutorial? oh, and DX only pls.

thanks.

+1  A: 

""Real" 3D models are just made up of a bunch of 2D polygons."

  • true, but when dealing with "real" 3D models you are also dealing with rotation in 3D space, which makes everything far more complicated (and since the techniques i found are designed to deal with that, they are way too complicated and over-kill for my needs). also, please note the huge difference between a flat quad that happens to be in a 3D space, and a mesh made of dozens if not more of polygons spread in a 3D space, while every polygon normals are factor of the polygon factor and the normal map - which is anther complication I'd like to avoid since all of my quads normals are the same - 0, 0, -1.
rubi
Please don't use the answer field to answer comments. Add another comment under your own question instead :-)
Mads Elvheim
All of your normals are the same? *exactly* the same? Then all you need to do is modify the approach I suggested in my answer, but instead of having a normal map simply pass in the one single normal you need. For added efficiency just pass the dot product of the light direction and the normal in directly.
Martin
Mds Elvheim - right, im kinda new to this site :)Martin - thank you very much, but im looking for something to support multiple lights. also in DX will be much better..Stringer Bell - you are probably right. my engine will only require X axis flip, which will make me need to invert the Red channel.
rubi
A: 

I'm more experienced with XNA rather than directX, but the principle is the same.

You need a normal map, this tells your shader exactly what the surface normal is at a given point. You then need your quads to be texture mapped (they probably already are, so this isn't really any extra work). Then you draw the quads with a pixel shader, inside the shader you do something like:

//This shader only handles one directional light, there are various tecnhiques for handling multiple lights.
float3 LightDirection;

//Normal map, set this before rendering the quad
Texture NormalMap;
//sampler
sampler normalSampler = sampler_state
{
  texture = <NormalMap>;
}

//Diffusemap, set this before rendering the quad. This is just your normal texture you want applied to the quad
Texture DiffuseMap;
//sampler
sampler diffuseSampler = sampler_state
{
  texture = <DiffuseMap>;
}

/* you probably need a vertex shader to run all your translations etc, that's pretty bog standard stuff so I won't include one here */

float4 PixelShader(float2 texCoord : TEXCOORD0) : COLOR0
{
  //standard directional lighting equation with normals
  float3 Normal = tex2D(normalSampler, texCoord);
  float dot = dot(LightDirection, Normal);
  return tex2D(normalSampler, texCoord) * dot;
}
Martin
A: 

Well in that case you don't even need to form a tangent basis which makes it quite easy. Assuming, directional lighting, if you transform your light into view space then you can directly N.L the light (L) against the normal (N) from the normal map. You transform teh light vector into view space by simply multiplying it by the view matrix.

It is a little more complicated if you want point lighting. You need to first transform your light position into view space. Then you need to subtract your light position from your pixel position, normalise the resulting vector and use that as your L vector in the N.L calculation :)

Either, way ... job done! :D

Goz