Hello Everyone, I have been working on a surface shader with a custom lighting function but I'm fairly new to writing complex shaders so I am really stuck on a few things. In particular, I can't seem to get the shader to receive shadows correctly and I have tried everything that I found via Google but nothing has worked. A couple notes first: 1. I am using a custom lighting function. 2. I am using a custom SurfaceOutput struct but it contains all of the standard SurfaceOutput struct fields. I just added a few new ones that I needed. 2. I have included: #pragma surface surf Diffraction fullforwardshadows (where Diffraction corresponds to the LightingDiffraction() function) 3. I have also tried including addshadow on that line 4. I have tried using the tags: "LightMode" = "ForwardAdd" and "LightMode" = "ForwardBase" But, so far, no luck. Is there something that I have to call in my lighting function to get the shadows to work? Or is there something else entirely that I am missing? I didn't include all of my code because it is kind of long and a bit of a mess at the moment due to it being very much a WIP. However, I totally understand that you might need to see it to be able to help, so I can post snippets or the whole thing if that is actually helpful. Thanks!
Can you post it here in the forums? Or preferably the entire shader? fullforwardshadows only enables shadow receiving for point lights, assuming your custom lighting function works with shadows to begin with. Adds a generated shadow caster pass. Usually not needed. Those are for specific shader passes, which a Surface Shader generates automatically. Those tags don't have any effect when used at the SubShader level, and are overridden by the generated passes anyway. Random thoughts that may or may not be useful: There are a handful of different forms of the custom lighting function, not all of which are well documented. If you're using the form that takes a UnityGI gi input, the shadows are already baked into the gi.light.color value. If you're using the form that takes a half atten, then atten is the shadow. If you're not using those values, you won't get shadows. If your shader is transparent, like if you're using "Queue"="Transparent" or your #pragma surface line includes alpha, then shadows won't work at all. Unity's built in renderer doesn't support shadow receiving on transparent objects. There are some work arounds for a single directional light, but it's impossible to support receiving shadows from the built in point or spot lights when you have a transparent object shader.
@bgolus Thanks for getting back to me! This was really helpful. I am using the custom lighting function that takes the UnityGI struct as a parameter but I didn't know that was where the shadow value was encoded. I just tried applying it to my calculated color with a simple multiplication and it seems like it works well for point lights but something is wrong with my directional lights. You can see the difference in the screenshots. It seems like I might just have some sort of issue with the directional light in general, though. The directional light doesn't seem to be creating correct shadows for anything in the scene, so I'm investigating that now. One other question: Do you know where I can find any info about using the GI data for manually calculating shadows (or how it is encoded)? Thanks for the help!
There's no documentation on it if that's what you're asking. Really the only thing you can do is look at the generated shader code, and then through the shader source code yourself to try and make sense of it all. There's a link to the source pinned at the top of this sub-forum, or a copy of the latest stable version is usually uploaded here by a community member: https://github.com/TwoTailsGames/Unity-Built-in-Shaders
Ok, cool. I had a feeling that this was the type of thing that just isn't documented but I figured I would ask anyway. I have been using the built-in shader source code to try to fill in the gaps in Unity's documentation on shaders, but there are definitely some details that are hard to figure out. (i.e. the shadow encoding). Thanks again for the help!
If you add addshadow fullforwardshadows decal:blend to your surface shader pragma, your transparent shader will receive shadows. Here's a fur shader with 10 alpha blended pases, all receiving shadows:
This works as long as it doesn’t need to appear in front of the skybox, or another transparent object. In both cases, the skybox and other transparencies in the scene will render on top anywhere an opaque object isn’t already rendered.
Yeah. It's not a bullet proof solution but with some renderingqueue tweaking might work just fine. A better solution is to decode shadows manually but still won't work with screenspace shadows pass (sice it decodes shadows using depth) unless there's a depth pass (or something that writes to depth) before the transparent pass with the same mesh on the same spot.