How to add glow and 2D lights to an old 2D Unity URP game
How to give an old 2D Unity game selective glow with URP Bloom and HDR, dynamic 2D lights and a sharp UI for current screens, using the game Dreamica.

An old 2D Unity game on the built-in render pipeline looks flat on a current phone: there is no lighting, glow is either missing or lights up the whole frame including the UI, and the interface sprites are blurry. In Unity URP you fix this with three things: Bloom with a threshold of 1 plus HDR colour only on objects that should glow, 2D lights from the 2D renderer, and a UI with larger sprites that respects the screen's safe area.
We show the process on our game Dreamica (App Store, Google Play). It is a falling adventure where you draw lines with your finger to guide a bubble with a sleeping child through four worlds. It was originally built in Unity 5.3, with the UI in the NGUI plugin, glow from the MK Glow plugin and art made for the iPhone 7 and its 1334 × 750 display. The gameplay stayed the same; only the graphics changed.
You often reopen an old game because of the store, not the graphics. Since August 2019 Google Play requires 64-bit versions, and a game with only a 32-bit build drops off it. That is exactly what happened to Dreamica. Once you are moving the project to Unity 6 anyway, the graphics are a relatively cheap bonus.
Why the old full-screen glow is not enough
Older glow plugins work as a full-screen effect. They light up everything bright, including the icon buttons in the menu. In Dreamica, MK Glow in Unity 6 made the icons nearly vanish. Unity's official Post Processing Stack v2 only replaces it for the built-in pipeline and no longer applies in URP. If you want glow you control per material, plus dynamic 2D lights, move to URP and use the Bloom built into it.
Step 1: Switch the project to URP
After switching to URP, an old 2D game will almost certainly hit two traps. Both show up as a picture that looks wrong, or exactly the same as before, even though the shaders are fine.
A grey screen: set up a camera stack
If the Game view in the Editor shows nothing but a grey area while the Scene view and a one-off camera render look fine, the problem is not in the shaders but in how the cameras are combined. Old games often have two cameras, one for the world and one for the UI, and the UI camera only clears depth. That is how cameras are layered in the built-in pipeline, and URP does not support it. It needs an explicit camera stack: one camera is the Base, the others are Overlays added to its stack. Set it up in every scene where cameras are layered.
Sprites ignore lights: switch to the 2D renderer
Sprites with a lit shader ignore every light if the regular URP renderer is active. It does not compute 2D lights at all. Switch to the 2D renderer. Even that one draws no lighting until the scene has at least one 2D light. When something looks exactly the same after a change, first check which renderer is running.
Particles and old plugins
Particles on old shaders render black, or not at all, under the 2D renderer. Give them a new, simple shader.
Watch the Asset Store too. During an asset refresh the Editor can apply an "update" to an old plugin on its own, adding metadata and renaming shaders. Materials find their shader by name, so they break silently. After every larger asset refresh in an old project, review all changed files in version control, including the ones you are not working on.
Step 2: Selective glow with HDR colour and Bloom at threshold 1
The goal is for selected objects to glow (in Dreamica the drawn line, lasers, sparks, fireflies and runes) but not the backgrounds or the UI. Bloom in URP blurs and adds everything brighter than its threshold. Set the threshold to 1 and push the colour of the materials that should glow above 1.
line shader:
colour = texture × vertex colour × tint × intensity (intensity = 6)
Bloom:
threshold = 1, intensity = 0.3
only what ends up brighter than 1 glows
Backgrounds and buttons have colours between 0 and 1, so they do not pass the threshold and stay sharp. That also gets rid of the washed-out icons. The camera must have HDR enabled. Without it the colour is clamped to 1 and nothing glows. The 2D renderer does not show the HDR toggle in the camera inspector, so enable it from a script.


Once glow is under control like this, it does not have to be optional. In Dreamica we removed the glow toggle from the settings; glow is part of the look.
Emission map: only part of the sprite glows
If only part of a sprite should glow, give it an emission map: a second, black and white texture that marks which part of the sprite glows. Only that part gets a colour above 1, so on a rune the core shines, not the whole outline.

Pulsing in exposure stops
If the glow should pulse, do not multiply the colour linearly. An HDR material can have a brightness around 2 to the power of 8, and a linear multiplier from 0 to 10 makes no visible difference on it. Compute the pulse in exposure stops (EV), the same way as the intensity slider in Unity's HDR colour picker:
colour = tint × 2 ^ ev, ev oscillates between a minimum and a maximum
Step 3: A dynamic 2D light around the player
Put a 2D point light on the player with a soft flare around it. In Dreamica a single sine wave drives the flare brightness, the light radius and the light intensity together, so they pulse as one. The environment can set the light colour: white in the forest, orange in the swamp, purple in winter, yellow in hell. Switch backgrounds and obstacles to lit shaders, otherwise they ignore the light.
Short lights bring events to life. When the squirrel's cannon fires, an amber light with intensity 3 flashes and fades out over 0.3 seconds, and the muzzle sparks glow. Not everything has to glow: the dust when the acorn disappears is brown on purpose and does not glow.
The same shader on adjoining surfaces
If two backgrounds join up, the source images have the same brightness and there is still a visible seam, check the shaders. In Dreamica the opening background and the endless forest background each used a different shader. One ignored the material tint of 0.733, the other applied it and darkened the forest to 73%. The fix is the same shader on both surfaces.


Surge: blend to a peak instead of adding
On the way into the next world the light and flare surge: 0.6 seconds up, a short hold, 1.4 seconds down, and the flare turns once. If you simply add the surge on top of the pulse, the peak depends on where the sine wave happens to be, and every surge has a different strength. Blend smoothly from the pulse to a fixed peak instead:
weight = surge curve (0 to 1)
value = pulse + (peak - pulse) × weight


Step 4: A sharp UI for current screens
A UI drawn for the iPhone 7 has small sprites. Dreamica's menu button sprite was 128 × 64 pixels, and on a phone with three times the pixel density it was stretched several times over. Redraw the sprites at a higher resolution: the new button is 800 × 434, and the progress bars grew from 200 × 26 to 800 × 104.


If the UI is built on NGUI, consider a rewrite. NGUI anchors resolve piece by piece across several frames, long anchor chains sometimes settle in the wrong place, and the scale differs between the Editor, a phone and an iPad. In Dreamica fixes did not make it reliable, so we rewrote the UI in uGUI and TextMeshPro. Go screen by screen and keep the old version running next to it as a reference. Scale the UI by height against a reference resolution (434 × 941 points in our case) and respect the screen's safe area, meaning the notch and rounded corners. When the rewrite is done, remove NGUI from the project entirely so you do not end up with two UI systems.
Limits: uncompressed textures
This process only changes the graphics. In Dreamica we did not compress textures, on purpose, because we wanted full sharpness. The price is size: even the original game had 313 MB of textures in memory in the Editor, and it is 299 MB on the App Store. By our estimate compression would shrink the textures to roughly 40 MB. If game size matters to you, that is the first place to save.
For another Unity game from the first line of code to release, see the post on Space Impact Watch; performance in Unity is covered in the post on horde navigation in Unity DOTS. If the game is still on Unity 4, don't open it directly in Unity 6; the safe route is described in how to upgrade a Unity 4 project to Unity 6. If you have an old Unity game that dropped off the stores and you want it back, get in touch.


