Hi there,

I needed to decrease material draw calls on a scene so i decided to create a multi material using vertex colors. Instead of drawing three materials, only one material is drawn.

shader_type spatial; 

uniform sampler2D tex1Albedo : hint_albedo;
uniform sampler2D tex1Normal: hint_normal;

uniform sampler2D tex2Albedo : hint_albedo;
uniform sampler2D tex2Normal: hint_normal;

uniform sampler2D tex3Albedo : hint_albedo;
uniform sampler2D tex3Normal: hint_normal;

varying vec4 vertexColor;

void vertex() {
    
    vertexColor = COLOR;

}

void fragment() {
    
    vec3 t1 = texture(tex1Albedo, UV ).rgb;
    vec3 t2 = texture(tex2Albedo, UV ).rgb;
    vec3 t3 = texture(tex3Albedo, UV ).rgb;
    
    vec3 n1 = texture(tex1Normal, UV ).rgb; 
    vec3 n2 = texture(tex2Normal, UV ).rgb; 
    vec3 n3 = texture(tex3Normal, UV ).rgb; 
    
    vec3 albedoAdd = t1 * vertexColor.r + t2 * vertexColor.g + t3 * vertexColor.b ; 
    vec3 normalAdd = n1 * vertexColor.r + n2 * vertexColor.g + n3 * vertexColor.b ; 
    
    ALBEDO =  albedoAdd;
    
    NORMALMAP = normalAdd;
    
    ROUGHNESS = 0.5;
}

Next is to include roughness maps, textures resolution multiplier; and perhaps another version with more materials.

With one multi material you can create characters with extra details with one draw call; it's also good to use on level objects categories with one multi material per category.

Does Godot has a vertex painter ? It would be a nice addition to the CSG tool :)

Do you have any benchmarks on how much faster this would be?

I would think any gain from this method could get partially canceled from the greater number of textures involved, or is this not the case?

@Ace Dragon said: Do you have any benchmarks on how much faster this would be?

I would think any gain from this method could get partially canceled from the greater number of textures involved, or is this not the case?

It's how materials works in general, each new material you draw it's a new draw call. This shader is one material and one draw pass. Less draw calls and less draw pass = more performance.

The workflow is not for everyone, you have to paint vertex, it's an additional manual work required.

Until you are making a game graphics intensive or towards VR you don't need to use such materials.

As Ace Dragon says, you should be a bit careful when doing things like this. It may not actually improve performance. Why? You have more texture samples.

For each pixel of those object the GPU now samples 6 images instead of 2. And in GPU land a texture sample is rather slow. So for this to be worthwhile, the overhead of the extra draw-call needs to be greater than the time doing the texture samples. The only way to determine this would be to benchmark it. Reducing draw-calls is not the end-all-be-all of optimization.

Perhaps atlas texture would solve the textures samples. The shader is about getting less draw calls, perhaps there is situations like mobile games where it could be usefull.

5 years later