From 8eb3fa65e255fa14309d2dda6579e63f61c819cd Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 20 May 2019 13:40:56 +0200 Subject: [PATCH] 2D3D:: skies and ceilings --- 3d-models.cpp | 2 + floorshapes.cpp | 25 +++---- geometry.cpp | 6 +- graph.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ hyper.h | 5 +- polygons.cpp | 9 ++- shaders.cpp | 27 ++++++-- 7 files changed, 228 insertions(+), 25 deletions(-) diff --git a/3d-models.cpp b/3d-models.cpp index 7bdcc535..71e20e36 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -1070,6 +1070,8 @@ void make_3d_models() { make_ball(shDisk, orbsize*.2, 2); make_ball(shHeptaMarker, zhexf*.2, 1); make_ball(shSnowball, zhexf*.1, 0); + make_ball(shSun, 3, 5); + make_ball(shNightStar, 0.75, 2); if(WDIM == 2) { for(int i=0; i<3; i++) diff --git a/floorshapes.cpp b/floorshapes.cpp index 5ae79ef0..8b0c2d27 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -712,43 +712,44 @@ void set_floor(const transmatrix& spin, hpcshape& sh) { qfi.usershape = -1; } -void draw_shapevec(cell *c, const transmatrix& V, const vector &shv, color_t col, PPR prio = PPR::DEFAULT) { - if(!c) queuepolyat(V, shv[0], col, prio); - else if(WDIM == 3) ; +dqi_poly *draw_shapevec(cell *c, const transmatrix& V, const vector &shv, color_t col, PPR prio = PPR::DEFAULT) { + if(!c) return &queuepolyat(V, shv[0], col, prio); + else if(WDIM == 3) return NULL; #if CAP_GP else if(GOLDBERG) { int id = gp::get_plainshape_id(c); - if(isize(shv) > id) queuepolyat(V, shv[id], col, prio); + if(isize(shv) > id) return &queuepolyat(V, shv[id], col, prio); + return NULL; } #endif #if CAP_IRR else if(IRREGULAR) { int id = irr::cellindex[c]; if(id < 0 || id >= isize(shv)) { - return; + return NULL; } - queuepolyat(V, shv[id], col, prio); + return &queuepolyat(V, shv[id], col, prio); } #endif #if CAP_ARCM else if(archimedean) { - queuepolyat(V, shv[arcm::id_of(c->master)], col, prio); + return &queuepolyat(V, shv[arcm::id_of(c->master)], col, prio); } #endif else if((euclid || GOLDBERG) && ishex1(c)) - queuepolyat(V * pispin, shv[0], col, prio); + return &queuepolyat(V * pispin, shv[0], col, prio); else if(!(S7&1) && PURE) { auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, 0); if(si.id == 8) si.dir++; transmatrix D = applyPatterndir(c, si); - queuepolyat(V*D, shv[pseudohept(c)], col, prio); + return &queuepolyat(V*D, shv[pseudohept(c)], col, prio); } else if(geosupport_threecolor() == 2) - queuepolyat(V, shv[pseudohept(c)], col, prio); + return &queuepolyat(V, shv[pseudohept(c)], col, prio); else if(binarytiling) - queuepolyat(V, shv[c->type-6], col, prio); + return &queuepolyat(V, shv[c->type-6], col, prio); else - queuepolyat(V, shv[ctof(c)], col, prio); + return &queuepolyat(V, shv[ctof(c)], col, prio); } void draw_floorshape(cell *c, const transmatrix& V, const floorshape &fsh, color_t col, PPR prio = PPR::DEFAULT) { diff --git a/geometry.cpp b/geometry.cpp index f0c25160..17870b04 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -268,7 +268,7 @@ namespace geom3 { LEG0, LEG1, LEG, LEG3, GROIN, GROIN1, GHOST, BODY, BODY1, BODY2, BODY3, NECK1, NECK, NECK3, HEAD, HEAD1, HEAD2, HEAD3, - ALEG0, ALEG, ABODY, AHEAD, BIRD; + ALEG0, ALEG, ABODY, AHEAD, BIRD, LOWSKY, SKY; string invalid; @@ -335,7 +335,7 @@ namespace geom3 { BIRD = 1.20; } else { - INFDEEP = GDIM == 3 ? (sphere ? M_PI/2 : +10) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(camera); + INFDEEP = GDIM == 3 ? (sphere ? M_PI/2 : +5) : (euclid || sphere) ? 0.01 : lev_to_projection(0) * tanh(camera); ld wh = actual_wall_height(); WALL = lev_to_factor(wh); FLOOR = lev_to_factor(0); @@ -381,6 +381,8 @@ namespace geom3 { LAKE = lev_to_factor(-lake_top); HELLSPIKE = lev_to_factor(-(lake_top+lake_bottom)/2); BOTTOM = lev_to_factor(-lake_bottom); + LOWSKY = lev_to_factor((1 + rock_wall_ratio) * wh); + SKY = LOWSKY - 5; } } diff --git a/graph.cpp b/graph.cpp index 97388bf5..4ea01e0b 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4473,6 +4473,180 @@ void queue_transparent_wall(const transmatrix& V, hpcshape& sh, color_t color) { } } +int ceiling_category(cell *c) { + switch(c->land) { + case laNone: + case laMemory: + case laMirrorWall2: + case laMirrored: + case laMirrored2: + case landtypes: + return 0; + + /* starry levels */ + case laIce: + case laCrossroads: + case laCrossroads2: + case laCrossroads3: + case laCrossroads4: + case laCrossroads5: + case laJungle: + case laGraveyard: + case laMotion: + case laRedRock: + case laZebra: + case laHunting: + case laEAir: + case laStorms: + case laMountain: + case laHaunted: + case laHauntedWall: + case laHauntedBorder: + case laWhirlwind: + case laDragon: + case laBurial: + case laHalloween: + case laReptile: + case laVolcano: + case laBlizzard: + case laDual: + case laWestWall: + case laAsteroids: + return 1; + + case laWineyard: + case laDesert: + case laAlchemist: + case laDryForest: + case laCaribbean: + case laMinefield: + case laOcean: + case laWhirlpool: + case laLivefjord: + case laEWater: + case laOceanWall: + case laWildWest: + case laOvergrown: + case laClearing: + case laRose: + case laWarpCoast: + case laWarpSea: + case laEndorian: + case laTortoise: + case laPrairie: + case laSnakeNest: + case laDocks: + case laKraken: + case laBrownian: + return 2; + + case laBarrier: + case laCaves: + case laMirror: + case laMirrorOld: + case laRlyeh: + case laHell: + case laCocytus: + case laEmerald: + case laDeadCaves: + case laPower: + case laHive: + case laCamelot: + case laTemple: + case laPalace: + case laPrincessQuest: + case laIvoryTower: + case laEFire: + case laEEarth: + case laElementalWall: + case laCanvas: + case laTrollheim: + case laDungeon: + case laBull: + case laCA: + case laMirrorWall: + case laTerracotta: + case laMercuryRiver: + case laRuins: + case laMagnetic: + case laSwitch: + case laVariant: + return 3; + + default: + return 4; + } + } + +ld camera_level; + +int get_skybrightness() { + ld s = 1 - (camera_level - geom3::WALL) / -2; + if(s > 1) return 255; + if(s < 0) return 0; + return int(s * 255); + } + +void draw_ceiling(cell *c, const transmatrix& V, int fd, color_t& fcol, color_t& wcol) { + + if(pmodel != mdPerspective || sphere) return; + + switch(ceiling_category(c)) { + /* ceilingless levels */ + case 1: { + if(fieldpattern::fieldval_uniq(c) % 3 == 0) { + auto &star = queuepolyat(V * zpush(geom3::SKY+0.5), shNightStar, 0xFFFFFFFF, PPR::SKY); + star.tinf = NULL; + star.flags |= POLY_INTENSE; + } + int sk = get_skybrightness(); + if(sk > 0) { + auto sky = draw_shapevec(c, V, shFullFloor.levels[SIDE_SKY], 0x000000FF + 0x100 * (sk/17), PPR::SKY); + if(sky) sky->tinf = NULL, sky->flags |= POLY_INTENSE; + } + return; + } + + case 2: { + color_t col; + if(c->land == laWineyard) { + col = 0x4040FF; + if(emeraldval(c) / 4 == 11) { + auto &sun = queuepolyat(V * zpush(geom3::SKY+0.5), shSun, 0xFFFF00FF, PPR::SKY); + sun.tinf = NULL; + sun.flags |= POLY_INTENSE; + } + } + else { + int cd = (euclid || stdhyperbolic) ? getCdata(c, 1) : 0; + int z = cd & 127; + if(z >= 64) z = 127 - z; + col = gradient(0x4040FF, 0xFFFFFF, 0, z, 63); + } + int sk = get_skybrightness(); + if(sk > 0) { + col = gradient(0, col, 0, sk, 255); + col = darkena(col, 0, 255); + auto sky = draw_shapevec(c, V, shFullFloor.levels[SIDE_SKY], col, PPR::SKY); + if(sky) sky->tinf = NULL; + } + + return; + } + + case 3: { + if(camera_level <= geom3::WALL) return; + draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL); + forCellIdEx(c2, i, c) + if(ceiling_category(c2) != 3) { + color_t wcol2 = gradient(0, wcol, 0, .8, 1); + placeSidewall(c, i, SIDE_SKY, V, darkena(wcol2, fd, 0xFF)); + } + return; + } + } + } + void drawcell_in_radar(cell *c, transmatrix V) { #if CAP_SHMUP if(shmup::on) { @@ -5299,6 +5473,10 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { draw_qfi(c, V, darkena(fcol, fd, flooralpha)); } + // draw the ceiling + if(WDIM == 2 && GDIM == 3) + draw_ceiling(c, V, fd, fcol, wcol); + // walls #if CAP_EDIT @@ -6488,6 +6666,7 @@ void make_actual_view() { ld max = WDIM == 2 ? geom3::camera : vid.yshift; if(max) actual_view_transform = zpush(wall_radar(viewctr.at->c7, inverse(View), max)) * actual_view_transform; + camera_level = asin_auto(tC0(inverse(actual_view_transform * View))[2]); } #endif } diff --git a/hyper.h b/hyper.h index 0c88ef11..8da890d0 100644 --- a/hyper.h +++ b/hyper.h @@ -2156,7 +2156,7 @@ enum class PPR { MONSTER_HOODCLOAK1, MONSTER_HOODCLOAK2, STUNSTARS, CARRIED, CARRIEDa, CARRIEDb, - PARTICLE, SWORDMARK, MAGICSWORD, MISSILE, + PARTICLE, SWORDMARK, MAGICSWORD, MISSILE, SKY, MINEMARK, ARROW, MOBILE_ARROW, LINE, @@ -4250,7 +4250,8 @@ void set_blizzard_frame(cell *c, int frameid); #define SIDE_LAKE 5 #define SIDE_LTOB 6 #define SIDE_BTOI 7 -#define SIDEPARS 8 +#define SIDE_SKY 8 +#define SIDEPARS 9 #if CAP_SHAPES struct floorshape { diff --git a/polygons.cpp b/polygons.cpp index f7307c28..2187dbac 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -88,6 +88,9 @@ static const int POLY_ALWAYS_IN = (1<<21); // made of TRIANGLES, not TRIANGLE_FAN static const int POLY_TRIANGLES = (1<<22); +// extra intense colors +static const int POLY_INTENSE = (1<<23); + vector hpc; basic_textureinfo user_triangles_texture; @@ -670,9 +673,10 @@ void dqi_poly::gldraw() { if(draw) { if(flags & POLY_TRIANGLES) { - glhr::color2(color); + 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); + glhr::set_fogbase(prio == PPR::SKY ? 1.0 + 5 / sightranges[geometry] : 1.0); glDrawArrays(GL_TRIANGLES, ioffset, cnt); } else { @@ -1714,7 +1718,7 @@ hpcshape shKnife, shTongue, shFlailMissile, shTrapArrow, shPirateHook, shPirateHood, shEyepatch, shPirateX, // shScratch, - shHeptaMarker, shSnowball, + shHeptaMarker, shSnowball, shSun, shNightStar, shSkeletonBody, shSkull, shSkullEyes, shFatBody, shWaterElemental, shPalaceGate, shFishTail, shMouse, shMouseLegs, shMouseEyes, @@ -2056,6 +2060,7 @@ void make_sidewalls() { dfloor_table[SIDE_LAKE] = geom3::LAKE; dfloor_table[SIDE_LTOB] = geom3::BOTTOM; dfloor_table[SIDE_BTOI] = geom3::INFDEEP; + dfloor_table[SIDE_SKY ] = geom3::SKY; // sidewall parameters for the 3D mode for(int k=0; kuFogBase, 1); fogbase = 1; mode = m; current_shader_projection = sp; GLERR("after_switch_mode"); @@ -472,6 +475,15 @@ void fog_max(ld fogmax) { #endif } +void set_fogbase(ld _fogbase) { + #if CAP_SHADER + if(fogbase != _fogbase) { + fogbase = _fogbase; + glUniform1f(current->uFogBase, fogbase); + } + #endif + } + void set_ualpha(ld alpha) { glUniform1f(current->uAlpha, alpha); } @@ -534,6 +546,7 @@ void init() { mps, "uniform mediump mat4 uMV;", mps, "uniform mediump mat4 uP;", 1, "uniform mediump float uFog;", + 1, "uniform mediump float uFogBase;", ball, "uniform mediump float uAlpha;", !varcol, "uniform mediump vec4 uColor;", @@ -593,13 +606,13 @@ void init() { hp && dim3, "t.x /= -rads; t.y /= -rads; t.z /= -rads; t[3] = 1.0;", s3, "vec4 t = uMV * aPosition;", - sh3, "vColor.xyz = vColor.xyz * (1.0 - acosh(t[3]) / uFog);", - sr3, "vColor.xyz = vColor.xyz * (1.0 - sqrt(t[0]*t[0] + t[1]*t[1] + t[2]*t[2]) / uFog);", + sh3, "vColor.xyz = vColor.xyz * (uFogBase - acosh(t[3]) / uFog);", + sr3, "vColor.xyz = vColor.xyz * (uFogBase - sqrt(t[0]*t[0] + t[1]*t[1] + t[2]*t[2]) / uFog);", - ss30, "vColor.xyz = vColor.xyz * (1.0 - (6.284 - acos(t[3])) / uFog); t = -t; ", - ss31, "vColor.xyz = vColor.xyz * (1.0 - (6.284 - acos(t[3])) / uFog); t.xyz = -t.xyz; ", - ss32, "vColor.xyz = vColor.xyz * (1.0 - acos(t[3]) / uFog); t.w = -t.w; ", // 2pi - ss33, "vColor.xyz = vColor.xyz * (1.0 - acos(t[3]) / uFog); ", + ss30, "vColor.xyz = vColor.xyz * (uFogBase - (6.284 - acos(t[3])) / uFog); t = -t; ", + ss31, "vColor.xyz = vColor.xyz * (uFogBase - (6.284 - acos(t[3])) / uFog); t.xyz = -t.xyz; ", + ss32, "vColor.xyz = vColor.xyz * (uFogBase - acos(t[3]) / uFog); t.w = -t.w; ", // 2pi + ss33, "vColor.xyz = vColor.xyz * (uFogBase - acos(t[3]) / uFog); ", sh3 || sr3 || ball,"t[3] = 1.0;", band || hp || s3 || ball,"gl_Position = uP * t;",