• 3D
  • Godot-Blender-Exporter and MagicaVoxel export problem

Hi, Do you have the same problem like me with MagicaVoxel palette (colors) when you want to import your model in Godot. You can see below my export procedure and the result what i get on Godot.

1st : I create my model on MagicaVoxel and export this in obj file

2nd : I import my model in Blender and i export it with the Godot-Blender-Exporter tool Export options :

3rd : I import my model in Godot and this is the result :

I have post an issue on the Github project page, but if you have any ideas :) Thanks for your help :+1:

Here the Godot inspector after import (there are no material)

But if i add the material we have the same result in the viewport :/

Here the inspector for the material

looking at the blender screenshot, I bet there is extra shader logic involved. If you would open up the material/shader editor in blender and show that too, we might be able to help you rebuild it in godot perhaps.

Ok, that is simpler than I expected, does the model have a vcol layer in the mesh data panel in properites(in blender)?

edit: also the smaterial on your godot object is a shader, so maybe show the actual shader too. Not sure why I overlooked that earlier.

There is no vertex color layer but you have UVMap layer And the material Shader in Godot

The code for the material :

shader_type spatial;
render_mode blend_mix, depth_draw_always, cull_back, diffuse_burley, specular_schlick_ggx;

uniform vec3 AABB_POS;
uniform vec3 AABB_SIZE;
uniform sampler2D texture_0;

varying smooth vec3 AABB_UVW;

void node_bsdf_principled(vec4 color, float subsurface, vec4 subsurface_color,
        float metallic, float specular, float roughness, float clearcoat,
        float clearcoat_roughness, float anisotropy, float transmission,
        float IOR, out vec3 albedo, out float sss_strength_out,
        out float metallic_out, out float specular_out,
        out float roughness_out, out float clearcoat_out,
        out float clearcoat_gloss_out, out float anisotropy_out,
        out float transmission_out, out float ior) {
    metallic = clamp(metallic, 0.0, 1.0);
    transmission = clamp(transmission, 0.0, 1.0);

    subsurface = subsurface * (1.0 - metallic);

    albedo = mix(color.rgb, subsurface_color.rgb, subsurface);
    sss_strength_out = subsurface;
    metallic_out = metallic;
    specular_out = pow((IOR - 1.0)/(IOR + 1.0), 2)/0.08;
    roughness_out = roughness;
    clearcoat_out = clearcoat * (1.0 - transmission);
    clearcoat_gloss_out = 1.0 - clearcoat_roughness;
    anisotropy_out = clamp(anisotropy, 0.0, 1.0);
    transmission_out = (1.0 - transmission) * (1.0 - metallic);
    ior = IOR;
}


void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) {
    color = texture(ima, co.xy);
    alpha = color.a;
}

void vertex () {
	AABB_UVW = mat3(vec3(1, 0, 0), vec3(0, 0, 1), vec3(0, -1, 0))
		* ((VERTEX - AABB_POS) * (1.0 / AABB_SIZE));
}

