         // it can be X axis, Y axis, or the depth
         vec2 cell_id = floor(vec2(ipos) / float(1 << lod)); // careful!
         ivec2 cell_tl = ivec2(cell_id) << lod;
-        vec2 cell_offset = float(1 << lod) * step(0.0, view.xy) - point.xy + vec2(cell_tl);
-        vec3 units = vec3(cell_offset, height - point.z) / view;
+        vec2 cell_offset = float(1 << lod) * step(0.0, dir.xy) - point.xy + vec2(cell_tl);
+        vec3 units = vec3(cell_offset, height - point.z) / dir;
         float min_side_unit = min(units.x, units.y);
 
         // advance the point
-        point += min(units.z, min_side_unit) * view;
+        point += min(units.z, min_side_unit) * dir;
         ipos = ivec2(floor(point.xy));
         iter++;
 

        }
    }

    /*
    CastPoint pt = cast_ray_to_map(near_plane, view);

    float lit_factor;
    if (pt.is_underground) {
        lit_factor = 0.25;
    } else {
        vec3 light_vec = normalize(u_LightPos.xyz - pt.pos * u_LightPos.w);
        vec3 a = pt.pos;
        vec3 outside = cast_ray_to_plane(u_TextureScale.z, a, light_vec);
        vec3 b = outside;

        Surface suf = cast_ray_impl(a, b, true, 4, 4);
        if (suf.delta != 0.0 && b.z < suf.low_alt + suf.delta) {
            // continue casting overground
            a = b; b = outside;
            cast_ray_impl(a, b, true, 3, 3);
        }
        lit_factor = b == outside ? 1.0 : 0.5;
    }

    vec4 frag_color = color_point(pt, lit_factor);

    if (pt.type == TERRAIN_WATER) {
        vec3 a = pt.pos;
        vec2 variance = mod(a.xy, c_ReflectionVariance);
        vec3 reflected = normalize(view * vec3(1.0 + variance, -1.0));
        vec3 outside = cast_ray_to_plane(u_TextureScale.z, a, reflected);
        vec3 b = outside;

        Surface suf = cast_ray_impl(a, b, true, 4, 4);
        if (b != outside) {
            CastPoint other;
            other.pos = b;
            other.type = suf.high_type;
            other.tex_coord = suf.tex_coord;
            //other.is_shadowed = suf.is_shadowed;
            vec4 ref_color = color_point(other, 0.8);
            frag_color += c_ReflectionPower * ref_color;
        }
    }*/

    //vec3 point = cast_ray_to_plane(0.0, near_plane, view);
    Surface surface = get_surface(point.xy);
    Target0 = evaluate_color(surface.high_type, surface.tex_coord, point.z / u_TextureScale.z, 1.0);
    //Target0 = vec4(iter == u_Params.y ? 1.0 : 0.0, float(iter) / float(u_Params.y), 0.0, 1.0);

    vec4 target_ndc = u_ViewProj * vec4(point, 1.0);
    gl_FragDepth = target_ndc.z / target_ndc.w * 0.5 + 0.5;

    float t = (level - base.z) / dir.z;
    return t * dir + base;
}

vec3 cast_ray(vec3 point, vec3 dir) {
    uint lod = u_Params.x;
    ivec2 ipos = ivec2(floor(point.xy)); // integer coordinate of the cell
    uint iter = 0U;
    while (iter < u_Params.y) {
