Game Development Community

Problems enabling shadows on TSStatics

by Manoel Neto · in Torque Game Engine · 12/14/2005 (10:19 am) · 3 replies

I got our TSStatics to cast player-style shadows, based on an old forum thread by Melv, and added a field variable so I can toggle shadows on/off on individual shapes. But I'm having a problem with the shadows projected on interiors.

On most of my models the shadows will disappear from the interiors' surface at certain camera positions/angles, while still looking fine on the terrain. If I move the camera so I can see through the interiors' walls I can see the shadow *is* there, but it's only being drawn facing inwards the interior brush. The player shadow is always drawn in both sides of the surfaces it's cast upon.

I tried debugging the shadow geometry bulding functions, but had no luck. Nothing in the shadow partitions seems to be different when the shadow is visible and when it's not. I further gave up debugging the shadow, since the shapeBase shadows go through the same path and it bears no problems. If I place the same shapes on the mission, but using a StaticShape with a datablock it's shadow will never flicker, ever. But using StaticShapes is out of question, since they bring uneeded overhead and I can't replicate them.

Right now I'm clueless to why the TSStatic shadows flicker and the ShapeBase ones don't. Here is my TSStatic::renderObject() and TSStatic::renderShadow() (where the significant modifications were done), maye someone can help me.

#1
12/14/2005 (10:20 am)
...continuing:

TSStatic::renderObject()
void TSStatic::renderObject(SceneState* state, SceneRenderImage* image)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   if (!DetailManager::selectCurrentDetail(mShapeInstance))
      // we were detailed out
      return;

   RectI viewport;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   dglGetViewport(&viewport);

   installLights();

   // Uncomment this if this is a "simple" (non-zone managing) object
   state->setupObjectProjection(this);

   // This is something of a hack, but since the 3space objects don't have a
   //  clear conception of texels/meter like the interiors do, we're sorta
   //  stuck.  I can't even claim this is anything more scientific than eyeball
   //  work.  DMM
   F32 axis = (getObjBox().len_x() + getObjBox().len_y() + getObjBox().len_z()) / 3.0;
   F32 dist = (getRenderWorldBox().getClosestPoint(state->getCameraPosition()) - state->getCameraPosition()).len();
   if (dist != 0)
   {
      F32 projected = dglProjectRadius(dist, axis) / 25;
      if (projected < (1.0 / 16.0))
      {
         TextureManager::setSmallTexturesActive(true);
      }
   }
   
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
   dglMultMatrix(&getRenderTransform());//PRLD_BETTER_SHADOWS //dglMultMatrix(&mObjToWorld);
   glScalef(mObjScale.x, mObjScale.y, mObjScale.z);




   // RENDER CODE HERE
   mShapeInstance->setEnvironmentMap(state->getEnvironmentMap());
   mShapeInstance->setEnvironmentMapOn(true,1);
   mShapeInstance->setAlphaAlways(1.0);

   Point3F cameraOffset;
   //PRLD_BETTER_SHADOWS
   getRenderTransform().getColumn(3,&cameraOffset); //mObjToWorld.getColumn(3,&cameraOffset);


   cameraOffset -= state->getCameraPosition();
   dist = cameraOffset.len();
   F32 fogAmount = state->getHazeAndFog(dist,cameraOffset.z);

   if (image->isTranslucent == true)
   {
      TSShapeInstance::smNoRenderNonTranslucent = true;
      TSShapeInstance::smNoRenderTranslucent    = false;
   }
   else
   {
      TSShapeInstance::smNoRenderNonTranslucent = false;
      TSShapeInstance::smNoRenderTranslucent    = true;
   }

   mShapeInstance->setupFog(fogAmount,state->getFogColor());
   mShapeInstance->animate();
   mShapeInstance->render();

   glMatrixMode(GL_MODELVIEW);
   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV
   glPopMatrix();

   //PRLD_BETTER_SHADOWS
   if (mRenderShadow)
	   renderShadow(dist,fogAmount);

   TSShapeInstance::smNoRenderNonTranslucent = false;
   TSShapeInstance::smNoRenderTranslucent    = false;
   TextureManager::setSmallTexturesActive(false);

   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV
   //  glMatrixMode(GL_MODELVIEW);
   //  glPopMatrix();   

   uninstallLights();
   dglSetCanonicalState();

   if (GameBase::gShowBoundingBox) {
      glDisable(GL_DEPTH_TEST);
      Point3F box;
      glPushMatrix();
      dglMultMatrix(&getTransform());
      box = (mObjBox.min + mObjBox.max) * 0.5;
      glTranslatef(box.x,box.y,box.z);
      box = (mObjBox.max - mObjBox.min) * 0.5;
      glScalef(box.x,box.y,box.z);
      glColor3f(1, 0, 1);
      ShapeBase::wireCube(Point3F(1,1,1),Point3F(0,0,0));
      glPopMatrix();

      glPushMatrix();
      box = (mWorldBox.min + mWorldBox.max) * 0.5;
      glTranslatef(box.x,box.y,box.z);
      box = (mWorldBox.max - mWorldBox.min) * 0.5;
      glScalef(box.x,box.y,box.z);
      glColor3f(0, 1, 1);
      ShapeBase::wireCube(Point3F(1,1,1),Point3F(0,0,0));
      glPopMatrix();
      glEnable(GL_DEPTH_TEST);
   }



   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   dglSetViewport(viewport);

   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}