void fragment () {
	
	// node: 'Image Texture'
	// type: 'ShaderNodeTexImage'
	// input sockets handling
	vec3 node0_in0_vector = vec3(0.0, 0.0, 0.0);
	// output sockets definitions
	vec4 node0_out0_color;
	float node0_out1_alpha;
	
	node0_in0_vector = AABB_UVW;
	node_tex_image(node0_in0_vector, texture_0, node0_out0_color, node0_out1_alpha);
	
	
	// node: 'Principled BSDF'
	// type: 'ShaderNodeBsdfPrincipled'
	// input sockets handling
	vec4 node1_in0_basecolor = node0_out0_color;
	float node1_in1_subsurface = float(0.0);
	vec3 node1_in2_subsurfaceradius = vec3(1.0, 0.20000000298023224,
		0.10000000149011612);
	vec4 node1_in3_subsurfacecolor = vec4(0.800000011920929, 0.800000011920929,
		0.800000011920929, 1.0);
	float node1_in4_metallic = float(0.0);
	float node1_in5_specular = float(0.0);
	float node1_in6_speculartint = float(0.0);
	float node1_in7_roughness = float(1.0);
	float node1_in8_anisotropic = float(0.0);
	float node1_in9_anisotropicrotation = float(0.0);
	float node1_in10_sheen = float(0.0);
	float node1_in11_sheentint = float(0.5);
	float node1_in12_clearcoat = float(0.0);
	float node1_in13_clearcoatroughness = float(0.029999999329447746);
	float node1_in14_ior = float(1.4500000476837158);
	float node1_in15_transmission = float(0.0);
	float node1_in16_transmissionroughness = float(0.0);
	vec4 node1_in17_emission = vec4(0.0, 0.0, 0.0, 1.0);
	float node1_in18_alpha = float(1.0);
	vec3 node1_in19_normal = NORMAL;
	vec3 node1_in20_clearcoatnormal = vec3(0.0, 0.0, 0.0);
	vec3 node1_in21_tangent = TANGENT;
	// output sockets definitions
	vec3 node1_bsdf_out0_albedo;
	float node1_bsdf_out1_sss_strength;
	float node1_bsdf_out3_specular;
	float node1_bsdf_out2_metallic;
	float node1_bsdf_out4_roughness;
	float node1_bsdf_out5_clearcoat;
	float node1_bsdf_out6_clearcoat_gloss;
	float node1_bsdf_out7_anisotropy;
	float node1_bsdf_out8_transmission;
	float node1_bsdf_out9_ior;
	
	node_bsdf_principled(node1_in0_basecolor, node1_in1_subsurface,
		node1_in3_subsurfacecolor, node1_in4_metallic, node1_in5_specular,
		node1_in7_roughness, node1_in12_clearcoat, node1_in13_clearcoatroughness,
		node1_in8_anisotropic, node1_in15_transmission, node1_in14_ior,
		node1_bsdf_out0_albedo, node1_bsdf_out1_sss_strength, node1_bsdf_out2_metallic,
		node1_bsdf_out3_specular, node1_bsdf_out4_roughness, node1_bsdf_out5_clearcoat,
		node1_bsdf_out6_clearcoat_gloss, node1_bsdf_out7_anisotropy,
		node1_bsdf_out8_transmission, node1_bsdf_out9_ior);
	
	
	ALBEDO = node1_bsdf_out0_albedo;
	SSS_STRENGTH = node1_bsdf_out1_sss_strength;
	SPECULAR = node1_bsdf_out3_specular;
	METALLIC = node1_bsdf_out2_metallic;
	ROUGHNESS = node1_bsdf_out4_roughness;
	CLEARCOAT = node1_bsdf_out5_clearcoat;
	CLEARCOAT_GLOSS = node1_bsdf_out6_clearcoat_gloss;
	NORMAL = node1_in19_normal;
	// uncomment it when you need it
	// TRANSMISSION = vec3(1.0, 1.0, 1.0) * node1_bsdf_out8_transmission;
	// uncomment it when you are modifing TANGENT
	// TANGENT = normalize(cross(cross(node1_in21_tangent, NORMAL), NORMAL));
	// BINORMAL = cross(TANGENT, NORMAL);
	// uncomment it when you have tangent(UV) set
	// ANISOTROPY = node1_bsdf_out7_anisotropy;
}

It's clearly generated from the blender/cycles shader-node tree. So it's up to debugging that shader then.

Though worth a note that the easiest solution might be to simply bake that material in blender into a texture to simply load it in godot. In fact I'd recommend that unless you have a really good reason for wanting a more procedural material in godot, note that this is also heavier computationally and affects performance, so again, baking it into a texture in blender would probably be a better solution.

Out of curiosity, have you tried a SpatialMaterial, with the MagicaVoxel texture (chenille.png) as the input for the Albedo map?

Looking at the shader coded posted above, it looks like a lot of it is for generating the PBR values from the Blender node editor inputs. While this makes sense, I think there is a lot of code in that shader that is not needed in this case. That said, I only have limited OpenGL and GLSL experience, so I might be completely wrong and/or missing something.

I think if you make a SpatialMaterial, assign the MagicaVoxel texture as the Albedo texture map,and set the roughness to 1, I think you should get the same result as the Blender picture. I do now know if it will give the same or similar results, but if you have not already tried it then it might be worth a try.

you're right, the shader isn't special, but the texture is a simple gradient pallet texture, there is likely something going on with the UV coordinates in there. Meaning a normal spatialmaterial might even work, but could be that theres something further going on in there. But I can't identify anything in the shader that looks like special coordinates for the texture, so probably not.

I confirm @TwistedTwigleg, i created a new SpatialMaterial with chenille.png in Albedo texture and it's working :D

Thanks a lot for your help !

So it's up to the UV's alone then. I guess the MagicaVoxel greates UV's per face rather than islands of faces.

@nuxlight said: I confirm @TwistedTwigleg, i created a new SpatialMaterial with chenille.png in Albedo texture and it's working :D

Thanks a lot for your help !

Great! Glad it is working :smile:

@Megalomaniak said: So it's up to the UV's alone then. I guess the MagicaVoxel greates UV's per face rather than islands of faces.

I’ve done similar UV layouts before for my own projects, which is why I thought this could be the case with MagicaVoxel outputs.

Though looking at the outputted Blender shader, I’m still not entirely positive how it works and why. One big question I have with the shader is why does it calculate a AABB box? Maybe it is my inexperience with shaders, but I’m not totally sure where knowing the AABB would be helpful to a shader.

Regardless, I’m just glad a solution was found. I was not looking forward to trying to dissect and understand how the Blender shader works :lol:

About the AABB. Probably because blender does it to generate the generated texture coordinates, I think there's just blenders own bias as noise in the data in here. Basically I was overthinking and analyzing the problem in the first place and ended up asking for too much data.

Sometimes it's better to just take a simple guess, others you really do need it. Most of the time it's probably the former rather than the later.