I am currently making a game based around colonizing planets, and I would like to know how I overlap a lightmap texture of the earth on a sphere, but only at the positions which are affected by shadow in shadergraph. I am using unity 2020.1.0a25 with the universal render pipeline.
The distribution of light across a sphere is at its most basic level determined by the dot product between the surface normal and the vector towards the light. This is called lambert shading. In shader language, it would be written like this:
float NdotL = dot(normal, lightDir);
We can incorporate this into a custom function in a similar way. Create a custom funciton with two input variables called Normal and WorldPos, and an output variable called Shadow. Paste this code into it:
#if SHADERGRAPH_PREVIEW
Shadow = 1 - saturate(dot(float3(0.707, 0.707, 0), Normal));
#else
Light mainLight = GetMainLight();
float lightAmount = saturate(dot(mainLight.direction, Normal));
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, WorldPos);
lightAmount += saturate(dot(light.direction, Normal));
}
#endif
Shadow = saturate(1 - lightAmount);
#endif
What this function does is that it sums up the light contribution from the main light and all additional lights and returns the inverse of that. Because the dot product produces a value between -1 and 1, it is first clamped to the [0, 1] range using saturate().
Note - what you get out of this function is essentially a gradient that goes from 0 at the terminus to 1 at the point opposite to the sun. You might want to remap this value somehow to have a more sharp border, you can for instance multiply it by 100 and clamp it to [0, 1], or use a square root.