diff --git a/examples/srtm.cpp b/examples/srtm.cpp index 9773f6c6..b6623cb9 100644 --- a/examples/srtm.cpp +++ b/examples/srtm.cpp @@ -39,7 +39,6 @@ // TODO: use LRU cache for tile generation requests, combine with threadpool // TODO: fix frustum culling // TODO: fix seams at tile borders -// TODO: fix normals at closest view // TODO: try a different coordinate system for closer tiles // TODO: use closer near plane, maybe try reversed-Z // TODO: add space, stars, the sun @@ -460,7 +459,47 @@ void main() color = (in_height > 0.0) ? texture(u_colormap, in_height / 8000.0).rgb : texture(u_colormap_neg, -in_height / 10000.0).rgb; })"; -static char const tile_fs[] = +static char const tile_close_gs[] = +R"(#version 330 + +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; + +in vec3 color[]; +in vec3 pos[]; + +out vec3 g_color; +out vec3 g_normal; + +void main() +{ + g_normal = normalize(cross(pos[1] - pos[0], pos[2] - pos[0])); + + for (int i = 0; i < 3; ++i) + { + g_color = color[i]; + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } + EndPrimitive(); +})"; + +static char const tile_close_fs[] = +R"(#version 330 + +uniform vec3 u_light; + +in vec3 g_color; +in vec3 g_normal; +out vec4 out_color; + +void main() +{ + float l = (0.5 + dot(normalize(g_normal), u_light) * 0.5); + out_color = vec4(g_color * l, 1.0); +})"; + +static char const tile_far_fs[] = R"(#version 330 uniform vec3 u_light; @@ -471,10 +510,8 @@ out vec4 out_color; void main() { - vec3 dx = dFdx(pos); - vec3 dy = dFdy(pos); - vec3 n = normalize(cross(dx, dy)); - float l = (0.5 + dot(n, u_light) * 0.5); + vec3 normal = cross(dFdx(pos), dFdy(pos)); + float l = (0.5 + dot(normalize(normal), u_light) * 0.5); out_color = vec4(color * l, 1.0); })"; @@ -496,7 +533,8 @@ struct srtm_app node_controller nodes; - gfx::program tile_program{tile_vs, tile_fs}; + gfx::program tile_close_program{tile_vs, tile_close_gs, tile_close_fs}; + gfx::program tile_far_program{tile_vs, tile_far_fs}; gfx::texture_1d color_map; gfx::texture_1d color_map_neg; @@ -680,12 +718,18 @@ void srtm_app::present() auto const frustum = cg::frustum(camera_transform); (void)frustum; - tile_program.bind(); - tile_program["u_transform"] = camera_transform; - tile_program["u_N"] = static_cast(node_size); - tile_program["u_light"] = geom::vector{0.f, 0.f, 1.f}; - tile_program["u_colormap"] = 0; - tile_program["u_colormap_neg"] = 1; + tile_close_program.bind(); + tile_close_program["u_transform"] = camera_transform; + tile_close_program["u_N"] = static_cast(node_size); + tile_close_program["u_light"] = geom::vector{0.f, 0.f, 1.f}; + tile_close_program["u_colormap"] = 0; + tile_close_program["u_colormap_neg"] = 1; + tile_far_program.bind(); + tile_far_program["u_transform"] = camera_transform; + tile_far_program["u_N"] = static_cast(node_size); + tile_far_program["u_light"] = geom::vector{0.f, 0.f, 1.f}; + tile_far_program["u_colormap"] = 0; + tile_far_program["u_colormap_neg"] = 1; gl::ActiveTexture(gl::TEXTURE0); color_map.bind(); gl::ActiveTexture(gl::TEXTURE1); @@ -805,10 +849,13 @@ void srtm_app::present() gfx::blue }; - tile_program["u_p0"] = v[0]; - tile_program["u_p1"] = v[1]; - tile_program["u_p2"] = v[2]; - tile_program["u_color"] = colors[tile_n % 4]; + auto * program = (level == max_child_level) ? &tile_close_program : &tile_far_program; + + program->bind(); + (*program)["u_p0"] = v[0]; + (*program)["u_p1"] = v[1]; + (*program)["u_p2"] = v[2]; + (*program)["u_color"] = colors[tile_n % 4]; return n->draw(tile_n); }