VPainter icon indicating copy to clipboard operation
VPainter copied to clipboard

Shader triplanar

Open GabrielBRDeveloper opened this issue 2 years ago • 0 comments

This project helped me a lot, so I'm here to give my contribution, based on some github code, and some changes I created a triplanar shader, it needs some adjustments, but I would like it to be implemented in the project, here is the code:

[gd_resource type="Shader" format=2]

[resource]
code = "/*----------------------
HEIGHTBLEND SHADER v1.0:
------------------------
The shader uses 3 textures per material:
	* M: A mask texture. R channel contains the height information, G channel contains the rougness information and B channel contains the metal information.
	* C: RGB color/albedo information.
	* N: Normalmap information.
------------------------
------------------------*/
shader_type spatial;

uniform float uv_scale:hint_range(0.01, 100.0) = 1;

uniform float UV_SCALE1:hint_range(0, 1000) = 1;
uniform sampler2D c1:hint_albedo;
uniform sampler2D n1:hint_normal;

uniform float UV_SCALE2:hint_range(0, 1000) = 1;
uniform sampler2D c2:hint_albedo;
uniform sampler2D n2:hint_normal;

uniform float UV_SCALE3:hint_range(0, 1000) = 1;
uniform sampler2D c3:hint_albedo;
uniform sampler2D n3:hint_normal;

uniform float UV_SCALE4:hint_range(0, 1000) = 1;
uniform sampler2D c4:hint_albedo;
uniform sampler2D n4:hint_normal;

uniform float blend_softness1:hint_range(0.01, 1.0) = 0.025;
uniform float blend_softness2:hint_range(0.01, 1.0) = 0.025;
uniform float blend_softness3:hint_range(0.01, 1.0) = 0.025;


vec3 heightblend(vec3 input1, float height1, vec3 input2, float height2, float softness){
	float height_start = max(height1, height2) - softness;
	float level1 = max(height1 - height_start, 0);
	float level2 = max(height2 - height_start, 0);

	return ((input1 * level1) + (input2 * level2)) / (level1 + level2);
}

vec3 heightlerp(vec3 input1, float height1, vec3 input2, float height2,float softness, float t ){
	t = clamp(t, 0.0 , 1.0);
    return heightblend(input1, height1 * (1.0 - t), input2, height2 * t, softness);
}

vec3 random(vec3 coord)
{
	vec3 res;
	res.x = fract(sin(dot(coord.yz, vec2(12.9898,78.233))) * 43758.5453123);
	res.y = fract(sin(dot(coord.xz, vec2(16.6539,68.698))) * 69845.5962848);
	res.z = fract(sin(dot(coord.xy, vec2(25.5263,41.256))) * 42538.6985436);
	return res;
}

vec3 triPlanarTexture(float scale,vec4 projected_coords, vec3 color_offset, vec3 normal_weights, sampler2D text ){
	float real = (1000.0 - scale)/1000.0;
	vec3 mask10 = texture(text, projected_coords.zy*real).rgb;
	vec3 mask11 = texture(text, projected_coords.xz*real).rgb;
	vec3 mask12 = texture(text, projected_coords.xy*real).rgb;
	
	return mix(vec3(0.0f), mix((mask10 * normal_weights.x + mask11 * normal_weights.y + mask12 * normal_weights.z), color_offset.rgb, 0.05f), 1.0f);
}


void fragment(){
	
	vec4 projected_coords = CAMERA_MATRIX * vec4(VERTEX, 1.0);
	
	vec3 world_normal = abs(CAMERA_MATRIX * vec4(NORMAL, 0.0)).xyz;
	vec3 normal_weights = world_normal / (world_normal.x + world_normal.y + world_normal.z);
	vec3 color_offset = random(floor(projected_coords.xyz));
	
	
	vec3 mask1 = vec3(1.0, 1.0, 1.0);
	vec3 mask2 = vec3(1.0, 1.0, 1.0);
	vec3 mask3 = vec3(1.0, 1.0, 1.0);
	vec3 mask4 = vec3(1.0, 1.0, 1.0);

	vec3 col1 = triPlanarTexture(UV_SCALE1, projected_coords, color_offset, normal_weights, c1);
	vec3 col2 = triPlanarTexture(UV_SCALE2, projected_coords, color_offset, normal_weights, c2);
	vec3 col3 = triPlanarTexture(UV_SCALE3, projected_coords, color_offset, normal_weights, c3);
	vec3 col4 = triPlanarTexture(UV_SCALE4, projected_coords, color_offset, normal_weights, c4);
	
	vec3 nor1 = triPlanarTexture(UV_SCALE1, projected_coords, color_offset, normal_weights, n1);
	vec3 nor2 = triPlanarTexture(UV_SCALE2, projected_coords, color_offset, normal_weights, n2);
	vec3 nor3 = triPlanarTexture(UV_SCALE3, projected_coords, color_offset, normal_weights, n3);
	vec3 nor4 = triPlanarTexture(UV_SCALE4, projected_coords, color_offset, normal_weights, n4);



	vec3 m_blend1 = heightlerp(mask1.rgb, mask1.r, mask2.rgb, mask2.r, blend_softness1, COLOR.r);
	vec3 m_blend2 = heightlerp(m_blend1.rgb, m_blend1.r, mask3.rgb, mask3.r, blend_softness2, COLOR.g);
	vec3 m_blend3 = heightlerp(m_blend2.rgb, m_blend2.r, mask4.rgb, mask4.r, blend_softness3, COLOR.b);
	
	vec3 c_blend1 = heightlerp(col1.rgb, mask1.r, col2.rgb, mask2.r, blend_softness1, COLOR.r);
	vec3 c_blend2 = heightlerp(c_blend1.rgb, m_blend1.r, col3.rgb, mask3.r, blend_softness2, COLOR.g);
	vec3 c_blend3 = heightlerp(c_blend2.rgb, m_blend2.r, col4.rgb, mask4.r, blend_softness3, COLOR.b);

	vec3 n_blend1 = heightlerp(nor1.rgb, mask1.r, nor2.rgb, mask2.r, blend_softness1, COLOR.r);
	vec3 n_blend2 = heightlerp(n_blend1.rgb, m_blend1.r, nor3.rgb, mask3.r, blend_softness2, COLOR.g);
	vec3 n_blend3 = heightlerp(n_blend2.rgb, m_blend2.r, nor4.rgb, mask4.r, blend_softness3, COLOR.b);
	
	ALBEDO = c_blend3.rgb;
	NORMALMAP = n_blend3.rgb;
	ROUGHNESS = m_blend3.g;
	METALLIC = m_blend3.b;
}"

Tested in Godot 3.4

GabrielBRDeveloper avatar Aug 12 '22 13:08 GabrielBRDeveloper