 	tc.z = trunc(mod(tc.y, u_TextureScale.w));
 	Surface suf;
 	suf.tex_coord = tc;
-	suf.high_alt = suf.delta = 0.0;
 	uint meta = texture(t_Meta, tc).x;
+	suf.is_shadowed = (meta & c_ShadowMask) != 0U;
 	suf.low_type = get_terrain_type(meta);
-	suf.high_type = 0U;
 	if ((meta & c_DoubleLevelMask) != 0U) {
 		if (mod(pos.x, 2.0) >= 1.0) {
-			tc.x -= 1.0 / u_TextureScale.x;
+			uint meta_low = textureOffset(t_Meta, tc, ivec2(-1, 0)).x;
 			suf.high_type = suf.low_type;
-			uint meta_low = texture(t_Meta, tc).x;
 			suf.low_type = get_terrain_type(meta_low);
+			suf.delta = get_delta(meta_low) << c_DeltaBits + get_delta(meta);
 		}else {
 			uint meta_high = textureOffset(t_Meta, tc, ivec2(1, 0)).x;
+			suf.tex_coord.x += 1.0 / u_TextureScale.x;
 			suf.high_type = get_terrain_type(meta_high);
+			suf.delta = get_delta(meta) << c_DeltaBits + get_delta(meta_high);
 		}
-		suf.low_alt = texture(t_Height, tc).x * u_TextureScale.z;
-		suf.high_alt = textureOffset(t_Height, tc, ivec2(1, 0)).x * u_TextureScale.z;
+		suf.low_alt = textureOffset(t_Height, suf.tex_coord, ivec2(-1, 0)).x * u_TextureScale.z;
+		suf.high_alt = texture(t_Height, suf.tex_coord).x * u_TextureScale.z;
 	}else {
 		suf.low_alt = texture(t_Height, tc).x * u_TextureScale.z;
+		suf.high_alt = suf.low_alt;
+		suf.high_type = suf.low_type;
+		suf.delta = 0.0;
 	}
 	return suf;
 }

	return t * dir + base;
}

vec4 cast_ray_with_latitude(float level, vec3 base, vec3 dir) {
	vec3 pos = cast_ray_to_plane(level, base, dir);
	Surface suf = get_surface(pos.xy);
	return vec4(pos, suf.low_alt);
}

vec3 cast_ray_to_map(vec3 base, vec3 dir) {
	vec4 a = cast_ray_with_latitude(u_TextureScale.z, base, dir);
	vec4 b = cast_ray_with_latitude(0.0, base, dir);
	vec4 step = (1.0 / float(c_NumForwardSteps + 1U)) * (b - a);
	for (uint i=0U; i<c_NumForwardSteps; ++i) {
		vec4 c = a + step;
		Surface suf = get_surface(c.xy);
		c.w = suf.low_alt;
		if (c.z < c.w) {
			b = c;
			break;
		}else {
			a = c;
		}
	}
	for (uint i=0U; i<c_NumBinarySteps; ++i) {
		vec4 c = 0.5 * (a + b);
		Surface suf = get_surface(c.xy);
		c.w = suf.low_alt;
		if (c.z < c.w) {
			b = c;
		}else {
			a = c;
		}
	}
	//float t = a.z > a.w + 0.1 ? (b.w - a.w - b.z + a.z) / (a.z - a.w) : 0.5;
	float t = 0.5;
	return mix(a.xyz, b.xyz, t);
}

void main() {


const float c_HorFactor = 0.5; //H_CORRECTION
const uint c_DoubleLevelMask = 1U<<6, c_ShadowMask = 1U<<7;
const uint c_TerrainShift = 3U, c_TerrainBits = 3U;
const uint c_DeltaShift = 0U, c_DeltaBits = 2U;
const uint c_NumBinarySteps = 8U, c_NumForwardSteps = 0U;

out vec4 Target0;
