Gah - a solution with more questions. – EntropicLqd

Legacy:Sourced Player Shadows

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search


I put together a map to try to track down the cause of the bugs that have shown up. Read about it here, and try it if you have a second.

Foxpaw: I didn't really follow that checklist you made but I tested lots of stuff anyway.. I'm not quite sure the exact terminology because I haven't experimented with the classes, I just downloaded the demo map to see if I could help you find the bugs. :P Anyways, here were my observations: (I supercompressed the JPEGs, so the image quality is very poor, but it should still be enough to illustrate the bug.)

  • The area with the three squares on the wall with the A shadows spinning around, the Scripted Shadow/Static Mesh and Scripted Shadow/BSP flickered at some angles. There was a discernable pattern in the flickering, which varies based on the angle. The Shadow Bitmap square did not flicker.
  • Switching tasks while playing causes the shadows to be garbled upon switching back. This rectifies itself in the next tick. This affects both the wall shadows and player shadows.
  • The square/sphere combo shadowbitmap and plain appeared fine, though the shadowbitmap one exhibited the task switching glitch detailed above.
  • The "scripted" square/sphere combo did not experience this glitch, but would go nearly completely flat grey right when I got to the point that the shadow started to be projected on my pawn. The shadow was projected on the pawn properly when this occurred, however.
  • The "scriptedShadow" square/sphere combo flickered madly, though with a discernable pattern. At first this appeared independant of the angle. It also suffered from the same "flat grey" effect as the "scripted" square/sphere combo.
Legacy Sourced Player Shadows Bug 1.jpeg

Note, however:

  • The behaviour of the shadows changed after I had run the level for several minutes. The "flat grey" issue was consistent and repeatable at first, but disappeared and could not be reproduced after the first few minutes. The flickering on the "scriptedShadow" square/sphere also declined dramatically and no longer appeared to have any discernable pattern or relationship to the angle of viewing.
  • Also, if you stand "within" the spinning A in the recess, your player's shadow is projected onto the surface of the A, farthest from where your pawn is actually at. (highly unrealistic) Due to the way the projector is used this is probrably unavoidable. It is a problem with the built in shadows as well. (At least, I assume that your sourced shadows were used for the shadow in this level.
Legacy Sourced Player Shadows Bug 2.jpeg

inio: Thanks! What graphics hardware do you have? As for the shadow bug you mentioned, thats the default shadow. This map doesn't have the sourced shadow stuff (just to remove any unnecessary variables).

Foxpaw: I don't remember when the last time was that I opened it, so I'll just go by the sticker on the side of the case. It just says Integrated nVidia GeForce 2 with 32MB Video RAM. It's on a Compaq 6020 CA, though I would assume that the integrated processor is the same as an AGP version of the same card, so that might not be relevant.

inio: Ah, I was wondering if it affected NVidia setups too. So this appears to be either a bug in D3D or UT, rather than in the ATI drivers.


For anyone still listening, Epic has indicated the all render-to-texture is not really supported in the OpenGL and software renderers, so I'm going to make a few more attempts but if those don't work I'm giving up and I'm going to restrict anything not using the D3D renderer to grayscale shadows or a single blob shadow. I have some ideas for making the single blob shadow as useful as possible.


Unfortunately in my final touches I've discovered a fairly serious issue I have to resolve. I still might make it tonight but it might be tomorrow or tuesday sometime. I didn't have time to make a playable demo map so the sample will just be a map showing off all the features instead.

Quick rundown of those features

  • Shadow sources replace Lights and Spotlights
  • Volumes create areas in which actors will cast shadows
  • players, pickups, and projectiles all create shadows. Unfortunately doe to some bizareness that I don't yet understand translocators do not in this release. This may be related to the problem I've just encountered.
  • transitions into, out of, and between volumes are handled smoothly with configurable fade times
  • most shadow options (includeing always blob shadows and no tangent fade) can be configured on a source-specific basis
  • Supports regular (bitmap) and blob shadows. blob shadows can be colored to realisticly shadow large colored light sources.
  • As of this writing, adds only about 55k to the map file, plus the volumes and extra data in the lights.

As for license, it's just gonna be a "mention it in the readme" type deal.

MUCH older[edit]

Early screenshots in a test map.

The Unreal-engine generation UT2003 is based on introduced dynamic drop shadows for players, but alas they're always just falling into the same direction with no regard to the lights placed in a map. Hence, this page strives to explain how to get true Sourced Player Shadows into the game.

Not all the exposed variables do anything, and it probably still has some bugs, but at least it works:

Sourced Player Shadows Beta

That includes a map thats little demo, and source scripts. For some reason I didn't include the myLevel.u package to make it easy to include in your own maps, but I've got a workaround for that in a bit.

If you're just in it for the tech demo, load up the map single player no bots and type "behindview 1" at the console. Now walk around and watch the shadows change to reflect the local lighting. Weeee!

