   Bumpmapping - find appropriate ( best ) light or lights?
  Hi  Recently I've started to carry on work on my engine,I've decided to add bumpmap support to my class workingwith Q3 Arena BSP map. I've had no experience with bumpmapping before, although I loved it.  So somehow I've put it together and now - somehow -it is showing levels with bumpmapping, but problemI have is with lights. Particularly with finding bestlight for some face. What is best light? I thought,thatit is closest one. No, it is not true. Then I thoughtthat face's normal must face light directly and beclosest one if posible. I've played around with fewposibilities, but I am still in beginning. I cannotfind best light source for bumpmapping. I should say,that I am looking for one light source, because I don'tknow how should I evaluate more lights for bumpmap purpose.I will show you my problem on few examples:In this one, the light is evaluated per whole face. Iwill find light closest to whole face, then I computeall vertices (bump shift - cubemap) to this perticular light.(notice lightchange on the floor between hall and corridor)Well, but what is problem - you can see on picture - thaton border of two faces, the light is different. From corridorit is becoming dark, and from hall it is still light. So thereis awful light jump.Code is about this:void bspLevel::CalculateBumpVerticesLightShift (){... some checks if light exist at all// go throught all faces and find closest light// do bump map shift according to this lightVertex lightVector;// vector from vertices to lightVertex stred;// middle point in facefor (int i=0;i<m_nFaces;i++)   {   bspFace *f = &m_pFaces;   // find middle point of face and make vector from it to light   // take first and third for ease   stred = m_pVertices[f->VertexIndex] + m_pVertices[f->VertexIndex + 2];   stred /= 2;   // find closest light and use face normal   Vertex light = ((CLight *)lt.FindClosestLight ( stred,f->m_vNormal ))->m_vPos;   for (int j=0;j<f->m_nVertices;j++){int id = f->VertexIndex + j;lightVector = light - m_pVertices[id];m_pVertices[id].CubemapCoord.x = CMath::DotProduct (m_pVertices[id].STangent,  lightVector);m_pVertices[id].CubemapCoord.y = CMath::DotProduct (m_pVertices[id].TTangent,  lightVector);m_pVertices[id].CubemapCoord.z = CMath::DotProduct (f->m_vNormal, lightVector);}   }}  So .. I've decided to find closest light to every single vertexin face, it's solved something, but not all problems. See image below:You see the problem? Lights are not OK, because it makes weird effect on walls, somewhere there is too much light, for me itis random. Code was:void bspLevel::CalculateBumpVerticesLightShift (){... some checks if light exist at all// go throught all faces and find closest light// do bump map shift according to this lightVertex lightVector;// vector from vertices to lightVertex stred;// middle point in facefor (int i=0;i<m_nFaces;i++)   {   bspFace *f = &m_pFaces;   for (int j=0;j<f->m_nVertices;j++){int id = f->VertexIndex + j;Vertex light = ((CLight *)lt.FindClosestLight (m_pVertices[id],m_pVertices[id].m_vNormal ))->m_vPos;lightVector = light - m_pVertices[id];m_pVertices[id].CubemapCoord.x = CMath::DotProduct (m_pVertices[id].STangent,  lightVector);m_pVertices[id].CubemapCoord.y = CMath::DotProduct (m_pVertices[id].TTangent,  lightVector);m_pVertices[id].CubemapCoord.z = CMath::DotProduct (f->m_vNormal, lightVector);}   }}Code for lightmanagers FindClosestLight, is not smartest one,it goes trought all lights, find its closest two - one for reallyclosest and second for closest, which also faces light.If there is no closest light which faces face, then use normalclosest.Please take this function as temporary, not final, it is notfor optimalisation, but for understanding etc..CLight *CLightManager::FindClosestLight (Vertex v, Vertex normal){if (m_lLight.Count==0)return NULL;float vzdal = 99999;// for regarding normalfloat vzdal2 = 99999;   // without normalfloat temp;float uhel;Vertex delta;Vertex lightpos;int id = 0;// id of light with normalint id2 = 0;// id of light without normalfor (int i=0;i<m_lLight.Count;i++){   lightpos = m_lLight.m_vPos;  delta = lightpos - v;  temp = delta;  CMath::Normalize (δ);  uhel = CMath::DotProduct(delta, normal);  if (temp < vzdal && uhel>0){vzdal = temp;id = i;}if (temp < vzdal2){vzdal2 = temp;id2 = i;}}   // if there is not closest light with normal, then use closest without normal   if (vzdal == 99999){id = id2;}  // if vzdal1 light is too far, then use closest one  if (vzdal > 2 * vzdal2){id = id2;}   return &m_lLight[id];}So and now, what I need. Firstly I am not decided to continue withonly one light source per face, however I don't know how I should doit for more lights. Is there any tutorial on it?Well, let's say one light per face is enough. But how can I find"good" light? How can I avoid this light jumps and light marks onwalls?If you know some tutorial, which solves this - if in BSP it will begreat, let me know.If you know some open source engine, which uses and solves this, alsolet me know.If you have better idea/procedure how to find best light, also let me know.Any sugestions will be welcomed.Thanks Martin[Edited by - martinhoge on December 5, 2005 8:54:50 AM]
  dont just have one light per surface it will look wrong and flicker during actual gameplay.take into consideration all lights that affect the surface   ;  Well, I agree with you, but how can I compute cubemap coords to all those lights? I haven't found any materials on it.And there is also another thing..how can I find lights who affects surface?What if there will be some wall ( still in bsp ) between ligth and surface that affects it. How should I recognize it? I think it could be done be portals visibility, but if I will evaluate all those light it will take lot of CPU.   ;  you can save light indices in each vertex and pre-calculate them into the static geometry on load time :struct MyVertex{    float3 p;    float2 coord;    float4 lightIndices;};"lightIndices" will hold 4 indices to the scene lights that you want to illuminate the vertex.pass these vertices to the vertex shader and light them.for more than 4 (less is even better) lights per vertex, you can do a simple algorithm like choosing the two lights that their angle between light position and destination vertex are wider.hope this helps !;  Well,    I think, I won't use more than 4 lights at once,but why you have indices in float? should it not bejust ordinary integers?   My problem is, that my graphic card - now I haveto work on notebook, does not support shaders at all.So I must do it in old way and look for algorithm tocalculate it on CPU. What is source code for thatshader you've written me? May be I could put it toC++. ? . Or do you now algorithm in c++ directly? ThanksMartinBtw: please don't write me to buy new graphic card,I know I should - however I want my engine run evenon older graphic cards.   ;Quote:but why you have indices in float? should it not be just ordinary integers?this is because the GPU works only with floating point values, you can define an Integer , but in shader they are all converted into floating-point internally.Quote:So I must do it in old way and look for algorithm to calculate it on CPUI'm also developing my engine on my laptop graphic card which doesn't support shaders. but you can write your vertex shader and run it on software, buy passing D3DCREATE_SOFTWARE_VERTEXPROCESSING flag to "CreateDevice" . and it runs pretty fast, faster than program code for sure.but you can't emulate Pixel shaders in driver, except in REF device, which is awefully slow.I suggest you go with shaders anyway, cuz games are played on decent graphic cards and needs GPU power.you can check out the demo of my engine that I'm working in my website, currently is supports per pixel + bump, and also vertex light + bump for older cards like gf3 , gf4, and does only per vertex lighting for crappy cards like mine(laptop). but it works only on dynamic meshes, not static geometry due to performance reasons.the algorithm is something like this :you have a vertex that light indices are stored in, and you have couple of lights for the scene, the indices for each vertex points to each light in the scene.when you want to lit each vertex you read each light by :// input is a vertex ...for( int i = 0; i < MAX_INDICES; i++ ) {    Light& light = sceneLights[ vertex.lightIndices ];    // do the lighting/bump calculations for vertex ...}anyway if you want to see the code, give me your mail and I will mail you my per vertex lighting + bump mapping shader, it supports two lights, and uses the indexing method that I told you.I guess for bump mapping, in order to get the right results for multiple lights, you need at least pixel shader 1.1, but if you have only one light you can implement it with fixed function pipeline.;  Every light should affect every surface, of course.First render a pass with only ambient lighting, and normal depthbuffering enabled. Then disable z-writes and render the scene once for each light, adding the results together. This may seem like it would be slow, but with depthwriting disabled it'll only render the visible pixels.Once you start implementing shadow volumes, you'll have to render once for each light anyway.   ;  Youre gonna get that sort of lighting with per vertex.  If you subdivide all your polys it will look better, but with a greater rendering overhead.   