So currently I have an unlit shader with shadows and a float value for shadow brightness. This works fine and all objects are uniformly shaded, so you don’t see any edges.
Now I would want to have that shader output be modified by light sources. Not turning into a real lit-shader where faces are shaded individually, but just have the overall object be brighter (and color tinted) when affected by a light-source.
I do have the fallback option to add a tint to the material and then manually at the start of the game go through all MeshRenderers and all Light Sources and apply the tint manually, but I’d rather do it with a shader.
Okay, so you want your object to be equally influenced by lights on all pixels.
The basics in pseudocode:
Light is additive which means the light from two sources is added up, so if you have a directional light and additional lights its like
The lights distance attenuation and shadows and calculated for the position of the pixel that is calculated in the fragment shader. Here’s your first change: you want all pixels of an object to have the same brightness, then you need to sample the same point for all pixels, like the center of the object.
You still need to write a loop that sums up the value of all additional lights.
The shader looks like built in pipeline, which i know almost nothing about, so i can’t tell you more about how to build a custom lighting solution for that.
That’s pretty easy to achieve (but will have some draw backs), just remove the normal vector inside the lighting calculation. This has been used in soome anime-style game.
For example - Blue Protocol
So a normal lighting model usually looks like this
//basic lambet lighting model, light attenuation is a falloff based on the distance to current pixel in world space.
float3 result = saturate(dot(normalWS, lightDirectionWS)) * light.attenuation * lightColor * albedo.rgb;
By removing the parts involves normal, every pixel will now lit by the distance to the light source.
//basic lambet lighting model, light attenuation is a falloff based on the distance to current pixel in world space.
float3 result = light.attenuation * lightColor * albedo.rgb;
You can then apply these logic to additional light source only.
The main draw back of this approach is that it will be lit purely based on the distacance. Even a light source behind the object will make the object brighter as long as it’s within the lighting range.
That’s close but not exactly what I want to achieve. I don’t want to have different light-intensities on a face-basis, but on the whole object basis. So, as an example, for this shader I do have the “atten” value, but when I multiply that into the color, then individual faces of the object will be lit differently. If I remove the atten value then every face is lit the same, but now the distance to a light source is completely ignored.
ChatGPT proposed to have a C# script calculate the distances of the object to each light source and set it as a float matrix for the shader. That might work… but then I limit the amount of light I can use as I have to predefine them for the matrix size.
Ok I did get it to work, with inputing the object center position via a C# script and then calculating the distance of the GameObject to the light sources. Looks really bad though, I’ll have to try something else. Still thanks for the ideas. ^^