If you're thinking of using this tech in your own map, the most important thing to know is that each DynamicShadowVolume creates a shadow for each player within it, source at the most important ShadowCaster (typ. ShadowLight) with the same Tag. Each DynamicShadowVolume will create only one shadow for each player within it. As a side effect if you have multiple intersecting DynamicShadowVolumes, players within them will have multiple shadows. ShadowCaster exists to be subclassed. I didn't create a ShadowSpotLight yet, but it wouldn't be hard.

To use this in your own map, first load the sample map into UnrealEd, then load your map. Now place a DynamicShadowVolume and a ShadowLight somewhere in your map. Always make sure before saving that there is at least one DynamicShadowVolume and one ShadowLight in the map. Loading the sample map as a script package is not advised, as I've had very odd behavior when I've done that in the past.

Note that right now you do not have the right to redistribute maps containing this code. This will be remedied in the upcoming final release.


  • Should be pretty easy for mappers to pick up and use.
  • Shadows fade out after leaving a zone.
  • (unreleased) Mapper can control shadow casting distance, whether shadows should fade as they approach parallel with the surface, and whether to draw the shadow using blob shadow mode.
  • (unreleased) A single DynamicShadowVolume can create multiple shadows from players.
  • (unreleased) Shadows for pickups and projectiles. Player, Projectile, and Pickup shadows each have their own configuration for max # and type (rendered or blob). Plus, you can get away with more pickup shadows because they don't have to be detached and reattached each frame (as long as the light source isn't moving).


  • colored shadows for colored lights. (quite possible, just need to merge the testing code into the rest of it)
  • blurry shadows for non-point light sources. Could be done by drawing the shadow texture to a couple different locations in a scripted texture with the right blend setup.
  • shadows for particles. (maybe to a limited extent for rocket/grenade contrails only)
  • Add shadows for first-person. This would be harder from what I can tell, and would cause the odd effect of shadows from your nonexistent legs when you look down.
  • figure out a nice way of attaching a Light to a mover, as the code right now doesn't care if it's the light or the player that's moving.
  • to reduce load in situations where you have 2 or more shadow sources close together to create shadows appropriate for a non-point light: share the shadow texture between them so it only gets rendered once.

Resolved Issues (but not fixed in release code):[edit]

  • Shadows pop up when you enter a DynamicShadowVolume that has a light to close to it's edge. Same thing for the default shadow disappearing and reappearing when you enter and exit DynamicShadowVolumes (not visible in the sample map).
  • Blob shadows don't fade

Known Issues:[edit]

  • If a player gets too close to a light the shadow doesn't behave quite right. This is due to a limit on the projector FOV. Without this there would be potential for enormous cpu load when an actor got too close to a light and the FOV of the shadow projector aproached 180, resulting in a slice of the level between the plane of the shadow projector and the plane at the trace distance being considered for shadow casting. Right now the FOV is limited to about 100 (not sure of the exact number).
  • Right now there's still a few default values that need to be set to make mappers' lives easier.
  • (untested but I assume this is the case) If a player is occluded and therefore not drawn, their shadows will also not be drawn. While it would be really cool to use a ground light shining up at a wall to give a hint of player's locations without directly showing them, this could be a PITA to get working reliably.


  • This shouldn't add any bandwidth overhead in net games as it happens entirely on the client side, but I'd like someone with more experience with replication to validate that.

Mosquito: Just copy and pasted your post on the forums for people twice as ass lazy as me!

inio: You could have at least wikified it a bit. Or even just maintained the formatting that was there.


Tarquin: Do you want a news posting on this? Put a link & summary on Featured pages if you do.

inio: Not yet. This is not final by a long shot and doesn't even contain a license allow redistribution. I'll be done with it this weekend some time and have the release party then :). Why do you insist on changing my 2nd level headings to 1st level heading? I like the way 2nd level headings look.

Mychaeel: Nobody said you should release it.  :-) I suppose tarquin rather thought about pointing people to it as the work in progress it is; that's far more interesting than just a finished component anyway.

As for the headings: You don't format visually here; you format logically. First-level headings are for first-level structure; so there.

Tarquin: Yeah, I just thought it would make a good news post. People get to see what you're working on. Good publicity for the wiki as a whole too :D – could probably get us a BU news post.

inio: I'll tell the story of the development for the scripters when I'm done. Right now I don't want a lot of mappers (consumers) playing around with and judging this until I'm satisfied with it's quality. The archive that was released was to get feedback on interest and easy of use. I've gotten negligible feedback on the later but the resounding positive interest has convinced me that any minor easy of use issues are easily compensated by the general coolness of the code (product). Rather than spend time documenting the development and doing incremental releases, I instead am concentrating on getting a full-featured release into the hands of content creators ASAP. When that time comes, I'd love a BU news post :).

Foxpaw: Instead of having the shadows cast by predefined casters, it might be easier to just have a mutator that places a shadow caster at the location of every light that is over a certain intensity. Generally speaking that's where mapps would place their shadow casters anyway.. wherever the brightest lights are.

