6-way lightmap WIP

heres the basis of the shader, bit late but hope it helps someone

		float ComputeLightMap(float3 LD, float4 lightmap, float frontMap, float  backMap)
			float hMap = (LD.r > 0.0f) ? (lightmap.x) : (lightmap.y);   // Picks the correct horizontal side.
			float vMap = (LD.g > 0.0f) ? (lightmap.z) : (lightmap.w);   // Picks the correct Vertical side.
			float dMap = (LD.b > 0.0f) ? (frontMap) : (backMap);              // Picks the correct Front/back Pseudo Map
			float lightMap = hMap*LD.r*LD.r + vMap*LD.g*LD.g + dMap*LD.b*LD.b; // Pythagoras!
			return lightMap;

		vertOutput vert (vertInput v)
			vertOutput o;
			o.texcoord = v.texcoord;
			o.texcoord2 =v.texcoord.zw;
			o.pos = UnityObjectToClipPos (v.vertex);
			o.color = v.color * _TintColor;
			o.ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
			float3 WP = mul (unity_ObjectToWorld, v.vertex).xyz;

			//particle world to tangent calculation

			float3 normalDir = UnityObjectToWorldNormal(v.normal);
			float3 tangentDir = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
			float3 bitangentDir = normalize(cross(normalDir, tangentDir) * v.tangent.w);
			float3x3 worldToTangent = float3x3(tangentDir, bitangentDir, normalDir);

			//directional light
			float3 lightDirection =   _WorldSpaceLightPos0.xyz;
			o.tangentlightDir1 = mul(worldToTangent, lightDirection).rgb;
			o.lightColor = _LightColor0.rgb;

			//point light 1			
			float3 lightPos = float3(unity_4LightPosX0.x, unity_4LightPosY0.x, unity_4LightPosZ0.x);
			float3 lightDirection2 = normalize(lightPos - WP.xyz); 
			o.tangentlightDir2 = mul(worldToTangent, lightDirection2);
			//o.tangentlightDir2 *= float3(1,1,-1);
			float range = (0.005 * sqrt(1000000 - unity_4LightAtten0.x)) / sqrt(unity_4LightAtten0.x);
			range =  distance(lightPos, WP.xyz) / range;
			range = saturate(1.0 / (1.0 + 25.0*range*range) * saturate((1 - range) * 5.0));			
			o.lightColor2 = unity_LightColor[0].rgb * range;

			o.normal = v.normal;
			o.blend = v.blend;


			return o;

		fixed4 frag (vertOutput IN) : COLOR
			//unity blend frames
				half4 LightMapA = tex2D(_LightmapTex, IN.texcoord);
				half4 LightMapB = tex2D(_LightmapTex, IN.texcoord2);
				half4 LightMap =  lerp(LightMapA, LightMapB, IN.blend);
			//float4 LightMap = tex2D(_LightmapTex, IN.texcoord);

				half4 AlphaMapA = tex2D(_AlphaTex, IN.texcoord);
				half4 AlphaMapB = tex2D(_AlphaTex, IN.texcoord2);
				half4 AlphaMap =  lerp(AlphaMapA, AlphaMapB, IN.blend);
			//float4 AlphaMap = tex2D(_AlphaTex, IN.texcoord);
			// If you find better approximations for front and back map using the 4channel we have… I am all ears.
			float frontMap = 0.25f * (LightMap.x+LightMap.y+LightMap.z+LightMap.w);
			frontMap = pow(frontMap, 0.55);
			float backMap =  1.0f - frontMap;
			backMap = saturate(0.25*(1.0-IN.normal.x) + 0.5*(backMap*backMap*backMap*backMap));
			//backMap *= 0.25;

			//directional light
			float3 lightDir = normalize(IN.tangentlightDir1);   //light 1
			float lightmap01 = ComputeLightMap(lightDir,LightMap,frontMap,backMap);
			//point light
			float3 lightDir2 = normalize(IN.tangentlightDir2);  //light2 
			float lightmap02 = ComputeLightMap(lightDir2,LightMap,frontMap,backMap);
			// light colors -
			float3 lightmap01rgb = float3(lightmap01, lightmap01, lightmap01)*IN.lightColor;
			float3 lightmap02rgb = float3(lightmap02, lightmap02, lightmap02)*IN.lightColor2;
			lightmap01rgb += lightmap02rgb;

			float4 heat = tex2D(_HeatGradientTex,float2((1-AlphaMap.r*IN.color.r),0));

			float4 Light = float4(lightmap01rgb,AlphaMap.g*IN.color.a);
			Light.rgb *= IN.lightColor +  IN.lightColor2;
			Light.rgb += IN.ambient;
			Light.rgb *= IN.color.ggg;
			Light.rgb += heat.rgb;
			Light.a += AlphaMap.r *IN.color.r;
			float4  d =  Light ;

did a small video about how to render those lightmaps at once in houdini:


I’m wondering: As we’re using a non-srgb texture, shouldn’t we gamma correct everything after mixing it together before sending it out to the material?

Thanks a lot for sharing! I am thinking to reproduce the shader in Unity as well. Maybe you’ve got the visual scription option? :slight_smile:

I recreated this shader, but for some reason, I found that R and G vector channels need to be multiplied to -1 to work correctly. It’s for sure some coordinate issue because I tried to swap gradients in “if” nodes and shadowing for X and Y was still upside down. However, for Z straight value from the vector node works just fine.
I’m very confused, maybe someone have an idea where problem could be?

It’s a bit hard to say why it would be backwards, the math in my original attempt was a bit dirty and I know I was having issues as well in that first shot at it. I ended up ditching all those lerps and went for a something much closer to mederics original shader, which is cleaner. So I’d defenitely recommend that over my initial version:

Am I correct to understand that this setup requires manually passing in the atmospheric sun direction vector (at least in UE4)? Does that imply that the system won’t receive dynamic shadows correctly (by ignoring them)? Or do dynamic shadows somehow come into play?

Is there a way this can be pulled off with directional normal calculations, so that the system can support any arbitrary light conditions?

a unity video about 6 way/sided lightmaps: Realistic smoke lighting with 6-way lighting in VFX Graph | Unity Blog

1 Like

it looks like in unity they can even light the particles with light probes, I am wondering if Unreal engine is supporting something like this aswell so that it doesnt look off when placed in different light situations of the level. currently it looks like all the unreal shader approachers are unlit right ?

You’re correct. The VFXGraph Unity HDRP 6-Way output is directly integrated in the HDRP Light Loop.
That means particles are receiving both Direct and indirect light contributions and that they can be lit by any numbers of lights without any shader hacks.

In all my past project as a VFX Artist, I always have been relying on Instance parameters to tweak my VFX so that they integrate better with the different lighting condition.
Then the lighting was changed and I was crying as I had to tweak again my instanced VFX.
This should enable VFX artist to make more generic VFX that can be put in different lighting condition and just work.