Game Development Community

Dynamic Shadow In TGB? Yes!

by William Lee Sims · in Torque Game Builder · 08/21/2010 (3:07 am) · 46 replies

When searching around the Hardcore final level, we wanted the power-ups and enemies to be hidden behind pillars. To that end, I found an article on dynamic 2D shadows.

Because it would be too hard to inject myself into the middle of the TGB rendering, I had to modify the steps a little bit. I create an overlay that makes the scene get darker away from our hero's light source. Then, I find all of the pillars currently on the screen and create convex polygons around the main features of the pillars.

It looks pretty nice and it adds a lot of tension and exploration to the game.


My code isn't generic enough for general use, but if you want a headstart, I can send you the class and an outline of its functionality.
#21
10/30/2010 (9:31 pm)
William, Great work!! I've been really impressed by your demos. If you are still in the giving mood, I would love a copy of the source for this ... Thanks!
#22
10/30/2010 (9:42 pm)
Very cool to finally see someone use this article in relation to TGB :)

Long time since I first posted it before TGB 1.0 and its long time since it was last hot (around the TX original release I think)
#23
02/27/2011 (8:29 pm)
First, an apology to all of those people who emailed and I never got back to. Work has been taking all of my free time and I had to let something go.

Good news! In the TGB Resources, I've added the standard email that I was sending.

BE WARNED! It's very rough code. If you need help getting your objects casting shadows, feel free to post here.

Later!
#24
08/12/2011 (12:27 am)
I would like to add Dynamic Shadow to my TGB project but I need some advice because I never modify TGB before.
I have to open "Torque2D.xcodeproj" which is into engine/compilers/Xcode. After that I don't know were I have to create t2dLightMap.h and t2dLightMap.cc.
I also need compiling setting or I can only press "Run" on xCode?
#25
08/12/2011 (12:43 pm)
Wow! I can't believe I never saw this thread. I might actually have to adopt this for my own game project. Nicely done William.
#26
08/30/2011 (2:08 pm)
Boy... I haven't compiled on the Mac in well over 2 years. I can't really help you too much.

You can put those files anywhere, but you need to add them to your project. It's easier to compile and then run the new executable.
#27
01/08/2012 (10:10 am)
Looks nice and exactly as something I'd love to implement...unfortunately, I'm being unlucky so far.

Here's my procedure and it would be great if someone of those who made it work could give me a clue what am I doing wrong. I don't get any script errors so it seems "legal".

At first I recompiled both TGB and TGBGame so they include the new t2dLightMap straight away. Then I parsed this code into my level1.t2d script:

new t2dLightMap(lightMap) {
	Layer = "8";
	scenegraph = "level1scene";
	size = "1250 1250";
	};

Then I try to mount the light map within my object's onLevelLoaded() function like this:

lightMap.mount(%this, 0, 0, 0, false, true, true, false);

To test it, I placed four circle sprites around my object. Two on layer 8, one on layer 7 and one on layer 9 and made them all receive collisions and physics, yet none of them casts shadows. Any help will be greatly appreciated.
#28
01/09/2012 (10:16 am)
Ideally, I'd clean up this code to work the way you're expecting it. Unfortunately, there's a lot of manual steps you probably still need to do.

First, in the C++, make sure you change "arcadeWindow" and "ArcadeScene" to the name of your t2dSceneWindow and t2dSceneGraph names.

Second, make sure that you have the circle sprites in Group #2. You can setthis in the same area of TGB where you set the layer.

Third, in the C++, in "t2dLightMap::processObject", I assume that the object is 60 units in the scene space. (Look at the section with "60" multiplied by the sin/cos values.)

If you want to clean this up, it'd need the following changes:

1) Add a function to t2dLightMap to let the user assign the scene window.
2) Add a function to t2dLightMap to let the user assign the groups that will cast shadows.
3) Instead of building a crude circle (24-sided polygon) in "::processObject", build a polygon from the collision polygon.
#29
01/14/2012 (8:53 am)
Wow I have trying to get this one to work for quite awhile stumbled on many way to do it but couldn't get it working on TGBand kinda didn't go back to after my daughter was born. Thanks for sharing the resource man.

#30
02/22/2012 (7:32 pm)
I can't seem to get it to work. I put the code in the TGBGame folder in TGB's solution. It rebuilds just fine. I put the TorqueScript into the Player character's code so that it creates the lightmap and mounts it when the player object respawns.

However, I get the error "unable to instantiate non-conobject class t2dLightMap"
#31
02/26/2012 (7:39 pm)
Did you copy the executable to your game's directory? It'll be under TGB/gameData/T2DProject.
#32
02/26/2012 (10:55 pm)
I'm a few steps from getting this working in without source just one issue I need to work out.
#33
03/18/2012 (8:15 pm)
Ah, that explains it. I'm making progress, but now I'm getting an error: "Vector<T>::operator[] out of bounds array access." I didn't change anything to the source code other than put in my scene window and scene graph's names.
#34
03/19/2012 (8:22 pm)
Are you proficient in the debugger? Do you know which line this is happening on? I'm curious if it's from the pick list or rendering the shadow.
#35
03/20/2012 (6:52 pm)
I'm not familiar with the debugger, unfortunately.
#36
03/20/2012 (9:14 pm)
In each function you could put the following code:

Con::printf( "I'm in function XYZ..." );

in each function (and change XYZ to the function name). Let me know what's the last one to print out to the console.
#37
03/21/2012 (9:18 am)
Ah! Okay, I never worked with TGB's source before.

The array out of bounds error is happening in renderShadow(). vert is being set to -15. Looking at the code...
S32 startingVert = -999, endingVert = -999;

...

S32 vert = (startingVert + i) % verts.size();

It looks like startingVert isn't being set after its initialized as -999. There's no trap to check this condition.

Though, it makes me scratch my head. Shouldn't modulus only return a negative if the right operand is negative? But verts should never have a negative size.
#38
03/21/2012 (12:58 pm)
Is your character inside an object that would cast a shadow? While I haven't tested it, it may cause this problem. I look for the corners of the object where the shadow would start and the corner for where the shadow would end. If you were inside the shadow-caster, all edges would point away from you and there would be no start and end corners where shadows would begin and end.
#39
03/23/2012 (6:52 pm)
I went through it carefully and made there there were no internal collisions. I even tried making a much simpler level to perform further tests.

Anytime I have an object on Group 2, I get "Fatal: (d:\programs\torque 2d\engine\source\core\tvector.h @ 441) Vector<T>::operator[] - out of bounds array access!" and the value of vert is -15.

Maybe I'm missing something? What groups and layers should everything be? From what I understand, the dynamic shadow system ignores anything not on group 2 and objects with a layer less than 8 can be concealed by shadows. Is this correct?
#40
03/23/2012 (8:08 pm)
If vert is -15, I'm really stumped. Clearly vert.size() must be positive, or we would not be in the for-loop. startingVert must be assigned something other than -999, but can only be assigned positive numbers.

Your understanding is correct. Everything in group 2 should be chosen for shadow rendering (with the assumption that it is a circle). Everything below layer 8 (assuming you used my example) will be concealed by shadows.

One more idea: Where are you placing your shadow map and is it attached to anything?