91 lines
4.4 KiB
Plaintext
91 lines
4.4 KiB
Plaintext
shader_type canvas_item;
|
|
render_mode unshaded;
|
|
uniform sampler2D height_map : filter_linear, repeat_disable;
|
|
uniform sampler2D grass_detail : source_color, filter_linear_mipmap, repeat_disable;
|
|
uniform sampler2D soil_detail : source_color, filter_linear_mipmap, repeat_disable;
|
|
uniform sampler2D rock_detail : source_color, filter_linear_mipmap, repeat_disable;
|
|
uniform sampler2D sand_detail : source_color, filter_linear_mipmap, repeat_disable;
|
|
uniform sampler2D moss_detail : source_color, filter_linear_mipmap, repeat_disable;
|
|
uniform vec4 low_color : source_color;
|
|
uniform vec4 high_color : source_color;
|
|
uniform vec4 sand_color : source_color;
|
|
uniform vec4 rock_color : source_color;
|
|
uniform float climate = 0.0;
|
|
uniform float seed_offset = 0.0;
|
|
uniform int biome_kind = 0;
|
|
|
|
float hash(vec2 p) {
|
|
uvec2 cell=uvec2(ivec2(p));
|
|
uint value=cell.x*1597334677u ^ cell.y*3812015801u;
|
|
value^=value>>16u;
|
|
value*=2246822519u;
|
|
value^=value>>13u;
|
|
value*=3266489917u;
|
|
value^=value>>16u;
|
|
return float(value & 16777215u)/16777216.0;
|
|
}
|
|
float noise(vec2 p) {
|
|
vec2 i=floor(p), f=fract(p); f=f*f*(3.0-2.0*f);
|
|
return mix(mix(hash(i),hash(i+vec2(1,0)),f.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),f.x),f.y);
|
|
}
|
|
float fbm(vec2 p) {
|
|
return noise(p)*0.55+noise(p*2.03+8.1)*0.27+noise(p*4.13+3.7)*0.13+noise(p*8.21)*0.05;
|
|
}
|
|
vec2 tile_uv(vec2 uv) { return vec2(1.0)-abs(fract(uv*0.5)*2.0-vec2(1.0)); }
|
|
float luminance(vec3 color) { return dot(color,vec3(0.299,0.587,0.114)); }
|
|
void fragment() {
|
|
vec2 p=UV*3840.0;
|
|
vec2 seed=vec2(seed_offset,seed_offset*0.317);
|
|
float region=fbm(p*0.0022+seed);
|
|
float moisture=fbm(p*0.0051+seed+vec2(31.4,17.3));
|
|
float patches=fbm(p*0.012+seed+vec2(74.2,91.7));
|
|
float fine=noise(p*0.19+seed);
|
|
float h=texture(height_map,UV).r+(patches-0.5)*0.03;
|
|
float slope_x=texture(height_map,UV+vec2(0.003,0)).r-texture(height_map,UV-vec2(0.003,0)).r;
|
|
float slope_y=texture(height_map,UV+vec2(0,0.003)).r-texture(height_map,UV-vec2(0,0.003)).r;
|
|
float shade=clamp(1.0-slope_x*3.8-slope_y*2.8,0.72,1.25);
|
|
// Different orientations and warped coordinates hide repeating square tiles.
|
|
vec2 warp=vec2(region-0.5,moisture-0.5)*110.0;
|
|
vec2 q=p+warp;
|
|
vec3 grass=texture(grass_detail,tile_uv(q/325.0+seed*0.013)).rgb;
|
|
vec3 soil=texture(soil_detail,tile_uv(vec2(q.y,-q.x)/245.0+seed*0.017)).rgb;
|
|
vec3 rock=texture(rock_detail,tile_uv((q*mat2(vec2(0.8,0.6),vec2(-0.6,0.8)))/360.0)).rgb;
|
|
vec3 sand=texture(sand_detail,tile_uv(vec2(-q.x,q.y)/235.0+vec2(0.37,0.18))).rgb;
|
|
vec3 moss=texture(moss_detail,tile_uv(q/210.0+seed*0.019)).rgb;
|
|
vec3 grass_base=mix(low_color.rgb,high_color.rgb,clamp(region*0.75+smoothstep(0.3,0.7,h)*0.25,0.0,1.0));
|
|
vec3 grass_surface=grass_base*(0.57+luminance(grass)*1.18);
|
|
vec3 soil_surface=mix(sand_color.rgb*0.58,soil*0.85,0.5)*(0.9+fine*0.16);
|
|
vec3 rock_surface=rock_color.rgb*(0.55+luminance(rock)*1.05);
|
|
vec3 sand_surface=sand_color.rgb*(0.54+luminance(sand)*0.86);
|
|
vec3 moss_surface=mix(low_color.rgb*0.82,vec3(0.2,0.32,0.16),0.2)*(0.63+luminance(moss)*1.1);
|
|
float vegetation=smoothstep(0.28,0.66,region*0.55+moisture*0.45);
|
|
float wetness=smoothstep(0.42,0.70,moisture);
|
|
float arid=biome_kind==4 ? 1.0 : 0.0;
|
|
if(biome_kind==2) { vegetation*=0.82; wetness=min(1.0,wetness+0.35); }
|
|
if(biome_kind==3) { vegetation*=0.65; }
|
|
if(biome_kind==5) { vegetation*=0.35; }
|
|
vegetation*=1.0-arid*0.8;
|
|
// Exposed soil, low vegetation and moss form distinct local patches.
|
|
vegetation*=1.0-smoothstep(0.58,0.76,patches)*0.72;
|
|
vec3 land=mix(soil_surface,grass_surface,vegetation);
|
|
land=mix(land,moss_surface,wetness*vegetation*0.72);
|
|
float sand_patches=smoothstep(0.42,0.7,patches)*(1.0-moisture);
|
|
land=mix(land,sand_surface,sand_patches*(0.22+arid*0.78));
|
|
float stone=max(smoothstep(0.59,0.77,h+patches*0.045),clamp(length(vec2(slope_x,slope_y))*9.0,0.0,0.7));
|
|
land=mix(land,rock_surface,stone);
|
|
// Small scree and gravel pockets below the main rock formations.
|
|
float scree=smoothstep(0.67,0.79,patches)*smoothstep(0.36,0.62,h)*0.45;
|
|
land=mix(land,rock_surface,scree);
|
|
if(climate< -10.0) {
|
|
float snow=smoothstep(0.46,0.73,h+(region-0.5)*0.13);
|
|
vec3 snow_surface=vec3(0.83,0.89,0.87)*(0.83+luminance(sand)*0.28);
|
|
land=mix(land,snow_surface,snow);
|
|
}
|
|
vec3 shore=mix(sand_surface,land,smoothstep(0.28,0.33,h));
|
|
float lake=1.0-smoothstep(0.265,0.278,h);
|
|
float depth=clamp((0.274-h)*8.0,0.0,1.0);
|
|
vec3 water=mix(vec3(0.23,0.42,0.39),vec3(0.08,0.22,0.27),depth);
|
|
water+=(fine-0.5)*0.012;
|
|
COLOR=vec4(mix(shore*shade,water,lake),1.0);
|
|
}
|