game/terrain/terrain.gdshader

58 lines
1.4 KiB
Plaintext

shader_type spatial;
const int MAP_COUNT = 4;
uniform sampler2D[MAP_COUNT] ALBEDO_MAPS;
uniform float HEIGHT_SCALE = 100.0;
uniform sampler2D[MAP_COUNT] NORMAL_MAPS;
uniform vec2 SIZE;
uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable;
void fragment() {
vec2 uv = UV * (SIZE / 2.0);
vec2 uv_alt = uv * -0.5;
vec3 splat_map = texture(TERRAIN_MAP, UV).rgb;
float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0);
ALBEDO = blank * 0.5 * (texture(ALBEDO_MAPS[0], uv).rgb + texture(ALBEDO_MAPS[0], uv_alt).rgb);
for (int i = 0; i < (MAP_COUNT - 1); i += 1) {
int map_index = i + 1;
ALBEDO += splat_map[i] * 0.5 * (texture(ALBEDO_MAPS[map_index], uv).rgb +
texture(ALBEDO_MAPS[map_index], uv_alt).rgb);
}
NORMAL_MAP = blank * 0.5 *
(texture(NORMAL_MAPS[0], uv).rgb + texture(NORMAL_MAPS[0], uv_alt).rgb);
for (int i = 0; i < (MAP_COUNT - 1); i += 1) {
int map_index = i + 1;
NORMAL_MAP += splat_map[i] * 0.5 * (texture(NORMAL_MAPS[map_index], uv).rgb +
texture(NORMAL_MAPS[map_index], uv_alt).rgb);
}
}
float height(vec2 uv) {
return HEIGHT_SCALE * texture(TERRAIN_MAP, uv).a;
}
void vertex() {
VERTEX.y = height(UV);
vec2 texel_size = UV / SIZE;
vec4 h = vec4(
height(UV + (texel_size * vec2(0, -1))),
height(UV + (texel_size * vec2(-1, 0))),
height(UV + (texel_size * vec2( 1, 0))),
height(UV + (texel_size * vec2( 0, 1))));
NORMAL = normalize(vec3(h.y - h.z, 2.0, h.x - h.w));
}