Bump Mapping & Normal Mapping
Blitz3D Forums/Blitz3D Programming/Bump Mapping & Normal Mapping
| ||
Can anyone point me to a blitz3d prog/demo with the source which demos on how to do bump maping, we tryed adding normal maps but it slowed down the game to much, will bump maps work any better? Thanks |
| ||
Normal maps = bump maps, just better (harder) way to do those than the old "heightmap bumpmaps" method. |
| ||
Were you using world space or tangant(sp) space? Tangant mapping is slower because it's pretty much cpu dependent, but world space is very fast on most cards. We had tech demos of 20-40 of rob's statues flying about with per pixel lighting, no slowdown, even on a g3. as it's basically just another blending mode..(dot3) try this, world space mapping technique, x#=entityX(myMesh)-entityX(light) y#=entityY(myMesh)-entityY(light) z#=entityZ(myMesh)-entityZ(light) td=entitydistance(myMEsh,light) x=x/td y=y/td z=z/td entityColor myMesh,128+128*x,128+128*y,128+128*z per frame on any normal mapped entities. You'll want to tweak the normals to add things like fall off and perhaps correct distance etc, but it's very fast. |
| ||
Ok anyone got any ideas why this is happening? We are using Omni for the light source which follows the character but when you turn the light isnt working correctly and some walls are dark. The player hasnt moved just turn around, any ideas? |
| ||
Normal maps can't usually be used by themselves as they do not provide any ambient light. The result of the normal map stage is alway 0-100% so you need to use multitexturing to add an ambient light stage to the surface calculation. |
| ||
So why does the wall work at the front but not at the back there all the same wall/mesh/texture/normal map? |
| ||
Without ambient light any surfaces facing away from the normal-map-light will be black. |
| ||
That's odd. Ambient light stage?(Raises eye-brow bond stylee) I just scaled the world-space normal to simulate differant light levels. Ie. x=x*distance (Distance being from 0 to 1) distance worked out ( distance =(fallOff-entityDistance(light,mesh))/fallOff Unless I'm getting the wrong end of the stick(Would not be the first time.Nor the last..) |
| ||
we use a point light at the center of the player, so there must be light reflecting on all walls near the player. So, ambient lighting is not the point here i think. What do you mean by "The result of the normal map stage is alway 0-100% so you need to use multitexturing to add an ambient light stage to the surface calculation" Thanks |
| ||
Normal maps work by multiplying a single *directional* light vector with the vectors encoded in each texel of the texture. The result of this multiply is 0..1 (black to white) which you can use to contribute extra detail to the final colour of the rendered surface but is not much use by itself (unless you're into ambientless (?) black and white lighting effects)... |
| ||
I suspect that you are using object space normal maps and not tangent space. ------------Something I found on the web--------------- The main idea behind using tangent space is going through extra steps to allow the reuse of a normal map texture across multiple parts of the model (storing normals/binormals/tangents at the vertices, and computing the normals of the normal map relative to them, then converting back when rendering. Also, you could use tangent-space to skin a flat bump texture around a model.) By writing a tutorial on object space, I'm not saying object space is better. However it does have some advantages, and is certainly a usable approach. Below are a few of my thoughts on the two methods for those interested, I'm not qualified to give a great comparison of the two though. There are some tricks or different ways to do things with any method. Advantages to using Object Space: It's simpler to implement and I find it more straightforward to think about. The normal map contains the normals pointing in their actual directions (for an unrotated model at least.) You get to forget about per vertex normals, tangents, and binormals ( which I'll call n/t/b for short. ) This means less initial calculations, and you don't have to worry about poorly behaved n/t/b causing distortion. It's also faster because you don't have to rotate the n/t/b with your model, or convert light vectors to tangent space. Level of detail algorithms or anything else that reduces and changes the vertices in your model can easily run fine. (In tangent space the changing n/t/b interpolations caused by removed vertices would distort the mesh normals. ) Disadvantages (as opposed to Tangent Space): You can't reuse texture coordinates for symmetric parts of the model. If you had a model that is completely symetric along an axis, and 1 MB normal map, that means 0.5 MBs of it is redundant information. If this bothers you, keep in mind this is only for something rendered as one piece. In the case mentioned above you could render the model in two halves, each using the same normal map, but one rendered with the light vector x component reversed ( or y or z depending on the axis of symmetry. ) Which would be a bit of extra work itself though. The main disadvantage to not using tangent space is that you can't use a detail normal map for fine close-up detail in addition to the one that approximates the high resolution mesh. (You can add details into the object space normal map when generating it, however, a detail normal map would be highly repeating, thus offering much greater resolution than just using the one normal map.) |
| ||
One thing to consider is in Blitz G=z and B=Y. (I.e reverse them in your 'equations') If you're still stuck after that, say so and I'll dig up some code off my hd that works. |
| ||
Otacon: Im really confused as to what we are doing wrong so any demo code which you think would help us would be grate :) |
| ||
Here's the smallest test I could find of mine, this is for a mesh using world space normal mapping. EntityLight will be of most use to you, it allows you to set the right entityColor based on both the lights position and the actual meshes orietnation. (It does this by projecting the light into object space first) Get rob's normal mapping demo for a compatible mesh/normal map. You can then compare it with your mesh in the test below to help pin-point any probs with your own normal maps. Graphics3D 640,480,16,2:HidePointer SetBuffer BackBuffer():MoveMouse 320,240 ;load And prep mesh For mapping ta =LoadMesh("3d/a.b3d") ;load mesh ScaleMesh ta,1,1,1 ;This is specific to the statue rob used. Remove or adjust for alternative media. ;nm=LoadTexture("normal.png") ;Normal map. If using rob's statue, it's the same one he used. nm=LoadTexture("3d/n2.png") t2=LoadTexture("3d/diffusemap.png") t1=LoadTexture("t1.jpg") ;TextureBlend nm,4 ;dot3 blendng EntityTexture ta,nm,0,0 ;set as base texture. EntityTexture ta,t2,0,1 TextureBlend nm,4 TextureBlend t2,3 HideEntity ta num=40 ;number of statues/meshes for tv=1 To num ti=CopyEntity(ta) RotateEntity ti,0,Rnd(160),0 PositionEntity ti,Rnd(-1000,1000),15,Rnd(-1000,1000) h.h=New h h\id=ti Next ;- Type h Field id End Type AntiAlias False Dither False ;- ;-end of bump-mapping prep. vcam=CreateCamera() cp=CreatePivot() ;just something for the camera to focus on PositionEntity cp,0,25,0 lp=CreateSphere() FitMesh lp,-2,-2,-2,4,4,4 PointEntity vcam,cp ;centre on the statue. PositionEntity vcam,0,15,-120 PointEntity vcam,cp p=CreatePlane() EntityTexture p,t1 ScaleTexture t1,10,10 AmbientLight 128,128,128 Repeat xa#=xa+0.2 If MouseDown(2) PositionEntity lp,EntityX(vcam),EntityY(vcam)+5,EntityZ(vcam) If MouseDown(1) PositionEntity lp,Cos(xa)*60,15,Sin(xa)*60 fr=fr+1 ms=MilliSecs() If ms>ls ls=ms+1000 fps=fr fr=0 EndIf TurnEntity vcam,MouseYSpeed(),-MouseXSpeed(),0 RotateEntity vcam,EntityPitch(vcam),EntityYaw(vcam),0 MoveMouse 320,240 FlushMouse RenderWorld Text 10,10,fps If KeyDown(17) MoveEntity vcam,0,0,0.3 If KeyDown(31) MoveEntity vcam,0,0,-0.3 If KeyDown(30) MoveEntity vcam,-0.3,0,0 If KeyDown(32) MoveEntity vcam,0.3,0,0 For h.h=Each h entitylight( h\id,lp) Next Text 1,30,"Tris>"+TrisRendered() Text 1,45,fps Flip False Until KeyDown(1) Function entityLight(entity,light) ;call every frame. ox=EntityX(light) oy=EntityY(light) oz=EntityZ(light) TFormPoint ox,oy,oz,light,entity PositionEntity light,TFormedX(),TFormedY(),TFormedZ() ;Transpose light into dx# =EntityX(light)-EntityX( entity) dy# =EntityY(light)-EntityY( entity) dz# =EntityZ(light)-EntityZ( entity) nl#=Sqr(dx*dx+dy*dy+dz*dz) nx#=dx/nl ny#=dy/nl nz#=dz/nl nl=(255-nl)/255.0 ;fall off. nl=1-nl If nl>1 nl=1 If nl<0 nl=0 nx=nx*nl ny=ny*nl nz=nz*nl EntityColor entity,128+(128*nx),128+(128*nz),128+(128*ny) PositionEntity light,ox,oy,oz ;return light. End Function |
| ||
Right a slight problem These pictures are from a program called DotMyBot which we tryed to work from but got the problem of the dark walls With Normal Map Without Normal Map These ones are from the code you did above, and they dont look really like they have normal maps more like reflective. With Normal Map Without Normal Map Any ideas :) |
| ||
Heh, nope, works fine with Rob's statue. Can't test it atm, stuck using a Voodoo5 until my g5 gets here from PcWorld. soz ;) |
| ||
Whats robs statue that your talking about? |
| ||
Right heres a file with the problem we have including source if anyone can fix it it would be a massive help! http://www.dungeon-maker.com/uploader/uploads/bump/bump.rar |
| ||
rob's statue is a pictureesque statue he had scholars of italian fine art produce of him, so he could bask in the glory of Rob all day long. Well, not really, it's a statue baked with a normal map he used in his demo. check his sig. |
| ||
when i tried robs statue with the code you gave me, the model is massive and it doesnt look like its bump maped :( |
| ||
Well wait a few days until my g5 gets here, I can't imagine why it's not working anymore. It worked on a g3 too 'cos I sent tests to evak and they worked fine..so unless you have a really old card it should work.. |
| ||
I have a ati radeon 9000m |
| ||
Dont suppose anyone else out there know where i can get a demo on how to do normal maps which includes the source? How come rob didnt release his source? (That would be handy) |
| ||
Yeah, as it goes search on blitzcoder.com's forums. I posted the source code to Rob's demo.(I.e I emulated what he did, not his actual code) |
| ||
Well, dunno if its me, but Rob's statue demo had no detailed texture like your stone wall correct? I just remember it being a grey model with a nice lighting job applied to it..... |
| ||
*hic* |
| ||
This is exactly why Blitz3D normal/bump mapping is so limited. The bump texture encodes normals in world space, not local or tangent space. Even though the cube uses the same texture on all six sides the normal map is correct for only one of them. For example, suppose it is correct for the front face. When the same bump map is applied to the back face the normals point into the cube. You need a separate bump map for each side. |
| ||
It's not limited, it's identical to how you'd do it in C++ or whatever imo. You just have to do tangant mapping, i.e instead of a universal entityColor job, you have calc it per-tri which involves transforming the light into tri(Tangant) space. and painting the vert colors with this. There's nothing to stop anyone doing this in blitz. This is the slowest but best method. Or option 2, you spread the normal map across six faces,(I.e each face has a unique direction)..this isn't as nice though, only of use on things like rob's statue, and is the method I posted above. This much easier, faster but not as nice. |
| ||
Can anyone explain how i would add the more normal maps i.e. 4 for each side (Dont worry about top and bottom) using the code I have above :) |
| ||
So has no one worked out how to apply a normal map to a cube? |
| ||
Not quite sure what i did but this seems to work :) www.dungeon-maker.com/uploader/uploads/bump/bumpupdated.rar Just in case anyone want to use it. |
| ||
Forget that, I really dont get this. I can rotate the cube and its fine all sides work not problems, but when u move the camera you get the dark sides, so surely it means theres something funny with the light code which isnt making the light follow the camera correctly |
| ||
Right Update: I will get this sorted some how. I changed the code so that I could freely move each object. 1. If i rotate the cube with the light and camers staying still it works fine. The normal maps are fine on each side of the cube. 2. I move the camera and not the cube I get dark patchs 3. I moved the camera and the light source, but i still get dark patchs!! What is the difference between moving the cube and moving the camera/light? |
| ||
Should i give up? |
| ||
Never give up.. "The Answer is out there...." |