Realistic Real-Time Fast Flat  Shadow Using Fog Shadows
How to

Principal

Shadows always add realism to our scene , here I explain about how to do it and how to apply it to your scene casting a character shadow , this technique is a good idea to apply for directional light , you don't need know the mesh structure data , and you can apply it in only one pas to you scene without project the texture , you only need build a square and apply the texture to it.

I use OpenGL ,C++ under GNU/Linux to explain this technique , all images are from my personal project at Black-Legacy.com

We can cast a fast flat shadow from a directiona light using our object like a shadow stencil, but we can use the wrap object texture to cast a realistic shadow



shadow from object 1
object shadow
These images have a Object shadow, left image you can see the model without texture and the right image have a texture using transparecy , but the shadow is a object shadow, We need Texture shadow to cast also the transparency.

To do it , follow the next steps:

* Clear Framebuffer using glcolor (1110) ,because later we do White color as tranparence.
* Place a camera on light position , camera are lookin to our object
* Draw your object.
* Get Framebuffer (using glCopyTexSubImage2D )like a texture and pace it down our object.
* Every Frame.

  glClearColor(1,1,1,0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f,(GLfloat)wwwn/(GLfloat)whwn, 5.0f ,4000.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(  Light_posX, Light_posY,Light_posZ,     ObjectX,ObjectY, ObjectZ,         0, 1, 0);

  DRAW YOUR OBJECT(IMPORTAN DRAW YOUR OBJECT USING TEXTURES AND TRANSPARENCES PROPERTIES IF REQUIERED)

  glBindTexture(GL_TEXTURE_2D, ShadowMapTexture);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,256,256, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (ScreenResolutionWn/2)-128, (ScreenResolutionWh/2)-128, 256, 256);

---------------------------
 DRAW YOUR SCENE AND PLACE A SQUARE DOWN OUR OBJECT.



 
     
Without transparece







We optain a similar image , but in these image shadow
is black , really we get a collored image.
Now We need apply glBlendFunc filters to convert white
color into transparent color, Just enable  Blend and Alpha Test
after drow the square down our object. And draw the square White as possible.


Note these function draw MY square , sure you need change it.

 glEnable(GL_TEXTURE_2D);
 glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
 glAlphaFunc(GL_GREATER, 0.9);
 glTranslatef(ObjectX,ObjectY, ObjectZ);

 glBlendFunc(GL_DST_COLOR, GL_ZERO);
 glBindTexture(GL_TEXTURE_2D, ShadowMapTexture); // shadowMapTexture is my texture name
 glColor4f(1,1,1,0.003);
 glBegin(GL_QUADS);
 glTexCoord2f(1.0f, 1.0f); glVertex3f(-7,0,-7);
 glTexCoord2f(0.0f, 1.0f); glVertex3f(-7,0,7);
 glTexCoord2f(0.0f, 0.0f); glVertex3f(7,0,7);
 glTexCoord2f(1.0f, 0.0f); glVertex3f(7,0,-7);
 glEnd();
 glPopMatrix(); 

mirror





Now white square is transparent and que can see our shadow, but this shadows is a  colored shadow, usefull for a mirror, sure , and for a reflective water, sure. But not for a shadow, We need delete the color or get only 2 colors , these is more easy option, Only need chane one data on our code to get gray scale.
Look for this line:
  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,256,256, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Change Red data to 1 ,like
glTexImage2D(GL_TEXTURE_2D, 0,1,256,256, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Now We get our image, but only grey color.






glass







These are the new image, now shadow have grey scale
,this is good for glass objects ,sure, and for ice objects
sure , perhaps is good for a invisibility ,but not for a shadow , we need a grey unifor shadow, and  to do it
We need conver our texture to Black texture, How,
After you draw the object to get it, select drawing color to Black , and disable light.

 glClearColor(1,1,1,0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f,(GLfloat)wwwn/(GLfloat)whwn, 5.0f ,4000.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(  Light_posX, Light_posY,Light_posZ,     ObjectX,ObjectY, ObjectZ,         0, 1, 0);

   glDisable(GL_LIGHTING);                             
   glColor4f(0,0,0,1)

  DRAW YOUR OBJECT (IMPORTAN DRAW YOUR OBJECT USING TEXTURES AND TRANSPARENCES PROPERTIES IF REQUIERED)

  glBindTexture(GL_TEXTURE_2D, ShadowMapTexture);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0,1,256,256, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (ScreenResolutionWn/2)-128, (ScreenResolutionWh/2)-128, 256, 256);

---------------------------
 DRAW YOUR SCENE AND PLACE A SQUARE DOWN OUR OBJECT.

 
Cero colour




A unifor shadow, but very hard , this shadow is good for a very strong light
near to our objects, but We don cant change our glcolor (0,0,0) to other grey
scale color because we return to glass shadow, Then we can use stencil buffer
to compare a our object and a  grey square  and only get the portion of the .....
Yes we can do it , is a hard way and stencyl buffer is a slow buffer , and
 need 32 colours bit.
More easy enable FOG , we can create a very hard gray fog, Shadow will be smooth like
 Fog as White. Now We can adjust our shadow smooth using the Fog colour.

  GLfloat fogColor[4]= {0.65f, 0.65f, 0.65f, 1.0f};
  glFogi(GL_FOG_MODE, GL_EXP);   
  glFogfv(GL_FOG_COLOR, fogColor);
  glFogf(GL_FOG_DENSITY, 0.35f);    
  glHint(GL_FOG_HINT, GL_DONT_CARE);         
  glFogf(GL_FOG_START, 1.0f);                
  glFogf(GL_FOG_END, 5.0f);       
  glClearColor(1,1,1,0);
  glEnable(GL_FOG);                        

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f,(GLfloat)wwwn/(GLfloat)whwn, 5.0f ,4000.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(  Light_posX, Light_posY,Light_posZ,     ObjectX,ObjectY, ObjectZ,         0, 1, 0);

   glDisable(GL_LIGHTING);                             
   glColor4f(0,0,0,1)

  DRAW YOUR OBJECT (IMPORTAN DRAW YOUR OBJECT USING TEXTURES AND TRANSPARENCES PROPERTIES IF REQUIERED)

  glBindTexture(GL_TEXTURE_2D, ShadowMapTexture);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0,1,256,256, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (ScreenResolutionWn/2)-128, (ScreenResolutionWh/2)-128, 256, 256);

---------------------------
 DRAW YOUR SCENE AND PLACE A SQUARE DOWN OUR OBJECT.

DON'T FORGET RESTORE YOUR ALPHA ,BLEND , FOG and LIGHT PROPERTIES


Final


And this is the final result , a Realistic Real-Time Fast Flat Shadow,
Flat shadow is a good way to apply shadow for a chjaracter, or other
 objects , but flat shadow don't have relief properties, You need Volumetric,Stencil or projective shadow to create relief shadow effect.

Luckyly this fog shadow have addidtion properties,and have really fast
to render it and look nice, I develop this shadow estyle to use it on my personal project Black Legacy . feel free to test it!!

I develop the FOG SHADOW idea and To avoid every one  get a fuck
copyright from this idea , I do IT GPL
ADD
                                                           Addition properties

www.Sorgonet.com
moc.tenogroS@_orceN