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); }