How to access surface material from spatial shader

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By bananasam

I have an imported mesh which has multiple surface materials and I would like to create a custom shader for this mesh that uses those surface materials. I essentially want to only override the light() shader processor function, using whatever defaults the surface material would provide in fragment(). However I’m having trouble figuring out how to accomplish this.

Here’s the MeshInstance3D: surface material (not sure how to embed. ctrl+g didn’t work for me, sorry).

Then I try to add a shader to the material override property on the GeometryInstance3D node, but I don’t see any way to get the data from the MeshInstance3D.mesh surface materials. Am I missing something (I tried to find answer online and in the shader reference with no luck)?

The only workaround I can think of for this would be to import the mesh resources as external, convert the existing surface materials to shader materials, and then somehow inject my custom shader code into the generated shader. Then I would add that shader as a surface material override on the MeshInstance3D. That sounds like a mess though so I’d rather avoid that (although maybe that could all be done in an import script?).

Any help is greatly appreciated!

update: I found a ShaderGlobalsOverride node, yet there are no docs :frowning: if anyone has any details on this I’d love to know, otherwise I’ll eventually getting around to diving into the engine source code to figure it out…

:bust_in_silhouette: Reply From: Inces

This has been confusing me for a long time.
There are several paths leading to materials in meshinstance

  1. MeshInstance.mesh
    2.MeshInstance.material
    3.GeometryInstance.material_override

Imported materials stored as built-ins, are stored in .mesh file (1), and can be accesed with this property of Mesh Instance. Materials of mesh instance (2) naturally override them, these methods are contained within MeshInstance class, check it in docs ( for example surface_get_material(x,y). Material override is one material overriding every surface at once. In Godot 3.5 there is also material overlay, but it seems broken…

Whatever You plan to do, You won’t be able to OVERLAY material with your light code. This will erase effects of fragment and vertex, they will be completely overriden.
I usually collect references to all materials in code, and create new ShaderMaterials with my shader file, swap old materials with new ones, and only set old albedo_colors as my new materials color parameter.

Thanks for the ideas! It’s unfortunate there’s no simple solution for this but oh well.

bananasam | 2022-12-21 18:22