sswift shadow system Q

Community Forums/Developer Stations/sswift shadow system Q

jfk EO-11110(Posted 2004) [#1]
How can I prevent the lights will cast trough walls? I have set the entitypickmode of the receiver(s) to 2, but there is still some shadows casted by a light that is behind a wall. How do I stop this? I cannot reduce the light range since the range is actually already small.

Is there a special forum for the sswift shadow system?

sswift(Posted 2004) [#2]
No, there isn't a special forum.

As for your question...

There is nothing in the system to prevent a shadow being cast from an entity from light which is behind a wall. I'm not a miracle worker. :-) I cannot just use a linepick or an entityvisible call in order to determine if a light can see an entity, because that might conflict with whatever someone is using pickmodes for, and to be quite frank, I never thought of doing it. There is no way for example to prevent a shadow from being cast though two walls, but yes, in theory you could stop a shaodw from being cast at all if the caster cannot see the light source.

I do not think it would be wise to implement such a thing in the shadow system as each game uses different methods to dtermine what is occluded and what is not, and that could be slow, or as I said, conflict with something else you want to do with linepicks.

However, if you wish to modify the system to do this check, then it should be fairly simple.

In the Update_Shadows function, you will see the following code near the start:

	; Loop through all the pairs of light sources and shadow casters.
	For ThisSet = Each Caster_Set

		; The reason we group these into sets is so that a texture can be created and maintained for each set. 
		; We don't always update the texture every frame, so we need to preserve the pointer to it.
		; We could probably perform the same operation with the meshes, however the only time a mesh be be able
		; to be retained from frame to frame would be if the caster, light source, and recevier had all stayed at
		; the same location in space between frames.
		; Implementing this would remove the need for static shadows, but would create the need to be able to specify
		; that certain light sources only affect certain caster/receiver pairs.

		; It is also tempting because removing the need for static shadows would remove the need to have two copies
		; of most of the below code, one for regular shadows and one for static shadows.

		ThisLight.Light_Caster   = ThisSet\Light
		ThisCaster.Shadow_Caster = ThisSet\Caster		

After this, ThisLight\Entity and ThisCaster\Entity hold the pointers to the entities that you are positioning in your world for each. Right after this code, you can just stick a check to see if they can see eachother with entityvisible, or linepick, whichever pleases you. If they can't see eachother then skip all the rest of the code in the loop and allow the loop to proceed to the next caster set.

You may get better performance however if you move this check a little bit further down in the code. Immediately after the above, there is a check to see if the distance between the light and caster is too great. This check is probably quite a bit faster than an entityvisible check, so you could put the entityvisible check AFTER the distance check so that you cull as many lights/caster pairs as possible just based on distance.

jfk EO-11110(Posted 2004) [#3]
Ok, thanks for that tip!

poopla(Posted 2004) [#4]
On the subject, does your system only handle spot lights? Or will it do omni? If it does omni, how are you managing the texture generation for that?

sswift(Posted 2004) [#5]

My system uses a hybrid light source that behaves like an omni light.

Basically, I point the light's camera at each object, and render a texture. Then I project that texture onto the surfaces behind the object.

So it is as if each light is actually a bunch of spotlights, one pointed at each nearby object that casts a shadow.

I do this because it's efficient. It allows high res shadows, with little overdraw.

jfk EO-11110(Posted 2004) [#6]
Yes, works great. Just added
If EntityVisible(ThisLight\Entity, ThisCaster\Entity)
right after the line
If Light_To_Caster_Distance# <= ...
(that's line 772 here, but I made some modifications, so it may be somewhere around 772)

The only problem is now for example when a caster is walking behind a row of columns, his shadow switches on and off everytime a column is obscuring sight to the light source. Especially since EntityVisible checks only the center of the entity, and also because the lightmap has very soft shadows compared to the realtime shadows, but hey, nobody's perfect. Before I thougt it looks wrong when they STILL got shadows, regardless if they are standing in the shadow of eg. a column.
This method isn't too slow, the loss of speed trough EntityVisible is partially compensated by the saving of lightcasting of obscured lights.

Thanks for the help!

sswift(Posted 2004) [#7]
"The only problem is now for example when a caster is walking behind a row of columns, his shadow switches on and off everytime a column is obscuring sight to the light source."

If you don't want columns to block the light, then you'll have to make the columns a sepetate mesh that cannot block line of sight.

The shadow system does have the ability to blur shadows, at a cost. Look at the global variables. It's not perfect, but it is hardware accelerated, and it might make the shadows match your lightmaps a little better.

jfk EO-11110(Posted 2004) [#8]
I know, but I am already at the limit concerning framerate.

It's not that bad with the columns, and it would comlicate the engine too much since currently the whole static part is one Mesh, this also saves surfaces.

But anyway, I modded your system in a lot of ways. It is now using a copy of the level mesh that consists only the Tris that are near the player. This hidden (singlesurface) copy is frequently created clusterwise. The engine also dynamicly creates lightemitter, depending on the Character locations. I see, it works pretty good with one light in a scene, also with multiple Casters, but as soon as there are 2 or 3 light that are affecting one or more Character, the Framerate goes real down. So the conclusion is: Create the lights of a level with the realtime lighting system in mind, never position multiple lights too close to one another, unless you won't use them for realtime rendered shadows. At least it was pretty easy to extract the light positions from a gile[s] exported mesh, so maybe I only need to go back to giles and edit the lights. (which is an other issue due to unique loading and redering times of the 2k lightmapsize on a weak machine)

I am still trying to make hte shadows faster. I wonder how they did the shadow system of the hitman 2 engine (something similar, but faster).

jfk EO-11110(Posted 2004) [#9]
Darn, it's gettin tricky. The camera entity is breaking trough the ceil when the player is crawling trough aircondition shafts and other small gangways. The camera (head) has its own collision because using one COllision radius only for the whole player would require to alter the collisionradius of it at runtime due to crouching, and this would result in fall-trough floor artifacts, which is even worse than breaking trough the ceil.

I am really stuck with this problem. I can deactivate the realtime shadows by hitting f10, and then it works without any problems.

Even when I shoot all casting Chars and their casters are removed and the framerate rises to the same like when realtime shadow are turned off, this still happens. So now I guess it's not the framerate. I also checked if the shadow include file does alter the entitytype of radius of the camera, but that's not the problem.

I simply can't track this bug down. Any ideas?

sswift(Posted 2004) [#10]
I don't understand the question.

jfk EO-11110(Posted 2004) [#11]
What could cause this behaviour of the camera entity? It works without the realtime shadow system, but doesn't when it's turned on. It feels like collision of the camera isn't handled anymore, but I explicitely reset the entitytype of the camera right after the UpdateShadows call, to make sure it is set correctly.

jfk EO-11110(Posted 2004) [#12]
Ok, nailed the sucker. Inside the UpdateShadows Function you need to:

HideEntity Current_Camera
CameraProjMode Current_Camera, 0

ShowEntity Current_Camera
CameraProjMode Current_Camera, 1

The sucker took me about 10 Hours so far. Hideentity performs some kind of Updateworld with hidden (thus collision off) state.

I have to say, I made the Shadow_cam global and mabe it to be created only once at startup, and then only hide and show it inside the UpdateShadows function. Maybe this causes this bugous behaviour.

However, I thought it should work with two cameras by hiding and showing then depending on usage. But it doesn't! So note: use CameraProjMode instead of HideEntity for the Cameras!

sswift(Posted 2004) [#13]
Why did you change code which didn't need to be changed? If the creating and deleting of a camera isn't causing problems, I don't see why you changed that. :-P

I'll consider making the change you suggested to the system, but I would like to know if what you changed caused this problem. I doubt it did. You are probably right that hiding the camera even temporarily causes Blitz to mess up the collision stuff.

jfk EO-11110(Posted 2004) [#14]
Yes, I think so too it doesn't have anything to do with the Shadow_Cam at all, I just mentioned it to be fair.

Basicly I try to avoid to continously create and delete things because this almost every time leads to resource fragmentation.

I hardly suggest to use CameraProjMode since hideentity REALLY kills the current position and positions the entity where it would be without collision, even when you don't call UpdateWorld, and CameraProjMode leaves the position intact, and it's also faster, from what the docs say.

sswift(Posted 2004) [#15]
As for the speed, the docs are out of date. Mark fixed hiding entities so it's instant now.