Realistic FDM 3D printed shader material

Shader to mimic FDM 3D prints.

There is a seperate top pattern. The minimum “angle” that determines what surface is considered as “top” can be tweaked using top_pattern_strength.

The entire pattern can be rotated by editing x_degrees and y_degrees.

If you need a combination of the 3D printed look and another material, set an overlay_texture (with a transparent background) to overlay a texture onto the 3D printed material.

Builtin AA that fades away the pattern at further distances to reduce Moiré patterns.

Shader code
shader_type spatial;

uniform float top_pattern_strength: hint_range(0.5, 1.0) = 0.6;
uniform vec3 color: source_color;
uniform float layer_height_mm: hint_range(0.1, 1.0) = 0.2;

uniform float x_degrees: hint_range(-90.0, 90.0) = 0.0; // rotation around X
uniform float z_degrees: hint_range(-90.0, 90.0) = 0.0;  // rotation around Z

uniform sampler2D overlay_texture:hint_default_transparent;

varying vec3 local_pos;
varying vec3 print_up;
varying vec3 local_normal;

vec3 get_normal_map(float x, float aa) {
	float theta = fract(x)*PI;
	
	vec3 normal = vec3(cos(theta), 0.0, -sin(theta)) * aa;
	
	//convert normal vector to correct normal map color
	return vec3(
		0.5+normal.x*0.5,
		0.5+normal.y*0.5,
		0.5-normal.z*0.5);
}

mat3 rotX(float a) {
	float c = cos(a), s = sin(a);
	return mat3(
		vec3(1.0, 0.0, 0.0),
		vec3(0.0, c, s),
		vec3(0.0, -s, c)
	);
}

mat3 rotZ(float a) {
	float c = cos(a), s = sin(a);
	return mat3(
		vec3(c, s, 0.0),
		vec3(-s, c, 0.0),
		vec3(0.0, 0.0, 1.0)
	);
}

void vertex() {
	mat3 print_rotation = rotX(radians(x_degrees)) * rotZ(radians(z_degrees));
	local_pos = print_rotation * VERTEX;
	print_up = print_rotation * vec3(0.0, 1.0, 0.0);
	local_normal = NORMAL; // model/object space, unaffected by node's world transform
}


void fragment() {
	const float INV_SQRT_2 = 0.70710678;
	ROUGHNESS = 0.3;
	float luminance = dot(color, vec3(0.299, 0.587, 0.114));
	SPECULAR = mix(0.2, 0.5, luminance);
	METALLIC = 0.0;
	float sideness = round(abs(dot(local_normal, print_up))*top_pattern_strength);
	
	float scale = (1.0/layer_height_mm)*1000.0;
	vec4 overlay_color = texture(overlay_texture, UV);
	
	float y_input = local_pos.y*scale;
	float diag_input = (local_pos.x+local_pos.z)*INV_SQRT_2*scale;
	
	float aa_y = 1.0 - smoothstep(0.7, 1.0, fwidth(y_input));
	float aa_diag = 1.0 - smoothstep(0.7, 1.0, fwidth(diag_input));
	
	NORMAL_MAP = mix(
		mix(
			get_normal_map(y_input, aa_y),
			get_normal_map(diag_input, aa_diag),
			sideness
		),
		vec3(0.5, 0.5, 1.0),
		overlay_color.a
	);
	
	ALBEDO.rgb = mix(color, overlay_color.rgb, overlay_color.a);
}
Live Preview
Tags
3d, 3D printed, FDM, plastic, print, printed, realistic
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from TreeOfTriangles

Related shaders

guest

0 Comments
Oldest
Newest Most Voted