Godot Version
Version 4.6.1 stable forward+ (and other rendering modes)
Question
TLDR: How do does ATTENUATION work in spatial shaders? I need to figure out how to divide it up into even divisions when combined with the dot product of the Normal and Light, that I can directly modify the values of later. Current issues are that it isn’t properly respecting surface area that the light should be hitting properly, and the distance the light nodes are from it and their projected light.
SEE EDIT BELOW! Prior is original issue and kept for potential sake of relevancy in case there is a simpler solution.
Trying to make a custom Cell-like spatial shader (this is the base off it but it will be stenciled further after) and I can’t seem to get it right when it comes to handling SpotLight3D nodes. This being that I either get it a good base for a cell-shaded look but the SpotLight3D node doesn’t accept it, or it does but I end up with the ugly effects of the image provided. Sometimes both. I’ve done testing, looking at other tutorials and all I can really grasp at is that it is tied to Attenuation. Not handling it or including it in sections like diffuse =dot(NORMAL,LIGHT) * ATTENUATION; has it be seen by spotlights. But will result in the cubing. At this point I just need an explanation on the cubing, ATTENUATION in the spatial shader and how it works, and the SpotLight3D node not wanting to work (does it not contribute light in the same way that others do, in that the typical diffuse lighting algorithm doesn’t have access to it?). Also to know if its even possible, since the closest I get still results in soft lighting areas which I’m trying to strictly avoid, to the point that if it comes to it I will just try and work around the cubing over it. However it should be possible to fit it into a cell-shaded architecture too right somehow? My attempts leave me with spotlights that cover drastically less area than they should, and only affecting surface they are closer than they need to, or dividing them into around 100 bands to get where it ought to be which naturally causes its own issues, like sorta defeating the point of a cel shader.
EDIT: Image removed so I can keep the one most relevant. Following link shows what I meant above. Found a report for the issue I am having ( Multiply by attenuation to prevent blocky artifacts · Issue #6 · CaptainProton42/FlexibleToonShaderGD · GitHub ), and thus managed to get things down to one singular issue since I could better pinpoint the source of my issues (I had already suspected it was tied to ATTENUATION). My current method which resolves the issue above (which I must also note also has the issue of the light from sources affecting areas larger than it should. Like in the image provided the light on the wall should not be covering that large of an area. ) is as follows:
void light(){
float ndotl = dot(NORMAL,LIGHT);
float diffuse =ndotl * ATTENUATION;
float cutDiffuse = floor(diffuse*5.0)/5.0;
//cutDiffuse=clamp(diffuse + mod(1.0 - diffuse, (1.0/5.0)), 0.0, 1.0);
DIFFUSE_LIGHT += cutDiffuse * albedo_color * LIGHT_COLOR/PI;
}
Which is what I had, at its most basic, when I started messing with it way before starting this post, and why I had originally thought SpotLight3D nodes weren’t working with it. This is because the method has a big issue, lights need to be far closer than needed to show up. It could be worked around, but I extremely doubt doing so when the disparity is that bad would be performant.
The commented out equation, is from digging around the github the issue report I linked is in and fixes “the needs to be too close to process light” issue, but has other issues. Particularly with trying to implement my processes on top of it, as they end up looking like a noise filter was applied (You can see this easily by adding
if(cutDiffuse <0.2){
cutDiffuse=0.0;
}
to the code above after the commented line (and of course uncommenting the line). but for accessibility here is how it looks:
I know it should be theoretically possible since the area is set proper when I smoothstep attenuation first (by the same value on both ends, i did 0.05, as it seems to be the only way I can manage this.) But as the images below show, it doesn’t decay with distance. Further testing on my end showed that it more or less is akin a static image being scaled up as you move away, restricted by the bounds of the light falling off yet not decaying itself. Ultimately making it another bust.
I think at this point I need a proper guide to how ATTENUATION works in the shader. I read that it is 0 to 1 and I tested and its not limited to that. Ultimately either know how ATTENUATION works so I can derive a solution myself or how to modify the divisions above to properly cover the range that the light should. Last clue I can consider on how my code isn’t perceiving the range properly, is it doesn’t respond to expanding SpotLight3D node’s range like it should either. Until the node is close enough, it might as well not exist; it doesn’t matter how far I make the node project its cone. Finally I apologize if anything doesn’t seem right or consistent with the edit and please ask, I have been actively typing and rewriting it for 2 days as I try stuff, think of something new to try come to a new conclusion on the problem, and repeat. So I may have missed something that results in some jumbleness.
