Can the player cast shadows from scene lights?
by Jen Garcia · in Torque Game Engine · 12/03/2004 (4:25 am) · 5 replies
I've been playing around with some ideas on how I would want my game to look, and I noticed that the player will only cast the shadow from the sun object. Scene lights will only cause buildings to cast shadows and other objects are ignored or cast only the sun shadow.
I've looked at other resources such as 'Stencil Shadows' but, although the resulting shadows are very nice, they only come from light cast from the sun.
Is there any way to change this in TGE?
**Note: this question was originally posted here but I was told to come to the SDK forums for help.
I've looked at other resources such as 'Stencil Shadows' but, although the resulting shadows are very nice, they only come from light cast from the sun.
Is there any way to change this in TGE?
**Note: this question was originally posted here but I was told to come to the SDK forums for help.
About the author
Coder, artist, and gamer.
#2
Now that I have the LightInfoList, do I have to eliminate all the code that calculates shadows the old way? Namely:
Also, I see that I'm going to have play around with all the references to mShadows now that it's an array.
Finally, how exactly do I use the information in the LightInfoList?
(BTW, I've never touched the engine code before today... Aren'tcha proud?! :)
12/03/2004 (10:14 am)
Thanks Brett. Now I have a couple of questions:Now that I have the LightInfoList, do I have to eliminate all the code that calculates shadows the old way? Namely:
// Get a real light dir... Point3F lightDir = gClientSceneGraph->getLightManager()->getShadowLightDirection(); F32 shadowLen = 10.0f * mShapeInstance->getShape()->radius; Point3F pos = mShapeInstance->getShape()->center;
Also, I see that I'm going to have play around with all the references to mShadows now that it's an array.
Finally, how exactly do I use the information in the LightInfoList?
(BTW, I've never touched the engine code before today... Aren'tcha proud?! :)
#3
12/07/2004 (2:33 am)
Uh-oh... smells like I'm gonna have to put up a 'Help Wanted' for a programmer pretty soon... :s
#4
- Brett
12/07/2004 (5:15 am)
No, you can utilize the existing code, cycling over your lightInfoList for each light, casting a new shadow object for each light. So, you might do:for (S32 light = 0; light < mShadowLights.size(); light++) {
// Get a real light dir...
Point3F pos = mShapeInstance->getShape()->center;
VectorF lightDir;
if (lightInfoList[light].mType == Light::Vector)
lightDir = lightInfoList[light].mDirection;
else {
// Get the light position, and then the image position
lightDir = pos - lightInfoList[light].mPosition;
lightDir.normalize();
}
F32 shadowLen = 10.0f * mShapeInstance->getShape()->radius;
if (mShadow[light])
mShadow[light] = new Shadow();
mShadow->prepare(pos,lightDir,shadowLen,objScale,dist,fogAmount,mShapeInstance);
...That should be about it. But, I was thinking, you can get a lot of this functionality from the Synapse Gaming Lighting Pack.- Brett
#5
12/07/2004 (5:32 am)
Actually, I was going to ask about that... I was thinking about getting it anyway to build my levels, but will it help make things easier as far as my multiple shadow problem?
Torque Owner Brett Fattori
So, you want to cast multiple shadows? Well, if you look into shadow.cc (which the players use) you will see that it doesn't know anything about the lights. What you need to do is go one level higher. Objects that cast shadows (shapeBase.cc) usually have a member object called mShadow. This one shadow object will be cast for the "sun".
Look for the call in the shapeBase rendering code (either prepRenderImage or renderObject) and you'll see it does something like (this is from memory so bear with me):
if (!mShadow) mShadow = new Shadow();That creates the instance of the shadow object. To create the shadow, we supply what light direction to use to project the shadow verts. So there's a call in there that looks like this:This supplies the light direction to the shadow generator. You could supply your own light direction. You could modify the prepare method to take a LightInfo structure rather than a direction. Then determine direction from the light itself.
If you want to cast multiple shadows, you could change the mShadow declaration (in shapeBase.h) to something like:
The LightManager has a method to determine which lights are relevant to an area in the scene. You could use this to grab the 4 most relevant lights to the character. You could also add some logic like so (this is "off the top of the head" code(tm)):
// Clear out our light list first mShadowLights.clear(); // Check to see if the sunlight is visible using a cast ray LightManager *lm = gClientSceneGraph.getLightManager(); // This assumes that light zero is the sun VectorF sunDir = lm->getLight(0).mDirection; // Cast ray from sun down to player RayInfo ri; Point3F plrPos = player.getPosition(); Point3F sunPos = plrPos + SOME_LARGE_AMOUNT * sunDir; U32 collisionMask = TerrainObjectType | InteriorObjectType; bool isSunVisible = !gClientContainer.castRay(sunPos, plrPos, collisionMask, &ri); S32 lightNum = 0; // If the sun is visible, put it into our light list to correspond // to shadow zero. if (isSunVisible) { mShadowLights.push_back(lm->getLight(0)); lightNum++; } // Expand the player's object box (not sure if this works this way) Box3F pBox = player->getWorldBox(); pBox.max += 30; pBox.min -= 30; // Now we'll use the light manager to get the closest lights lm->getBestLights(pBox, mShadowLights, (MAX_SHADOWS - lightNum));Now you'll have a LightInfoList (see scenegraph/lightManager.h) that contains all of the important lights. The sun is a vector light so it only has a direction. For point lights, they will have a position. To determine the light vector for the shadow casting, get the direction vector between the light and the player and use that.Good luck with getting multiple shadows working..
- Brett