Unity3D - Sharing tricky technique Particle Per Pixel Lighting with low cost

Hello RTVFX guys!:smiley:

I’d share a funny and tricky technique for particle lighting with Unity3D. This was talked on certain public Japanese game conference last year.
On Unity3D, getting good lighting and receive shadow with low cost is not easy regarding particles. Maybe the people who has been developed game on PS4 with Unity3D knows that is very hard to achieve rich lighting and shadow.
This method achieve better detail of particle receive shadow and lighting than LPPV a little bit.

Left = This method, Right = default particle(Unity3D 5.2)

Current Unity3D has LPPV which affect light prove to particle. However, when I worked on FPS(60f/s) game at out sourcing company as a VFX tech artist at Capcom, Unity3D was “version 5.2”:scream:, so I couldn’t use that. And 5.2 didn’t have some multi-threading yet, but we had to have “particle lighting” and “receive shadow” on PS4. (Developing on PC was super easy!!)

Over view of Pipe Line

.1. Preparing the 16 plane polygon, and bake important lights of level.

Why I used 16 layer, that game had maximum raughly Width 50m * Depth 50m * Height 18m, so it didn’t need so much height layer to bake lights.

.2. Aligning those textures on one 2D texture horizontally.

I used “2562564096 texture, RGB without Alpha-Channel”. On run-time, memory size was about 3MB.

.3.This method needs script in order to make Volume Texture. Unity3D couldn’t use Volume Texture directly (not yet?), so I had to make Volume Texture from 2D texture which prepared.
Like this,

.4. The Volume Texture that made with script have to attach to custom particle shader.
Shader’s properties are like this,

Properties {
    _MainTex ("MainTex", 2D) = "white" {}
    _TintColor ("Color", Color) = (1,1,1,1)
    _Volume ("_Volume", 3D) = "" {} //Attach the volume tex.
    _VolumeOfset ("VolumeOfset", Vector) = (0.5,0,0.5,0) // In order to adjust position of Volume Tex.
    _VolumeScaling ("VolumeScaling", Vector) = (1,1,1,0) // Adjustment scale. Should be Depended on Scale of Level.

And this is baked lighting affect per pixel. (you can use per vertex instead of per pixel, but it was too rough for this game.)
like this,

float4 frag(VertexOutput i) : COLOR {
float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
float3 VolumeUVD = (float3(_VolumeScale.r,_VolumeScale.g,_VolumeScale.b) + float3(_VolumeOfs.r,_VolumeOfs.g,_VolumeOfs.b));
float4 _Volume_var = tex3D(_Volume, VolumeUVD);

float3 finalColor = (_MainTex_var.rgbi.vertexColor.rgb_TintColor.rgb*_Volume_var.rgb); /* i.vertexColor is the colour from shuriken.*/

Pros and Cons

Not bad performance, and gain the lighting and receive shadow. In fact I could use this method on PS4.
I think it will be better combining with LPPV.
Small Volume Tex (2562564096) was nice, because it got a soft shadow automatically.:smiley:

It doesn’t fit to “Full destructive level”, because it is static… just baked lights. However, it will be able to blend some Volume Tex that are prepared as other situation, it will resolve some of problem I guess.
And it can’t use open world.:pensive: If the level is small (such as 50m*50m), it could be work.

I hope it could help something…:slight_smile:



Dude this is really cool! I’ve done some experiments with 3D textures but never considered using them on a level-wide scale. This has certainly given me some interesting ideas, thank you x)

1 Like

Thanx for sharing! I have been using a similar technique for a mobile project. I used gradiented rectangular boxes to light dynamic objects and particles instead of 3D textures. Lighting configuration was limited but minimal performance and memory impact. Actually I never thought about using 3D textures, they could work for mobile as well.

1 Like

Wow thx for sharing this! Never used 3D textures before but this is a really interesting and powerful case of use. Now I’m eager to try it out somewhere :smiley:

1 Like

this is the kinda shit that WORKS. great job man!

1 Like

Thanks Matt-san! :smile: