Moving light sources on mobile?

I’ve had a look at this:

I’m thinking about doing a project involving simple indoor levels with the player carrying a torch (in 1st person), however it says that only Stationary and Static lighting is supported on mobile platforms.

Is this a strict limitation in that a project won’t build to Android at all with moving light sources, or will it build but be missing any moving lights? Or is it more of a ‘soft-limitation’ in that it may or may not work depending on the circumstances but it’s not officially supported?

If it is a strict limitation, are there any plans to support moving light sources on mobile at all in the near future?

Mobile uses a different forward rendered pipeline so it is a hard limitation.

The UE4 Trello roadmap has both dynamic lighting and shadows for mobile, but they are still in the “Wishlist/Backlog” category so there is no telling when they might be included in the engine.

However, it doesn’t mean it is entirely impossible to add your own torch light to a scene. You could use a Custom UV node (so it is calculated per vertex), and provide the location of your torch to your material . Then calculate the distance and add emissive light to the material. I haven’t tried anything similar so I am not sure if that specifically would work, but it should be possible to get it working somehow. Worst-case scenario would be re-writing and customizing some of the mobile shaders assuming you have someone with the skills to do it.

Thanks for the info!

That’s a shame, hopefully it’ll get implemented sooner rather than later though.

Your alternative solution sounds interesting, but my plan with this idea was just going to be a quick side-project to spend just a few hours reimplementing something I’d made before, so it sounds a little complex for what I was hoping to do!

The basic material isn’t too complicated to set up. Here’s a quick example I put together:

You have a light position, light radius, and a light color as parameters. This just adds light based on distance–you could do better if you take into account the light angle as well, but this was just a quick proof of concept. This is being done in a custom UV so it is relatively cheap as the computer does it per-vertex and not per-pixel. You would need to have enough triangles in your geometry to get a good result. You might be able to use a per-pixel lighting calculations (i.e specular or normal mapping), but that would start getting expensive because this is all in addition to the standard UE4 material.

Here’s a screenshot of what it looks like in the mobile preview:

Hopefully it will work the same on actual devices.

Awesome stuff there CaptainScience, I had thought custom UV was for tiling only!!

I still had the project open so I decided to add the dot product for the light angle on there as well to make a very simple vertex light. It should be pretty fast as long as your geometry isn’t too crazy detailed, but you can see a few interpolation artefacts on the ground.


Here’s the changes I made to the material. Makes it a bit more useful for adding a very simple dynamic light to a mobile scene.


Very nice, thanks!

I’ll give it a try when I get back to doing that side-project :smiley:

Just as a note to anyone who wants to try something like this: it seems like custom UVs only accept a float2 so the blue component will be cut off. You would need to use a component of one of the other custom UVs to pass through the blue component of the light.

Or make due with yellow/red/green/monochromatic light.

I’ve been trying hard with no success to get this working with a texture instead of just a color as shown in the examples above for a mobile unlit texture.

Customized UVs do not seem to allow textures so I tried plugging it into the emissive color node however the texture does not show correctly.

If I plug the whole lot into the emissive color node it works - at least on the pc and mobile preview - on the android device the ‘light radius effect’ does not work :frowning:

Any one able to get the above ‘torch’ effect to work with textures rather than just colors or at least can give hint were I’m going wrong?

Many thanks in advance!


Your value coming through the customized UV isn’t a UV at all–it’s really an intensity value of your light–so you don’t want to use it directly to sample from a texture. You want to use your regular object UVs to get the texture, and then multiply that by the value in the custom UV.

If your object doesn’t have UVs, you can always do some type of UV projection (planar is simple: just use two components of your world position). It might be expensive per-pixel if you wanted to try a more complicated projection (like a spherical projection centred on the eye of your character) so you could store that in a second set of custom UVs and it will also be calculated at each vertex Though that will always introduce some interpolation artefacts.

Hi CaptainScience thanks for the reply!

Unfortunately I’m still a bit of a noob with the material editor - so when you say:

How exactly do you do that?

I’m just using the default floor object from the starter kit so I assume the object has UVs … would be interested to know how to do that simple planar UV projection as well though if also not complicated to demostrate

If you leave the “UVs” input empty, the texture should use the first set of UVs automatically. If the model has UV data, it will be loaded into UV0 automatically. However, if you use custom UVs, and put data into UV0 you will overwrite them. So if you have UV data from your mesh that you want to keep, you need to have extra custom UV slots in your material and don’t use the first one or two. Models will frequently use UV0 for their main texture (possibly overlapping) and UV1 for their lightmap (guaranteed to be unique).

Here’s a quick material I set up with a textured light. The important change is putting the data into UV1, and then multiplying that with the light color and texture to get the final value.

And here’s an example of a planar projection. You just take the world coordinates, scale them to a size that fits your texture, and use any two of them as UVs:

Many many thanks for these examples CaptainScience!! I think I have a slightly better understanding of UVs now :slight_smile:

Will apply them to my demo project soon and post here when it’s done :slight_smile:

Thanks for sharing this. For a small performance hit, it works on Android! I tested out having pre-baked static lighting with a point light, and utilizing this vertex shader to provide dynamic lighting to some objects and it works very well for my older device! I’m not sure if there’s a better way to modify intensity other than multiplying the final output once more by a constant (works well enough!) and it doesn’t seem to light any vertices at all if the object is rather centered on the light source. But that can be avoided with level design…

Thanks again for your nice material idea CaptainScience - as promised the link to the finished product :slight_smile:

Great effect for a maze where I don’t want to reveal too much area :wink:

Hi, everyone!
I’m newbie, and my question may be stupid, but I’d spend a lot of hours trying to change “light source position” value to another (based on my character location) in runtime.
Could anyone give a tip?

one mistake ruined all!
i’ve made it work :slight_smile:

An alternative would be to just bake a regular per-vertex lighting equation into each material you use.

Have a global parameter for where the torch is, and calculate the vector/distance between torch and vertex, do regular NdotL clamping, bias/offset to about 0.25 … 1.0 range, and modulate the “base color” with this value. The bias/clamp the inverse of the range to a 0.25 … 1.0 range, and modulate your ambient map with that value.

You’d have to make all the light maps be full-bright for this to really work. Or you can mark the material as “unlit” and just modulate/sum all the lighting terms into the emissive slot.
GL 1.1 level lighting! Whee!

Is it possible to use normal map with this light effect? I mean using only “texture light” without any usual lights.

Normal maps are per pixel, which means you would have to do the calculations on top of the color/emissive output instead of the per vertex stuff. More expensive, but perfectly possible.