Fixes to get shadowing working ... enjoy!
by Melv May · in Torque Game Engine · 06/13/2003 (2:02 pm) · 58 replies
Guys,
I've noticed a few people struggling to get shadowing working correctly but being as I've already fixed it but just not had the time to get it into the CVS, I thought I'd at least give you the fixes here. Sorry I didn't do this earlier, it's just that our game is taking almost every hour of my freetime.
Anyway, here's how to do it and I will endeavour to get it into the [HEAD] soon. Note that you can scroll down to the bottom if you're not interested in the reasoning and copy the whole functions into the SDK.
First, in "shapebase.h" around line 916, change the levels to something like...
The next problem you will encounter is that shapes with translucency get skipped. You can force it to render these shapes such as the stock trees but you may get artifacts. If you want to stop this then you can amend the line in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)" around line 311 to...
The next two amendments allow you to change the behaviour of the shadows. Since statics don't move or animate, the shadows are set to non-moving/animating. This produces a higher-performance shadow but doesn't animate when you move it in the editor. You may also want to amend this behaviour dynamically as mentioned by Robert Blanchet here. It's a total choice for you but you can amend this functionality by editing two lines in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)", namely...
The next problem is the incorrect reference to the Obj->World transform. Brett Fattori mentions one of these here but there is another on line 331 where the position is transformed into world-space.
Because there are numerous problems in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)", here is the whole function with dynamic shadows turned-on. Be careful with dynamic shadows if you've got lots of statics that don't need it. It could be made to be a $Prefs option that you can turn-on/off at will I guess.
Next up is the function "void TSStatic::renderObject(SceneState* state, SceneRenderImage* image)". This is so wrong! I'll let you work out what I changed so here's the whole thing...
Enjoy.
- Melv.
I've noticed a few people struggling to get shadowing working correctly but being as I've already fixed it but just not had the time to get it into the CVS, I thought I'd at least give you the fixes here. Sorry I didn't do this earlier, it's just that our game is taking almost every hour of my freetime.
Anyway, here's how to do it and I will endeavour to get it into the [HEAD] soon. Note that you can scroll down to the bottom if you're not interested in the reasoning and copy the whole functions into the SDK.
First, in "shapebase.h" around line 916, change the levels to something like...
#define StaticShape_GenericShadowLevel 0.4f #define StaticShape_NoShadowLevel 0.01f
The next problem you will encounter is that shapes with translucency get skipped. You can force it to render these shapes such as the stock trees but you may get artifacts. If you want to stop this then you can amend the line in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)" around line 311 to...
if (mShapeInstance->getShape()->subShapeFirstTranslucentObject.empty()/* || mShapeInstance->getShape()->subShapeFirstTranslucentObject[0]==0*/) return;
The next two amendments allow you to change the behaviour of the shadows. Since statics don't move or animate, the shadows are set to non-moving/animating. This produces a higher-performance shadow but doesn't animate when you move it in the editor. You may also want to amend this behaviour dynamically as mentioned by Robert Blanchet here. It's a total choice for you but you can amend this functionality by editing two lines in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)", namely...
mShadow->setMoving(true); mShadow->setAnimating(true);
The next problem is the incorrect reference to the Obj->World transform. Brett Fattori mentions one of these here but there is another on line 331 where the position is transformed into world-space.
Because there are numerous problems in "void TSStatic::renderShadow(F32 dist, F32 fogAmount)", here is the whole function with dynamic shadows turned-on. Be careful with dynamic shadows if you've got lots of statics that don't need it. It could be made to be a $Prefs option that you can turn-on/off at will I guess.
void TSStatic::renderShadow(F32 dist, F32 fogAmount)
{
if (Shadow::getGlobalShadowDetailLevel()<StaticShape_NoShadowLevel)
return;
if (mShapeInstance->getShape()->subShapeFirstTranslucentObject.empty()/* || mShapeInstance->getShape()->subShapeFirstTranslucentObject[0]==0*/)
return;
// for safety, since I can't yet guarantee when this gets called.
dglNPatchEnd();
if (!mShadow)
mShadow = new Shadow();
mShadow->setGeneric(Shadow::getGlobalShadowDetailLevel() < StaticShape_GenericShadowLevel);
// The following set to TRUE slows things down but you can also see the changes to shadows
// immediately within the editor.
mShadow->setMoving(true); // MM: Set this to false to improve performance.
mShadow->setAnimating(true); // MM: Set this to false to improve performance.
Point3F lightDir(0.57f,0.57f,-0.57f);
F32 shadowLen = 3.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);
getRenderTransform().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);
mShadow->renderToBitmap(mShapeInstance,getRenderTransform(),pos,mObjScale);
mShadow->endRenderToBitmap();
}
mShadow->render();
}Next up is the function "void TSStatic::renderObject(SceneState* state, SceneRenderImage* image)". This is so wrong! I'll let you work out what I changed so here's the whole thing...
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) / 350;
if (projected < (1.0 / 16.0))
{
TextureManager::setSmallTexturesActive(true);
}
}
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
dglMultMatrix(&mObjToWorld);
glScalef(mObjScale.x, mObjScale.y, mObjScale.z);
dglNPatchBegin();
// RENDER CODE HERE
mShapeInstance->setEnvironmentMap(state->getEnvironmentMap());
mShapeInstance->setEnvironmentMapOn(true,1);
mShapeInstance->setAlphaAlways(1.0);
Point3F 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();
dglNPatchEnd();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
renderShadow(dist,fogAmount);
TSShapeInstance::smNoRenderNonTranslucent = false;
TSShapeInstance::smNoRenderTranslucent = false;
TextureManager::setSmallTexturesActive(false);
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");
}Enjoy.
- Melv.
About the author
#3
these two lines:
mShadow->setMoving(true);
mShadow->setAnimating(true);
does drop framerate by quite a bit so I might have to leave those set to false until I get a new laptop to work on :)
06/13/2003 (2:47 pm)
Very nice Melv! It seems to give the entire game a slightly different appearance when I tried it out. I'm betting the game you're working on will be kick-ass. Best of luck with it.these two lines:
mShadow->setMoving(true);
mShadow->setAnimating(true);
does drop framerate by quite a bit so I might have to leave those set to false until I get a new laptop to work on :)
#4
Bad Melv :) I'll have to redesign all ! Naw, with those 2 lines set to false, it's wonderfull.
Thanks again and again Melv !
06/13/2003 (3:06 pm)
Wowy ! My levels are now unplayable but ... they look awesome !Bad Melv :) I'll have to redesign all ! Naw, with those 2 lines set to false, it's wonderfull.
Thanks again and again Melv !
#5
God help me, if I EVER finish this damn game, at the end of the credits it's going to read "Special Thanks: " and in letters taking up the whole screen, "MELV MAY".
It's so freaky. You and Joshua Ritter seem to release resources like this about two hours before I was planning to ruin a few copies of my game trying to do it myself.
Thanks again, Melv!
06/13/2003 (4:56 pm)
Dude, how many times have I said that you're the man?! MELV IS DA MAN!!God help me, if I EVER finish this damn game, at the end of the credits it's going to read "Special Thanks: " and in letters taking up the whole screen, "MELV MAY".
It's so freaky. You and Joshua Ritter seem to release resources like this about two hours before I was planning to ruin a few copies of my game trying to do it myself.
Thanks again, Melv!
#6
06/13/2003 (5:10 pm)
This is great. Thanks Melv.
#7
Don't forget that for performance, you can also tweak the StaticShape_GenericShadowLevel and the StaticShape_NoShadowLevel for best performance.
Tweaking these defines results in a big recompile so you could easily add some fields into the respective objects in consoleInit to handle this dynamically rather than change/build/run.
Also, use the script call setShadowDetailLevel(val 0...1); (which stores itself in $pref::Shadows) to change the global shadow level dynamically. This is compared against the ..._GenericShadowLevel each frame and produces a generic shadow rather than the hull-shadow you see and results in a major performance boost.
As always with things like shadowing, you can get great results and tweak good performance but it's much easier to bugger-up your levels with wrong settings and get 5fps. ;)
I'm hoping to bring you guys alot of the performance objects I've created for our game Strategem after its release. We can potentially have 256 animated models on the screen at the same time (although 60-100 is average) and so a fast, efficient LOD shape blitter was called for.
Enjoy guys,
- Melv.
06/14/2003 (1:20 am)
Thanks guys,Don't forget that for performance, you can also tweak the StaticShape_GenericShadowLevel and the StaticShape_NoShadowLevel for best performance.
Tweaking these defines results in a big recompile so you could easily add some fields into the respective objects in consoleInit to handle this dynamically rather than change/build/run.
Also, use the script call setShadowDetailLevel(val 0...1); (which stores itself in $pref::Shadows) to change the global shadow level dynamically. This is compared against the ..._GenericShadowLevel each frame and produces a generic shadow rather than the hull-shadow you see and results in a major performance boost.
As always with things like shadowing, you can get great results and tweak good performance but it's much easier to bugger-up your levels with wrong settings and get 5fps. ;)
I'm hoping to bring you guys alot of the performance objects I've created for our game Strategem after its release. We can potentially have 256 animated models on the screen at the same time (although 60-100 is average) and so a fast, efficient LOD shape blitter was called for.
Enjoy guys,
- Melv.
#8
Thanks. Great infos there. I'll try to tweak it. And again, can't wait to see all those goodies in your game :) On another topic, do you have a guiMirror (like guiViewport, but mirrored) somewhere on you HD to drop my way, huh ? Well, just in case :)
06/15/2003 (1:43 am)
Melv,Thanks. Great infos there. I'll try to tweak it. And again, can't wait to see all those goodies in your game :) On another topic, do you have a guiMirror (like guiViewport, but mirrored) somewhere on you HD to drop my way, huh ? Well, just in case :)
#9
You're welcome. I've been working on the game now for nearly 6 months and it still gets me excited to work with it. We can't wait to release it unto the world!
With regards to guiViewport, that is a control that shows you a rotate view around the player. Technically this isn't a mirrored view. Is it an exact mirror that you require like in a car racing game?
- Melv.
06/15/2003 (1:51 am)
Gilles,You're welcome. I've been working on the game now for nearly 6 months and it still gets me excited to work with it. We can't wait to release it unto the world!
With regards to guiViewport, that is a control that shows you a rotate view around the player. Technically this isn't a mirrored view. Is it an exact mirror that you require like in a car racing game?
- Melv.
#11
I've made the trivial amendments to the GuiViewport and called it the GuiMirrorPort. Note that I've left the transform open so that you can mirror around any/all axis.
Enjoy,
- Melv.
06/15/2003 (5:12 am)
Gilles,I've made the trivial amendments to the GuiViewport and called it the GuiMirrorPort. Note that I've left the transform open so that you can mirror around any/all axis.
Enjoy,
- Melv.
#include "sceneGraph/sceneGraph.h"
#include "game/gameConnection.h"
#include "console/consoleTypes.h"
#include "terrain/sky.h"
#include "gui/guiTSControl.h"
class GuiMirrorPort : public GuiTSCtrl
{
private:
typedef GuiTSCtrl Parent;
virtual void renderScene(const RectI &){};
void renderWorld(const RectI & updateRect);
public:
GuiMirrorPort() {};
bool processCameraQuery(CameraQuery * query);
DECLARE_CONOBJECT(GuiMirrorPort);
};
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiMirrorPort);
//------------------------------------------------------------------------------
void GuiMirrorPort::renderWorld(const RectI & updateRect)
{
// Set-up OpenGL for a scene render.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClear(GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glMatrixMode(GL_MODELVIEW);
dglSetCanonicalState();
// Render Client Scene Graph.
gClientSceneGraph->renderScene();
// Disable Depth Test.
glDisable(GL_DEPTH_TEST);
}
//------------------------------------------------------------------------------
bool GuiMirrorPort::processCameraQuery(CameraQuery * query)
{
// Get Game Connection.
GameConnection* pConnection = dynamic_cast<GameConnection *>(NetConnection::getServerConnection());
// Did we get the connection?
if (pConnection)
{
// Yes, so get control camera transform.
if (pConnection->getControlCameraTransform(0.032, &query->cameraMatrix))
{
// Set Near/Far Planes.
query->nearPlane = 0.1;
// Fetch Sky.
Sky* pSky = gClientSceneGraph->getCurrentSky();
// If we've got the sky then use its visible distance field.
if (pSky)
{
// Get Visible Distance.
query->farPlane = pSky->getVisibleDistance();
}
else
{
// Set default Distance.
query->farPlane = 1000.0f;
}
// Fetch Camera FOV.
F32 cameraFov;
if(!pConnection->getControlCameraFov(&cameraFov))
return(false);
// Set Camera FOV.
query->fov = mDegToRad(cameraFov);
// Create Mirror Transform.
MatrixF MirrorXForm(true);
MirrorXForm.setColumn(0, Point3F(-1,0,0));
MirrorXForm.setColumn(1, Point3F(0,-1,0));
//MirrorXForm.setColumn(2, Point3F(0,0,1));
// Flip Camera.
query->cameraMatrix.mul(MirrorXForm);
// Return OK.
return(true);
}
}
// Return Error.
return(false);
}
#12
I can't beleive it ! Man, you're great ! Thanks a million ! I own you another one :) Thanks, thanks, thanks !
06/15/2003 (5:24 am)
Melv,I can't beleive it ! Man, you're great ! Thanks a million ! I own you another one :) Thanks, thanks, thanks !
#14
06/16/2003 (9:41 am)
Thanks from me as well Melv. Today is my birthday and putting this resource into my game was my present. Your a peach.
#15
I've downloaded the .rar.
I've applyed the terrainmanager.patch inside the archive.
It builds correctly but the game crashes on load.
I's my foult or I need to apply the rest of patches in order
of see game working.
06/24/2003 (4:12 am)
Please help a newbee...I've downloaded the .rar.
I've applyed the terrainmanager.patch inside the archive.
It builds correctly but the game crashes on load.
I's my foult or I need to apply the rest of patches in order
of see game working.
#16
What .rar? patch?
What has this got to do with my shadow fixes?
- Melv.
06/24/2003 (5:08 am)
Errr,What .rar? patch?
What has this got to do with my shadow fixes?
- Melv.
#17
06/24/2003 (6:34 am)
Lol :)
#18
this rar....the patch file on the gorpe site.
06/25/2003 (6:46 am)
Http://www.gorpe.com/source/TerrainManager_18.rarthis rar....the patch file on the gorpe site.
#19
- Melv.
06/25/2003 (7:27 am)
Again ... what has this got to do with this thread on SHADOWING????- Melv.
#20
The patch you downloaded is for the Terrain Manager, which is completely unrelated to this topic, which is for enabling shadowing.
Use the search feature on the forums for the Terrain Manager and you will find the correct thread.
Alternatively, join the GarageGames IRC channel #garagegames on irc.maxgaming.net. You may or may not find the current maintainer of the Terrain Manager, J Donovan Stanley there.
06/25/2003 (8:17 am)
Earth calling elettrozero, earth calling elletrozero.The patch you downloaded is for the Terrain Manager, which is completely unrelated to this topic, which is for enabling shadowing.
Use the search feature on the forums for the Terrain Manager and you will find the correct thread.
Alternatively, join the GarageGames IRC channel #garagegames on irc.maxgaming.net. You may or may not find the current maintainer of the Terrain Manager, J Donovan Stanley there.
Torque Owner Leslie Young