Wandering Clipmap – Stylized Grass

Tested on Godot 4.1

A stylized grass shader designed for use with a wandering clipmap terrain! Uses dithered fadeout.

Stylistic inspiration from No Man’s Sky.

Designed to work in concert with my wandering clipmap grass particle shader: https://godotshaders.com/shader/wandering-clipmap-foliage-particle-process

Looks great with kenny foliage textures: https://kenney.nl/assets/foliage-sprites

 

Shader code
shader_type spatial;

render_mode cull_disabled, vertex_lighting;

group_uniforms properties;
uniform float specular : hint_range(0.0, 1.0);
uniform float roughness : hint_range(0.0, 1.0);
uniform float metallic : hint_range(0.0, 1.0);
uniform vec2 fadeout_envelope;

group_uniforms color;
uniform vec3 top_color : source_color;
uniform vec3 bottom_color : source_color;
uniform vec3 noise_color : source_color;

group_uniforms maps;
uniform sampler2D foliage_texture;
uniform sampler2D heightmap_normals : hint_normal;
uniform float heightmap_scale;
uniform sampler2D color_noise;
uniform float color_noise_scale;
uniform float color_noise_intensity : hint_range(0.0, 1.0);

group_uniforms wind;
uniform bool wind;
uniform sampler2D wind_noise;
uniform float wind_scale = 1.0;
uniform float wind_intensity = 1.0;
uniform float wind_speed = 1.0;
uniform float wind_darken : hint_range(0.0, 1.0);

varying vec2 heightmap_position;
varying vec3 vert_normal;

const mat4 dither = mat4(
	vec4(0.0625, 0.5625, 0.1875,  0.6875),
	vec4(0.8125, 0.3125, 0.9375,  0.4375),
	vec4(0.25, 0.75, 0.125, 0.625),
	vec4(1.0, 0.5, 0.875,  0.375));

vec3 unpack_normal(vec4 rgba) {
	vec3 n = rgba.xzy * 2.0 - vec3(1.0);
	n.z *= -1.0;
	return n;
}

float getValue(int x, int y) {
	return dither[x][y];
}

float remap(float value, float istart, float istop, float ostart, float ostop) {
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

void fragment() {
	NORMAL = (VIEW_MATRIX * (MODEL_MATRIX * vec4(vert_normal, 0.0))).xyz;
	
	float limit = getValue(int(FRAGCOORD.x) % 4, int(FRAGCOORD.y) % 4);
	
	ALPHA = texture(foliage_texture, UV).a;
	if (COLOR.a < limit - 0.001) {
		discard;
	}
	
	ALPHA_SCISSOR_THRESHOLD = 0.7;

	float color_noise_at_position = mix(0, texture(color_noise, heightmap_position * color_noise_scale).r, color_noise_intensity);
	
	vec3 base_color = mix(top_color, bottom_color, UV.y);
	vec3 mixed_color = mix(base_color, noise_color, color_noise_at_position);
	
	float wind_darkening = mix(1.0, texture(wind_noise, heightmap_position * wind_scale + vec2(TIME * wind_speed)).r, wind_darken);
	if (!wind) { wind_darkening = 1.0; }
	ALBEDO = mixed_color * texture(foliage_texture, UV).rgb * wind_darkening;
//	ALBEDO = vec3(COLOR.a);
	SPECULAR = specular;
	ROUGHNESS = roughness;
	METALLIC = metallic;
}

void vertex() {
	float heightmap_size = float(textureSize(heightmap_normals, 0).x);
	heightmap_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xz * (1.0 / (heightmap_scale * heightmap_size)) + vec2(0.5);
	
	if (wind) {
		float wind_intensity_at_position = texture(wind_noise, heightmap_position * wind_scale + vec2(TIME * wind_speed)).r * wind_intensity;
		float wind_offset = mix(wind_intensity_at_position, 0.0, UV.y);
		VERTEX.x += wind_offset;
	}
	
	vec3 world_position = (MODEL_MATRIX * vec4(VERTEX, 1)).xyz;
	float camera_distance = distance(world_position, INV_VIEW_MATRIX[3].xyz);
	float fadeout = clamp(remap(camera_distance, fadeout_envelope.x, fadeout_envelope.y, 1, 0), 0, 1);
	COLOR.a = fadeout;
	
	vert_normal = unpack_normal(texture(heightmap_normals, heightmap_position));
	NORMAL = vert_normal;
}
Tags
grass, stylized, terrain, terrain detail
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 ZestfulFibre

Wandering Clipmap – Stylized Terrain

Wandering Clipmap – Foliage Particle Process

Related shaders

Wandering Clipmap – Stylized Terrain

Wandering Clipmap – Foliage Particle Process

Stylized Cartoon Grass

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Nxur
Nxur
1 year ago

Looks so good, can you put a demo project?