Blockout shader material

Hello to all,

I’d like to share a shader that generates UV on boxes influenced by their scale. It’s not production ready but i think it can be a good base when you block out your levels.

process

The main idea is to extract the model scale and select the right projection based on the normal of the face. Everything is done in vertex.

void vertex() {
	// extraction of the global scale
	vec3 scale = vec3(length(MODEL_MATRIX[0].xyz), length(MODEL_MATRIX[1].xyz), length(MODEL_MATRIX[2].xyz));
	// scaling the vertex
	vec3 scaledvertex = scale * VERTEX;
	// render the dot products in all directions
	vec3 dots = vec3(abs(dot(NORMAL, RIGHT)), abs(dot(NORMAL, UP)), abs(dot(NORMAL, FWD)));
	// followed by a terrible if else block
	if (dots.x > dots.y && dots.x > dots.z)
	{
		UV = scaledvertex.yz;
	}
	else if (dots.y > dots.z)
	{
		UV = scaledvertex.xz;
	}
	else {
		UV =scaledvertex.xy;
	}
}

result in the viewport:

the solution was given in the post : https://www.reddit.com/r/opengl/comments/sih6lc/4x4_matrix_to_position_rotation_and_scale/

complete shader

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

const vec3 RIGHT = vec3(1,0,0);
const vec3 UP = vec3(0,1,0);
const vec3 FWD = vec3(0,0,1);

uniform float uv_scale = 0.5;
uniform vec2 uv_offset = vec2(0.25, 0.25);

uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable;

uniform float roughness : hint_range(0.0, 1.0);
uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap, repeat_enable;

uniform float specular : hint_range(0.0, 1.0, 0.01);
uniform float metallic : hint_range(0.0, 1.0, 0.01);

void vertex() {
	// extraction of the global scale
	vec3 scale = vec3(length(MODEL_MATRIX[0].xyz), length(MODEL_MATRIX[1].xyz), length(MODEL_MATRIX[2].xyz));
	// scaling the vertex
	vec3 scaledvertex = scale * VERTEX;
	// render the dot products in all directions
	vec3 dots = vec3(abs(dot(NORMAL, RIGHT)), abs(dot(NORMAL, UP)), abs(dot(NORMAL, FWD)));
	if (dots.x > dots.y && dots.x > dots.z)
	{
		UV = uv_offset + scaledvertex.yz * uv_scale;
	}
	else if (dots.y > dots.z)
	{
		UV = uv_offset + scaledvertex.xz * uv_scale;
	}
	else {
		UV = uv_offset + scaledvertex.xy * uv_scale;
	}
	
}

void fragment() {

	vec4 albedo_tex = texture(texture_albedo, UV);
	ALBEDO = albedo.rgb * albedo_tex.rgb;
	
	vec4 roughness_texture_channel = vec4(1.0, 0.0, 0.0, 0.0);
	float roughness_tex = dot(texture(texture_roughness, UV), roughness_texture_channel);
	ROUGHNESS = roughness_tex * roughness;

	METALLIC = metallic;
	SPECULAR = specular;
	
}

I hope it might help some of you.

Best regards

1 Like