diff --git a/3d-models.cpp b/3d-models.cpp index 46fd54c8..fbdaa0e3 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -745,13 +745,18 @@ void geometry_information::make_star(hpcshape& sh, ld rad) { void geometry_information::make_euclidean_sky() { bshape(cgi.shEuclideanSky, PPR::EUCLIDEAN_SKY); for(int x=-20; x<20; x++) - for(int y=-20; y<20; y++) + for(int y=-20; y<20; y++) { + auto x0 = x * cgi.LOWSKY; + auto x1 = (x+1) * cgi.LOWSKY; + auto y0 = y * cgi.LOWSKY; + auto y1 = (y+1) * cgi.LOWSKY; hpcsquare( - lzpush(cgi.WALL) * hpxy(x, y), - lzpush(cgi.WALL) * hpxy(x, y+1), - lzpush(cgi.WALL) * hpxy(x+1, y), - lzpush(cgi.WALL) * hpxy(x+1, y+1) + lzpush(cgi.LOWSKY) * hpxy(x0, y0), + lzpush(cgi.LOWSKY) * hpxy(x0, y1), + lzpush(cgi.LOWSKY) * hpxy(x1, y0), + lzpush(cgi.LOWSKY) * hpxy(x1, y1) ); + } } /** res[0] and res[1] place H on the plane, while res[2] is the altitude */ @@ -1118,13 +1123,10 @@ void geometry_information::make_3d_models() { make_ball(shDisk, orbsize*.2, 2); make_ball(shHeptaMarker, zhexf*.2, 1); make_ball(shSnowball, zhexf*.1, 1); - if(euclid) { - make_ball(shSun, 0.5, 2); - make_euclidean_sky(); - } - else - make_star(shSun, 3); - make_star(shNightStar, euclid ? 0.05 : 0.75); + make_ball(shSkyboxSun, 8 * zhexf, 2); + if(euclid) make_euclidean_sky(); + make_star(shSun, vid.sun_size * zhexf); + make_star(shNightStar, vid.star_size * zhexf); if(WDIM == 2) { for(int i=0; i<3; i++) { diff --git a/config.cpp b/config.cpp index 63248fa7..1849f523 100644 --- a/config.cpp +++ b/config.cpp @@ -325,6 +325,7 @@ void non_editable() { void float_setting::show_edit_option(int key) { if(modify_me) modify_me(this); dialog::addSelItem(XLAT(menu_item_name), fts(*value) + unit, key); + if(*value == use_the_default_value) dialog::lastItem().value = XLAT("default"); dialog::add_action([this] () { add_to_changed(this); dialog::editNumber(*value, min_value, max_value, step, dft, XLAT(menu_item_name), help_text); @@ -2368,6 +2369,45 @@ EX void show_spatial_embedding() { dialog::display(); } +EX void show3D_height_details() { + cmode = sm::SIDE | sm::MAYDARK; + gamescreen(); + dialog::init(XLAT("3D detailed settings")); + + add_edit(vid.wall_height); + + dialog::addBreak(50); + + add_edit(vid.rock_wall_ratio); + add_edit(vid.human_wall_ratio); + add_edit(vid.lake_top); + add_edit(vid.lake_shallow); + add_edit(vid.lake_bottom); + + dialog::addBreak(50); + + if(embedded_plane) { + add_edit(auto_remove_roofs); + add_edit(vid.wall_height2); + add_edit(vid.wall_height3); + add_edit(draw_sky); + add_edit(vid.lowsky_height); + add_edit(vid.sky_height); + add_edit(vid.star_height); + add_edit(vid.infdeep_height); + add_edit(vid.sun_size); + add_edit(vid.star_size); + add_edit(vid.height_limits); + if(euclid && msphere) add_edit(use_euclidean_infinity); + } + else dialog::addInfo(XLAT("more options in 3D engine")); + + dialog::addBreak(100); + + dialog::addBack(); + dialog::display(); + } + EX void show3D() { cmode = sm::SIDE | sm::MAYDARK; gamescreen(); @@ -2411,11 +2451,9 @@ EX void show3D() { dialog::addBreak(50); add_edit(vid.wall_height); + dialog::addSelItem("height details", "", 'D'); + dialog::add_action_push(show3D_height_details); - add_edit(vid.rock_wall_ratio); - add_edit(vid.human_wall_ratio); - add_edit(vid.lake_top); - add_edit(vid.lake_bottom); if(scale_used()) add_edit(vid.creature_scale); } @@ -2584,7 +2622,10 @@ EX int config3 = addHook(hooks_configfile, 100, [] { param_b(numerical_minefield, "numerical_minefield") ->editable("display mine counts numerically", 'n'); param_b(dont_display_minecount, "dont_display_minecount"); - param_b(draw_sky, "draw sky", true); + param_enum(draw_sky, "draw_sky", "draw_sky", skyAutomatic) + -> editable({{"NO", "do not draw sky"}, {"automatic", ""}, {"skybox", "works only in Euclidean"}, {"always", "might be glitched in some settings"}}, "sky rendering", 's'); + param_b(use_euclidean_infinity, "use_euclidean_infinity", true) + -> editable("infinite sky", 'i'); param_f(linepatterns::parallel_count, "parallel_count") ->editable(0, 24, 1, "number of parallels drawn", "", 'n'); param_f(linepatterns::parallel_max, "parallel_max") @@ -2688,10 +2729,44 @@ EX int config3 = addHook(hooks_configfile, 100, [] { fts(cosh(vid.depth - vid.wall_height * vid.human_wall_ratio) / cosh(vid.depth))) ); }); - param_f(vid.lake_top, "lake_top", "3D lake top", .25) + param_f(vid.lake_top, "lake_top", "3D lake top", .25 / 0.3) ->editable(0, 1, .1, "Level of water surface", "", 'l'); - param_f(vid.lake_bottom, "lake_bottom", "3D lake bottom", .9) + param_f(vid.lake_shallow, "lake_shallow", "3D lake shallow", .4 / 0.3) + ->editable(0, 1, .1, "Level of shallow water", "", 's'); + param_f(vid.lake_bottom, "lake_bottom", "3D lake bottom", .9 / 0.3) ->editable(0, 1, .1, "Level of water bottom", "", 'k'); + param_f(vid.wall_height2, "wall_height2", "wall_height2", 2) + ->editable(0, 5, .1, "ratio of high walls to normal walls", "", '2'); + param_f(vid.wall_height3, "wall_height3", "wall_height3", 3) + ->editable(0, 5, .1, "ratio of very high walls to normal walls", "", '3'); + param_f(vid.lowsky_height, "lowsky_height", "lowsky_height", 2) + ->editable(0, 5, .1, "lowsky height", "", '4'); + param_f(vid.sky_height, "sky_height", "sky_height", use_the_default_value) + ->editable(0, 10, .1, "altitude of the sky", "", '5') + ->set_extra([] { + dialog::addSelItem(XLAT("use the default value"), 0, 'D'); + dialog::add_action([] { vid.sky_height = use_the_default_value; }); + }); + param_f(vid.star_height, "star_height", "star_height", use_the_default_value) + ->editable(0, 10, .1, "altitude of the stars", "", '6') + ->set_extra([] { + dialog::addSelItem(XLAT("use the default value"), 0, 'D'); + dialog::add_action([] { vid.star_height = use_the_default_value; }); + }); + param_f(vid.infdeep_height, "infdeep_height", "infdeep_height", use_the_default_value) + ->editable(0, 10, .1, "infinite depth", "", '7') + ->set_extra([] { + dialog::addSelItem(XLAT("use the default value"), 0, 'D'); + dialog::add_action([] { vid.infdeep_height = use_the_default_value; }); + }); + param_f(vid.sun_size, "sun_size", "sun_size", 8) + ->editable(0, 10, .1, "sun size (relative to item sizes)", "", '8'); + param_f(vid.star_size, "star_size", "star_size", 0.75) + ->editable(0, 10, .1, "night star size (relative to item sizes)", "", '9'); + param_b(vid.height_limits, "height_limits", true) + ->editable("automatically limit heights if too high", 'l'); + param_b(auto_remove_roofs, "auto_remove_roofs", true) + ->editable("do not render higher levels if camera too high", 'r'); addsaver(vid.tc_depth, "3D TC depth", 1); addsaver(vid.tc_camera, "3D TC camera", 2); addsaver(vid.tc_alpha, "3D TC alpha", 3); diff --git a/drawing.cpp b/drawing.cpp index 25b59b32..687b2ac4 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -727,7 +727,7 @@ void dqi_poly::gldraw() { glhr::color2(color, (flags & POLY_INTENSE) ? 2 : 1); glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE); glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY); - glhr::set_fogbase(prio == PPR::SKY ? 1.0 + (euclid ? 20 : 5 / sightranges[geometry]) : 1.0); + glhr::set_fogbase(prio == PPR::SKY ? 1.0 + ((abs(cgi.SKY - cgi.LOWSKY)) / sightranges[geometry]) : 1.0); glDrawArrays(GL_TRIANGLES, ioffset, cnt); } else { @@ -2456,7 +2456,7 @@ EX void drawqueue() { #endif #if MAXMDIM >= 4 && CAP_GL - if(embedded_plane && (hyperbolic || cgi.emb->is_sph_in_low() || cgi.emb->is_in_noniso()) && !vrhr::rendering()) make_air(); + make_air(); #endif #if CAP_VR diff --git a/embeddings.cpp b/embeddings.cpp index 616848db..e5c351fb 100644 --- a/embeddings.cpp +++ b/embeddings.cpp @@ -271,6 +271,7 @@ EX } virtual ld anim_center_z() { return center_z(); } virtual hyperpoint anim_tile_center(); virtual void logical_fix(transmatrix&) = 0; + virtual ld height_limit(ld sign); virtual bool is_euc_in_product() { return false; } virtual bool is_product_embedding() { return false; } @@ -283,7 +284,6 @@ EX } virtual bool is_euc_in_nil() { return false; } virtual bool is_euc_in_noniso() { return false; } virtual bool is_in_noniso() { return false; } - virtual bool is_depth_limited() { return false; } virtual bool is_cylinder() { return false; } virtual bool no_spin() { return false; } @@ -307,6 +307,21 @@ EX } EX geometry_information *swapper; +ld embedding_method::height_limit(ld sign) { + if(sign > 0) { + if(hyperbolic || sol || nih || sl2 || in_h2xe()) return 5; + if(sphere || nil || in_s2xe()) return M_PI/2; + return 100; + } + if(sign < 0) { + if(center_z()) return -center_z(); + if(hyperbolic || sol || nih || sl2 || in_h2xe()) return -5; + if(sphere || nil || in_s2xe()) return -M_PI/2; + return -100; + } + return 0; + } + hyperpoint embedding_method::tile_center() { ld z = center_z(); if(z == 0) return C0; @@ -608,7 +623,6 @@ struct emb_euc_in_hyp : emb_actual { struct emb_sphere_in_low : emb_actual { bool is_sph_in_low() override { return true; } - bool is_depth_limited() override { return true; } transmatrix intermediate_to_actual_translation(hyperpoint i) override { return map_relative_push(logical_to_actual(i)) * zpush(-1); } @@ -757,7 +771,6 @@ struct emb_euc_in_sl2 : emb_euclid_noniso { struct emb_euc_cylinder : emb_euclid_noniso { bool is_cylinder() override { return true; } ld center_z() override { return 1; } - bool is_depth_limited() override { return true; } transmatrix get_lsti() override { return cspin90(0, 1); } hyperpoint actual_to_intermediate(hyperpoint a) override { ld z0 = asin_auto(hypot(a[1], a[2])); @@ -845,9 +858,11 @@ struct emb_euc_cylinder_sl2 : emb_euc_cylinder_twisted { } }; +/** Clifford torus */ struct emb_euc_in_sph : emb_euclid_noniso { bool is_euc_in_sph() override { return true; } ld center_z() override { return 1; } + virtual ld height_limit(ld sign) { return sign < 0 ? 0 : 90._deg; } hyperpoint actual_to_intermediate(hyperpoint a) override { ld tx = hypot(a[0], a[2]); ld ty = hypot(a[1], a[3]); diff --git a/geometry.cpp b/geometry.cpp index 5e903f5a..d71e8979 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -236,7 +236,7 @@ struct geometry_information { BODY, BODY1, BODY2, BODY3, NECK1, NECK, NECK3, HEAD, HEAD1, HEAD2, HEAD3, ALEG0, ALEG, ABODY, AHEAD, BIRD, LOWSKY, SKY, HIGH, HIGH2, - SHALLOW; + HELL, STAR, SHALLOW; ld human_height, slev; ld eyelevel_familiar, eyelevel_human, eyelevel_dog; @@ -308,7 +308,7 @@ hpcshape shKnife, shTongue, shFlailMissile, shTrapArrow, shPirateHook, shSmallPirateHook, shPirateHood, shEyepatch, shPirateX, // shScratch, - shHeptaMarker, shSnowball, shHugeDisk, shSun, shNightStar, shEuclideanSky, + shHeptaMarker, shSnowball, shHugeDisk, shSkyboxSun, shSun, shNightStar, shEuclideanSky, shSkeletonBody, shSkull, shSkullEyes, shFatBody, shWaterElemental, shPalaceGate, shFishTail, shMouse, shMouseLegs, shMouseEyes, @@ -991,10 +991,9 @@ EX namespace geom3 { BIRD = 1.20; SHALLOW = .95; STUFF = 1; - LOWSKY = SKY = HIGH = HIGH2 = 1; + LOWSKY = SKY = HIGH = HIGH2 = STAR = 1; } else { - INFDEEP = GDIM == 3 ? (sphere ? 90._deg : +5) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera); ld wh = actual_wall_height(); WALL = lev_to_factor(wh); FLOOR = lev_to_factor(0); @@ -1041,36 +1040,43 @@ EX namespace geom3 { slev = vid.rock_wall_ratio * wh / 3; for(int s=0; s<=3; s++) SLEV[s] = lev_to_factor(vid.rock_wall_ratio * wh * s/3); - LAKE = lev_to_factor(sgn * -vid.lake_top); - SHALLOW = lev_to_factor(sgn * -.4); + LAKE = lev_to_factor(sgn * wh * -vid.lake_top); + SHALLOW = lev_to_factor(sgn * wh * -vid.lake_shallow); HELLSPIKE = lev_to_factor(sgn * -(vid.lake_top+vid.lake_bottom)/2); BOTTOM = lev_to_factor(sgn * -vid.lake_bottom); - LOWSKY = lev_to_factor(2 * wh); - HIGH = LOWSKY; - HIGH2 = lev_to_factor(3 * wh); - SKY = LOWSKY - sgn * 5; + LOWSKY = lev_to_factor(vid.lowsky_height * wh); + HIGH = lev_to_factor(vid.wall_height2 * wh); + HIGH2 = lev_to_factor(vid.wall_height3 * wh); + SKY = vid.sky_height == use_the_default_value ? cgi.emb->height_limit(-sgn) : lev_to_factor(vid.sky_height * wh); + STAR = vid.star_height == use_the_default_value ? lerp(FLOOR, SKY, 0.95) : lev_to_factor(vid.star_height * wh); + HELL = -SKY; + if(embedded_plane) + INFDEEP = vid.infdeep_height == use_the_default_value ? cgi.emb->height_limit(sgn) : lev_to_factor(vid.infdeep_height * wh); + else + INFDEEP = (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(vid.camera); /* in spherical/cylindrical case, make sure that the high stuff does not go through the center */ - if(cgi.emb->is_depth_limited()) { - ld max_high = lerp(-FLOOR, -1, 0.8); - ld max_high2 = lerp(-FLOOR, -1, 0.9); - if(HIGH < max_high) HIGH = max_high; - if(HIGH2 < max_high2) HIGH2 = max_high2; - if(LOWSKY < max_high) LOWSKY = max_high; - if(SKY < max_high) SKY = max_high; - if(vid.wall_height < 0) { - SKY = -3 * vid.wall_height; - LOWSKY = 1.75 * SKY; - } - if(SHALLOW < max_high) SHALLOW = max_high; - if(LAKE < max_high) LAKE = max_high; - if(BOTTOM < max_high2) BOTTOM = max_high2; - if(HELLSPIKE < max_high) HELLSPIKE = max_high; - if(sgn < 0) INFDEEP = -1; + if(vid.height_limits) { + auto hp = cgi.emb->height_limit(1); + auto hn = cgi.emb->height_limit(-1); + auto adjust = [&] (ld& val, ld& guide, ld lerpval) { + if(val > hp) + val = lerp(guide, hp, lerpval); + else if(val < hn) + val = lerp(guide, hn, lerpval); + }; + adjust(HIGH, FLOOR, 0.8); + adjust(HIGH2, HIGH, 0.5); + adjust(SKY, FLOOR, 1); + adjust(STAR, FLOOR, 0.9); + adjust(LAKE, FLOOR, 0.8); + adjust(SHALLOW, LAKE, 0.9); + adjust(BOTTOM, SHALLOW, 0.5); + adjust(INFDEEP, FLOOR, 1); } - if(cgi.emb->is_euc_in_hyp() && sgn < 0) INFDEEP = FLOOR - 5; + println(hlog, "WALL = ", WALL, " LOWSKY = ", LOWSKY, " SKY = ", SKY, " STAR = ", STAR, " INFDEEP = ", INFDEEP, " wh = ", wh); } } @@ -1269,6 +1275,15 @@ EX string cgi_string() { V("LB", fts(vid.lake_bottom)); if(GDIM == 3 && vid.pseudohedral) V("PS", fts(vid.depth_bonus)); + V("LS", fts(vid.lake_shallow)); + V("SSu", fts(vid.sun_size)); + V("SSt", fts(vid.star_size)); + V("WH2", fts(vid.wall_height2)); + V("WH3", fts(vid.wall_height3)); + V("WHL", fts(vid.lowsky_height)); + if(vid.sky_height != use_the_default_value) V("SHe", fts(vid.sky_height)); + if(vid.star_height != use_the_default_value) V("StH", fts(vid.star_height)); + if(vid.infdeep_height != use_the_default_value) V("ID", fts(vid.infdeep_height)); } V("3D", ONOFF(vid.always3)); diff --git a/hyper.h b/hyper.h index 0f573dd0..36aee3ca 100644 --- a/hyper.h +++ b/hyper.h @@ -313,6 +313,8 @@ struct projection_configuration { enum eThreatLevel { tlNoThreat, tlSpam, tlNormal, tlHighThreat }; +constexpr ld use_the_default_value = -20.0625; + struct videopar { projection_configuration projection_config, rug_config; ld yshift; @@ -416,7 +418,9 @@ struct videopar { ld depth; // world level below the plane ld camera; // camera level above the plane ld wall_height, creature_scale, height_width; - ld lake_top, lake_bottom; + ld lake_top, lake_bottom, lake_shallow, wall_height2, wall_height3; + ld lowsky_height, sky_height, star_height, infdeep_height, star_size, sun_size; + bool height_limits; ld rock_wall_ratio; ld human_wall_ratio; bool pseudohedral; // in 3D modes diff --git a/sky.cpp b/sky.cpp index 50879817..59f113c3 100644 --- a/sky.cpp +++ b/sky.cpp @@ -5,10 +5,18 @@ namespace hr { EX bool context_fog = true; EX ld camera_level; -EX bool draw_sky = true; EX bool camera_sign; +#if HDR +enum eSkyMode { skyNone, skyAutomatic, skySkybox, skyAlways }; +#endif + +EX eSkyMode draw_sky; + +EX bool auto_remove_roofs; + EX bool camera_over(ld x) { + if(!auto_remove_roofs) return false; if(camera_sign) return camera_level <= x; return camera_level >= x; } @@ -41,16 +49,22 @@ struct dqi_sky : drawqueueitem { EX struct dqi_sky *sky; +EX bool do_draw_skybox() { + if(no_wall_rendering) return false; + if(!euclid) return false; + if(draw_sky == skySkybox) return true; + if(!embedded_plane) return false; + if(draw_sky == skyAutomatic) return !cgi.emb->is_sph_in_low() && !cgi.emb->is_cylinder(); + return false; + } + EX void prepare_sky() { sky = NULL; - if(euclid && !cgi.emb->is_sph_in_low() && !cgi.emb->is_cylinder()) { - if(WDIM == 3 || GDIM == 2) return; - if(no_wall_rendering) return; - if(!draw_sky) return; + if(do_draw_skybox()) { shiftmatrix T = ggmatrix(currentmap->gamestart()); T.T = gpushxto0(tC0(T.T)) * T.T; queuepoly(T, cgi.shEuclideanSky, 0x0044e4FF); - queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY); + queuepolyat(T * zpush(cgi.STAR * 0.7) * xpush(cgi.STAR * 0.7), cgi.shSkyboxSun, 0xFFFF00FF, PPR::SKY); } else { sky = &queuea (euclid ? PPR::EUCLIDEAN_SKY : PPR::MISSILE); @@ -66,17 +80,35 @@ EX void delete_sky() { skyvertices.clear(); } +EX bool do_draw_sky() { + if(!embedded_plane) return false; + if(draw_sky == skyAlways) return true; + if(draw_sky != skyAutomatic) return false; + + if(vid.wall_height < 0 && cgi.emb->is_euc_in_hyp()) return false; /* just looks bad, hollow horospheres should not have sky */ + if(vid.wall_height < 0 && meuclid && geom3::ggclass() == gcNIH) return false; /* same */ + if(among(geom3::ggclass(), gcSol, gcSolN)) return false; /* errors */ + if(among(geom3::ggclass(), gcNil)) return false; /* errors sometimes too */ + if(cgi.emb->is_hyp_in_solnih()) return false; + if(cgi.emb->is_euc_in_product()) return false; + if(cgi.emb->is_euc_in_sl2()) return false; + if(cgi.emb->is_cylinder()) return false; + + return true; + } + +EX bool do_draw_stars(bool rev) { + if(!do_draw_sky()) return false; + if(cgi.emb->is_sph_in_low()) { + if(cgi.SKY < 0) return false; + } + if(cgi.emb->is_euc_in_hyp() && (rev ? cgi.SKY > 0 : cgi.SKY < 0)) return false; + return true; + } + void compute_skyvertices(const vector& sky) { skyvertices.clear(); - if(!draw_sky) return; - if(vid.wall_height < 0 && cgi.emb->is_euc_in_hyp()) return; /* just looks bad, hollow horospheres should not have sky */ - if(vid.wall_height < 0 && meuclid && geom3::ggclass() == gcNIH) return; /* same */ - if(among(geom3::ggclass(), gcSol, gcSolN)) return; /* errors */ - if(among(geom3::ggclass(), gcNil)) return; /* errors sometimes too */ - if(cgi.emb->is_hyp_in_solnih()) return; - if(cgi.emb->is_euc_in_product()) return; - if(cgi.emb->is_euc_in_sl2()) return; - if(cgi.emb->is_cylinder()) return; + if(!do_draw_sky()) return; int sk = get_skybrightness(); @@ -87,10 +119,10 @@ void compute_skyvertices(const vector& sky) { ); hyperpoint skypoint = cpush0(2, cgi.SKY); - hyperpoint hellpoint = cpush0(2, -cgi.SKY); + hyperpoint hellpoint = cpush0(2, cgi.HELL); vector this_poly; - + for(const sky_item& si: sky) { auto c = si.c; @@ -271,7 +303,7 @@ void compute_skyvertices(const vector& sky) { void dqi_sky::draw() { if(!vid.usingGL || sky.empty() || skyvertices.empty()) return; - if(!draw_sky) { delete_sky(); return; } + if(!do_draw_sky()) { delete_sky(); return; } #if CAP_VR transmatrix s = (vrhr::rendering() ? vrhr::master_cview : cview()).T * inverse(sky_cview.T); @@ -279,7 +311,8 @@ void dqi_sky::draw() { transmatrix s = cview().T * inverse(sky_cview.T); #endif - if(euclid) be_euclidean_infinity(s); + be_euclidean_infinity(s); + for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) { if(global_projection && global_projection != ed) continue; current_display->next_shader_flags = GF_VARCOLOR; @@ -292,7 +325,7 @@ void dqi_sky::draw() { glapplymatrix(s); } glhr::prepare(skyvertices); - glhr::set_fogbase(1.0 + 5 / sightranges[geometry]); + glhr::set_fogbase(1.0 + abs(cgi.SKY - cgi.LOWSKY) / sightranges[geometry]); glhr::set_depthtest(model_needs_depth() && prio < PPR::SUPERLINE); glhr::set_depthwrite(model_needs_depth() && prio != PPR::TRANSPARENT_SHADOW && prio != PPR::EUCLIDEAN_SKY); glDrawArrays(GL_TRIANGLES, 0, isize(skyvertices)); @@ -306,28 +339,22 @@ color_t skycolor(cell *c) { return gradient(0x4040FF, 0xFFFFFF, 0, z, 63); } +EX bool use_euclidean_infinity = true; + /** move an Euclidean matrix to V(C0) == C0 */ -EX void be_euclidean_infinity(transmatrix& V) { for(int i=0; i<3; i++) V[i][3] = 0; } +EX void be_euclidean_infinity(transmatrix& V) { + if(euclid && msphere && use_euclidean_infinity) + for(int i=0; i<3; i++) V[i][3] = 0; + } void draw_star(const shiftmatrix& V, const hpcshape& sh, color_t col, ld rev = false) { - ld star_val = 2; - bool have_stars = cgi.emb->is_same_in_same() || cgi.emb->is_sph_in_low() || cgi.emb->is_euc_in_hyp(); - if(cgi.emb->is_sph_in_low()) { - if(cgi.SKY < 0) have_stars = false; - if(euclid) star_val = 1.8; - } - if(cgi.emb->is_euc_in_hyp() && (rev ? cgi.SKY > 0 : cgi.SKY < 0)) have_stars = false; - if(!have_stars) return; - ld val = cgi.SKY+star_val; + if(!do_draw_stars(rev)) return; + + ld val = cgi.STAR; if(rev) val = -val; - if(euclid) { - auto V1 = V; be_euclidean_infinity(V1.T); - queuepolyat(V1 * zpush(val), sh, col, PPR::EUCLIDEAN_SKY); - } - else { - queuepolyat(V * zpush(val), sh, col, PPR::SKY); - } + auto V1 = V; be_euclidean_infinity(V1.T); + queuepolyat(V1 * zpush(val), sh, col, PPR::SKY); } void celldrawer::draw_ceiling() { @@ -341,7 +368,6 @@ void celldrawer::draw_ceiling() { switch(ceiling_category(c)) { /* ceilingless levels */ case 1: { - if(euclid && !cgi.emb->is_sph_in_low()) return; if(fieldpattern::fieldval_uniq(c) % 3 == 0) draw_star(V, cgi.shNightStar, 0xFFFFFFFF); add_to_sky(0x00000F, 0x00000F); @@ -356,7 +382,6 @@ void celldrawer::draw_ceiling() { } case 2: { - if(euclid && !cgi.emb->is_sph_in_low()) return; color_t col; color_t skycol; @@ -464,7 +489,6 @@ void celldrawer::draw_ceiling() { placeSidewall(c, i, SIDE_HIGH2, V, darkena(wcol2, fd, 0xFF)); } if(among(c->wall, waClosedGate, waOpenGate) && qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], 0x202020FF, PPR::WALL); - if(euclid) return; draw_star(V, cgi.shNightStar, 0xFFFFFFFF); break; @@ -517,7 +541,6 @@ void celldrawer::draw_ceiling() { else if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL); - if(euclid) return; draw_star(V, cgi.shNightStar, 0xFFFFFFFF); break; } @@ -539,6 +562,7 @@ EX void swap_if_missing(bool missing) { EX void make_air() { if(!sky) return; + if(!embedded_plane) return; if(centerover != sky_centerover) { sky_centerover = centerover; @@ -547,6 +571,7 @@ EX void make_air() { } if(!context_fog) return; + if(vrhr::rendering()) return; const int AIR_TEXTURE = 512; if(!airbuf) {