6-way lightmap WIP

It looks like your lighting directions are all derived from tangent space?
If that’s the case then they’d need to get transformed to the same space as the light vector (World), or preferably see if you can transform the Light Vector to tangent and see how you fare with that (you’d probably be able to punt that to a vertex interpolator to keep down pixel cost.)


What alex said, basically if you are using the code in my post (or based on it), the Light Vector direction needs to be in Tangent space. From the looks of it, you’re getting it in world space, so you’d need to pass that Light Vector node through a “World to Tangent” transform node.


Ahh ok I think I get what I need to do. Ill give it a shot tomorrow and see where I land with it. Thanks for the help guys! :blush:

hey it worked like a charm! Awesome! I get a little bit of artifact with the blends but I think I just have one of my channels backwards or something. Definitely a lot closer to where I want to be though!


Good to hear!!

In the specific case you are displaying above, you are blending between 2 maps, (roughly half of Z+ and half of X+, i think?) . So it’ll never look exactly like pure X+. Once you have proper lightmaps (instead of sphere gradients), the details will hide most of that as it kinda blends in.


A bit more work into the shader. Using multiple resolutions. (Edit) Will proceed with the 1024 version which is using 2 1024’s, one alpha one not.

I also did a version of the approximation of the front and back derived from just left right up down that @Mederic does. Images of result below.

Still have yet to implement the ramps for color remapping. That’s next!

Here’s what the current labeled “2048” example in the video uses. The second one from left just takes my lightmap output at the end and I input 2 color parameters to completely control the coloring of the clouds which is also nice.

Thanks to @EStampes, seeing your graph helped me understand the math a bit better than my first take, allowing me to just ditch my lerps and multiply my lightmaps as @Mederic originally had.

I also gave the approximated front and back a go. The front looks pretty close to actual front with a bit more contrast. I feel I want to play with the back a bit more to make the edges and lighter thinner parts at the end of the sim pop out a bit more from the solid darker center. For anyone curious here is the math in nodes attempting to duplicate what Mederic layed out (also, let me know if that math looks wrong):

Also pretty happy with how the sim turned out in Houdini, upper half of comp from texture 1:

Feedback on how to optimize/improve super welcome. Thanks guys, and thanks again @Mederic!


Have you tried downscaling your animated lightmap texture to 1k? It holds up pretty well as well as being a huge memory saver.

Yeah good point. The version on the far right is using 1024’s which still holds up, I’ll move forward with making those ones work. Also, makes me wonder if there’s some post process I could use to hide pixelation and sell motion blur :thinking:

Motion vectors? Will post a link when I find one remember a tutorial/write up a while back for them - Also great work man been useful for me to learn from so thanks for the updates and write ups :smiley:

My only question is in your node graph above whats in the second texture?:slight_smile: the first I think is top/left/right lighting but wasn’t sure about the second

T1: red - right
T1: green - left
T1: blue - top
T1: alpha - alpha
T2: red - bottom
T2: green - back
T2: blue - front


Thanks appreciated :slight_smile:

Hey Nate, in your material setup in the 6-way Lightmap group, what’s the second/bottom texture sample? Is that just the same flipbook rendered from the “back” of your sim?

I guess you could refer to this :slight_smile:

1 Like

Dang, thanks. Dunno how I glossed over that the first time :sleeping:

1 Like

I am very interested in this discussion and am trying to recreate what you posted, but I have to ask a sily question, what is your material’s shading model, ie lit directional or what? as I am getting no effect from my actual lights, or do you have to feed in the light direction vector using a blueprint?

1 Like

If I remember correctly the shading model is unlit. The vector for the light is fed in using AtmosphericLightVector which is the default sun/sky sun direction. I never got beyond using just that so if you wanted to use your own lights and (feed them into the shader) maybe somebody else can chime in on how to do that!

thanks for your reply, really appreciate it, I tried moving the sun/directional light direction but I couldn’t see the vector in the shader updating, I will investigate more in depth

Hey Niel, hows things…

I;ve got a version of this shader working with directional lights and 2 point lights in Unity…I can past some bits to help if your interested…


Hi Alcolepone,
I am interested in how you set this up in Unity. I’ve been playing around with this most of the day and can’t say I’ve had success.

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 ;