inio: First off all, there are way too many bright lights in most maps for that to be feasible. The shadow logic has to examine every potential caster each frame. If you get above about 100 lights that starts becoming a non-trivial CPU hit. Splitting the map into multiple DynamicShadowVolumes reduces this by reducing the number of potential casters the shadow casters. Secondly, the ShadowCaster (and it's descendants ShadowLight and ShadowSpotlight) are already a subclass of Light and so can be used to create light in the map themseleves.

Foxpaw: I suppose, it just seems more logical to me that way because then it could be made to work on any map, since it isn't really map-specific. Perhaps you could use the already existing zoning in lieu of volumes? At any rate, it's just an idea.

inio: Are scripted textures rendered on the gpu or on the cpu?

Foxpaw: I'm pretty sure that they are "assembled" on the CPU. The GPU does the actual drawing on the surface, however.

Mychaeel: I wouldn't be so sure about that; just look at the DrawPortal function. I rather expect the game reserves some video memory for that texture and directly draws there within the realm of the GPU.

Mosquito: Let me just get this straight, you can have Volumes AND points in space that will create shadows (so its just a simple placing these actors over top map lights) :)

inioAtWork: Not quite. What you do is first define the Volumes in which actors will cast shadows. You then replace regular lights in/near those volumes with special shadow lights (that have all the functionality of a regular light or spotlight). You set the Tag of the volume and the light's from which actors in the volume will cast shadows to the same thing. It's okay to be a little lazy with the volumes - if you keep it under about 50 shadow lights per volume you should be just fine performance wise. If you go over that you might see some issues caused by the code having to pick out the top few lights to cast shadows for every frame. It'll make more sense once you see the demo map (which will be released this weekend, along with version 1.0 of the module).

Mosquito: ok, so the only thing zones do is make the light sources function! I was worried you needed to make like light boxes or something, and have to manually set which way the shadow casts!

inioAtWork: Mosquito: Nope, the directions are automatic based on the sources. A DynamicShadowVolume can also replace the default shadow with one that has custom direction, distance, and darkness/color, which would be useful in outside areas with sunlight. Mychaeel: Just noticed your comments. My worry is that doing faded blob shadows will be almost as bad as if I used regular shadows, causing a texture upload each frame (rather than just rendering a few polygons into a texture, which in comparison is very cheap).

MWGemini: 12/30/03: Is this still a work in progress, and will you be releasing this code to mod teams/the public? If you are no longer supporting this project, but would be willing to release the code as is, I (and many others, I'm sure) would be very interested in using it.

Dr.AwkwArD: Will it also support movers and Karma in general (since it'll support projectiles)?

Dr.AwkwArD: 4/6/2004: What is the status of this project? This seems like it's a great mapping resource, and I'm anxious to see it progress. BTW, in case anyone is interested, I compiled and ran it in UT2004 and it seems to work properly. :D

Dirk Fist: Back to Fox's idea, The Mutator would only have to perform the caculations ONCE at map start, after that the Shadow caster's would continue to exist on there own. The calculations could limit the number of caster's so that you would'nt have more than a certain number of shadows in any given area (which like emitters should'nt render shadows unless they are likely to be seen) Obviously this kind of mutator would work well on some maps and not well on others but would provide a quick and dirty retrofit for existing maps. (The mutator could even detect whether a map has shadow zone/volume/caster's and not do anything in that case) :D

Foxpaw: I think Inio's hesitance to do it that was was because of the number of shadow casters that would be created. However, now that I think about it, you could maintain a dynamic array of all zones in the mutator, and that could maintain a dynamic array of shadow casters that can possibly affect actors in that zone. That way, you can precalculate virtually all of the checks, and completely exclude shadow casters that are too far away. The only ones you'd have to check would be ones that may or may not be able to make an affect.

SquirrelZero: True dynamic shadows have interested me for quite some time. I remember reading inio's original data on this project about a year ago and was very intrigued, now i'm getting around to completing my own. For those who might be interested i will be releasing a public domain version of my shadow engine, which does not require any specially placed mapper volumes or anything like that. All light source calculations are done via code and it is compatible with any existing maps and mods. It features multiple shadow support, multiple lightsource calculation, dynamically adjusted shadow FOV, full sunlight actor and even dynamic light support (this makes muzzle flash shadows possible), dynamic shadow lightening and darkening, and will not pass through walls as often as most shadow projectors will (still an issue, although i'm working on improving this). Even in maps with hundreds of lights, it still performs acceptably, as it was designed to support many players at once. The drawbacks are that it performs a bit worse than the standard 2k4 dynamic shadows, does not support zonelight, shadows look a little odd at certain angles sometimes (working on this), it doesn't always support every type of dynamic light (actors that are not light subclasses and are not spawned with lighting properties but later given them) and will not work on linux or mac. Although i wrote this about 5 months ago, it wasn't viable due to the fact that the shadows often projected onto the owner pawn, but with the addition of the bNoProjectOwner variable in UT2004 i decided to revisit it :)

JCBDigger: worth linking to the page for SquirrelZero's version