Is there any way to use per-vertex lighting, vertex colors, and decals in the same shader?

I have been struggling trying to get this to work and I was wondering if anybody would know how to solve this issue.

I created a model that uses vertex colors to paint the model, with a textures added on a few part of the model as extra details.

One option I tried was writing a surface shader, but that wouldn’t allow for per-vertex lighting as far as I could tell (Although I could be wrong, I’m a little new to writing shaders without the simplicity of the shader graph haha)

The other option I tried was writing a fixed-function shader, but it appears to me that lighting and vertex colors are inseparably tied together here. When I try to interpolate from the primary color to my decal texture, the result is always unlit. My two options in that case are textures applied normally rather than as decals that are lit correctly, or decals that are completely unlit.

Is there any solution here that I’m missing?

I’m assuming that by “per vertex lighting” you mean you want Gouraud shading for all lights. By default Unity uses per vertex lighting for non-important point lights, but not directional or spot lights. If you only need point lighting, then you can use the default example Surface Shader, add float4 vertexColor : COLOR; to the Input struct, multiply your texture byIN.vertexColor and you’re done.*

If you want Gouraud shading for all light types, Surface Shaders are entirely capable of this, but they’re not designed for it so it’s actually in some ways more complicated to use them for this purpose.

Fixed function shaders are effectively deprecated and aren’t actually supported anymore. They have very limited functionality compared to any other type of shader. You can normally ignore them for anything you want to do. But for this specific case, Unity’s legacy vertex lit shader is still a “fixed function” shader.

I use quotes there because today “fixed function” shaders are effectively another kind of Surface Shader. Surface Shaders and the still existing fixed function shaders are both shader generators, taking the code you write and outputting another shader that’s all HLSL. If you take the above shader, and copy it into a new file, if you select it in the editor, the inspector will show you a “Show Generated Code” button that you can click on. That’ll open up the “real” code, which you can then copy over the fixed function version and modify to add vertex colors to.

  • But there’s one big caveat. You mentioned decals. If you’re using Surface Shaders and fixed function shaders, that means you’re using the built in rendering path. That doesn’t have built in support for decals. So what decals are you talking about? If they’re some asset, it’ll depend on how that asset is written. Some only work with deferred, in which case it’s impossible to have both Gouraud shading and decals because deferred rendering is explicitly per pixel lighting. If they support forward rendering, then it won’t have per vertex lighting either, either because the decals do their own lighting, or because it requires special shaders on the objects.

Ah, thank you! That’s what I was looking for. I completely forgot I could get generated code for fixed function.

I think I was using the wrong term? Essentially, I was trying to use the alpha of my texture to lerp from vertex colors to texture. The fixed functions wouldn’t let me do this without excluding lighting from the texture, since lighting and vertex colors were tied together. But using the generated code has let me do what I was trying to do. Thank you!