#2
12/14/2005 (10:20 am)
Last part:

TSStatic::renderShadow
void TSStatic::renderShadow(F32 dist, F32 fogAmount)
{
   if (Shadow::getGlobalShadowDetailLevel()<StaticShape_NoShadowLevel)
      return;
   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV   
   //if (mShapeInstance->getShape()->subShapeFirstTranslucentObject.empty()/* || mShapeInstance->getShape()->subShapeFirstTranslucentObject[0]==0*/)
   //   return;

   if (!mShadow)
      mShadow = new Shadow();
   mShadow->setGeneric(Shadow::getGlobalShadowDetailLevel() < StaticShape_GenericShadowLevel);
   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV
   // The following set to TRUE slows things down but you can also see the changes to shadows
   // immediately within the editor.
   mShadow->setMoving(false); // MM: Set this to false to improve performance.
   mShadow->setAnimating(false); // MM: Set this to false to improve performance.
   
   //Point3F lightDir = gClientSceneGraph->getLightManager()->getShadowLightDirection();
#ifdef SG_ADVANCED_DYNAMIC_SHADOWS
   Point3F lightDir = gClientSceneGraph->getLightManager()->sgGetShadowLightDirection(this);
#else
   Point3F lightDir = gClientSceneGraph->getLightManager()->getShadowLightDirection();
#endif

   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV
   F32 shadowLen = 4.0f * mShapeInstance->getShape()->radius; //F32 shadowLen = 10.0f * mShapeInstance->getShape()->radius;
   Point3F pos = mShapeInstance->getShape()->center;
   // this is a bit of a hack...move generic shadows towards feet/base of shape
   if (Shadow::getGlobalShadowDetailLevel() < StaticShape_GenericShadowLevel)
      pos *= 0.5f;

   pos.convolve(mObjScale);
   //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV
   getRenderTransform().mulP(pos); //mObjToWorld.mulP(pos);

   // pos is where shadow will be centered (in world space)
   mShadow->setRadius(mShapeInstance,mObjScale);
   if (!mShadow->prepare(pos,lightDir,shadowLen,mObjScale,dist,fogAmount,mShapeInstance))
      return;

   F32 maxScale = getMax(mObjScale.x,getMax(mObjScale.y,mObjScale.z));

   if (mShadow->needBitmap())
   {
      mShadow->beginRenderToBitmap();
	  mShadow->selectShapeDetail(mShapeInstance,dist,maxScale, 0);
	  //PRLD_STATIC_SHAPE_SHADOWS_BY_MELV	  
      mShadow->renderToBitmap(mShapeInstance,getRenderTransform(),pos,mObjScale);//mShadow->renderToBitmap(mShapeInstance,mObjToWorld,pos,mObjScale);
      mShadow->endRenderToBitmap();
   }
   
   mShadow->render();
}
#3
12/15/2005 (3:30 pm)
@Manoel, I tried the same approach and got the same results. Perhaps this is a better way?