mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 21:07:17 +00:00
sky-based fog in 2.5D
This commit is contained in:
parent
3c198a3672
commit
7c3c34c3d8
@ -582,6 +582,8 @@ EX void initConfig() {
|
||||
sightranges[i] = 10;
|
||||
else if(ginf[i].cclass == gcSL2)
|
||||
sightranges[i] = 4.5;
|
||||
else if(ginf[i].cclass == gcHyperbolic && ginf[i].g.gameplay_dimension == 2)
|
||||
sightranges[i] = 4.5;
|
||||
else
|
||||
sightranges[i] = 5;
|
||||
sightranges[gArchimedean] = 10;
|
||||
|
@ -1999,6 +1999,8 @@ void dqi_line::draw_back() {
|
||||
|
||||
EX void sort_drawqueue() {
|
||||
|
||||
if(WDIM == 2 && GDIM == 3 && hyperbolic) make_air();
|
||||
|
||||
DEBBI(DF_GRAPH, ("sort_drawqueue"));
|
||||
|
||||
for(int a=0; a<PMAX; a++) qp[a] = 0;
|
||||
|
6
glhr.cpp
6
glhr.cpp
@ -273,8 +273,8 @@ struct GLprogram {
|
||||
GLuint _program;
|
||||
GLuint vertShader, fragShader;
|
||||
|
||||
GLint uFog, uFogColor, uColor, tTexture, tInvExpTable, uMV, uProjection, uAlpha, uFogBase, uPP;
|
||||
GLint uPRECX, uPRECY, uPRECZ, uIndexSL, uIterations, uLevelLines, uSV;
|
||||
GLint uFog, uFogColor, uColor, tTexture, tInvExpTable, tAirMap, uMV, uProjection, uAlpha, uFogBase, uPP;
|
||||
GLint uPRECX, uPRECY, uPRECZ, uIndexSL, uIterations, uLevelLines, uSV, uRadarTransform;
|
||||
|
||||
flagtype shader_flags;
|
||||
|
||||
@ -392,6 +392,7 @@ GLprogram::GLprogram(string vsh, string fsh) {
|
||||
uColor = glGetUniformLocation(_program, "uColor");
|
||||
tTexture = glGetUniformLocation(_program, "tTexture");
|
||||
tInvExpTable = glGetUniformLocation(_program, "tInvExpTable");
|
||||
tAirMap = glGetUniformLocation(_program, "tAirMap");
|
||||
|
||||
uPRECX = glGetUniformLocation(_program, "PRECX");
|
||||
uPRECY = glGetUniformLocation(_program, "PRECY");
|
||||
@ -400,6 +401,7 @@ GLprogram::GLprogram(string vsh, string fsh) {
|
||||
uSV = glGetUniformLocation(_program, "uSV");
|
||||
uIterations = glGetUniformLocation(_program, "uIterations");
|
||||
uLevelLines = glGetUniformLocation(_program, "uLevelLines");
|
||||
uRadarTransform = glGetUniformLocation(_program, "uRadarTransform");
|
||||
}
|
||||
|
||||
GLprogram::~GLprogram() {
|
||||
|
45
shaders.cpp
45
shaders.cpp
@ -44,6 +44,7 @@ constexpr int aTexture = 8;
|
||||
|
||||
/* texture bindings */
|
||||
constexpr int INVERSE_EXP_BINDING = 2;
|
||||
constexpr int AIR_BINDING = 4;
|
||||
#endif
|
||||
|
||||
EX map<string, shared_ptr<glhr::GLprogram>> compiled_programs;
|
||||
@ -268,7 +269,39 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
if(!skip_t) {
|
||||
vmain += "mediump vec4 t = uMV * aPosition;\n";
|
||||
vmain += coordinator;
|
||||
if(distfun != "") {
|
||||
if(GDIM == 3 && WDIM == 2) {
|
||||
vsh +=
|
||||
"uniform mediump mat4 uRadarTransform;\n"
|
||||
"uniform mediump sampler2D tAirMap;\n"
|
||||
"uniform mediump float uFog;\n"
|
||||
"uniform mediump float uFogBase;\n"
|
||||
"vec4 color_at(vec4 ending, float dist) {"
|
||||
" vec3 pt = ending.xyz * sinh(dist);\n"
|
||||
" pt.xy /= sqrt(pt.z*pt.z+1.);\n"
|
||||
" pt.xy /= 2. * (1. + sqrt(1.+pt.x*pt.x+pt.y*pt.y));\n"
|
||||
" pt.xy += vec2(.5, .5);\n"
|
||||
" return texture2D(tAirMap, pt.xy);\n"
|
||||
" }\n";
|
||||
|
||||
vmain +=
|
||||
"vec4 ending = uRadarTransform * t;\n"
|
||||
"float len = acosh(ending.w);\n"
|
||||
"float eulen = length(ending.xyz);\n"
|
||||
"ending.xyz /= eulen;\n"
|
||||
"ending.y *= -1.;\n"
|
||||
"vec4 fog = vec4(1e-3,0,1e-3,1e-3);\n"
|
||||
"vec4 last = vec4(0,0,0,0);\n"
|
||||
"for(int i=0; i<50; i++) {\n"
|
||||
" vec4 px = color_at(ending, ((float(i) + .5) / 50.) * min(len, uFog));\n"
|
||||
" if(px.r < .9 || px.b < .9 || px.g > .1) last = px;\n"
|
||||
" fog += last;\n"
|
||||
" }\n"
|
||||
"mediump float fogs = (uFogBase - len / uFog);\n"
|
||||
"if(fogs < 0.) fogs = 0.;\n"
|
||||
"fog.xyz /= fog.w;\n"
|
||||
"vColor.xyz = vColor.xyz * fogs + fog.xyz * (1.0-fogs);\n";
|
||||
}
|
||||
else if(distfun != "") {
|
||||
vmain += "mediump float fogs = (uFogBase - " + distfun + " / uFog);\n";
|
||||
vmain += "vColor.xyz = vColor.xyz * fogs + uFogColor.xyz * (1.0-fogs);\n";
|
||||
vsh +=
|
||||
@ -357,6 +390,16 @@ void display_data::set_projection(int ed, ld shift) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if(selected->tAirMap != -1) {
|
||||
glActiveTexture(GL_TEXTURE0 + AIR_BINDING);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, airbuf->renderedTexture);
|
||||
glUniform1i(selected->tAirMap, AIR_BINDING);
|
||||
glActiveTexture(GL_TEXTURE0 + 0);
|
||||
glUniformMatrix4fv(selected->uRadarTransform, 1, 0, glhr::tmtogl_transpose3(radar_transform).as_array());
|
||||
}
|
||||
|
||||
if(selected->uIterations != -1) {
|
||||
glhr::set_index_sl(0);
|
||||
glhr::set_sv(stretch::not_squared());
|
||||
|
191
sky.cpp
191
sky.cpp
@ -16,7 +16,8 @@ struct sky_item {
|
||||
cell *c;
|
||||
shiftmatrix T;
|
||||
color_t color;
|
||||
sky_item(cell *_c, const struct shiftmatrix _T, color_t _color) : c(_c), T(_T), color(_color) {}
|
||||
color_t skycolor;
|
||||
sky_item(cell *_c, const struct shiftmatrix _T, color_t _color, color_t _skycolor) : c(_c), T(_T), color(_color), skycolor(_skycolor) {}
|
||||
};
|
||||
|
||||
struct dqi_sky : drawqueueitem {
|
||||
@ -41,7 +42,7 @@ EX void prepare_sky() {
|
||||
queuepolyat(T * zpush(cgi.SKY+0.5) * xpush(cgi.SKY+0.5), cgi.shSun, 0xFFFF00FF, PPR::SKY);
|
||||
}
|
||||
else if(!(cgflags & qIDEAL)) {
|
||||
sky = &queuea<dqi_sky> (PPR::SKY);
|
||||
sky = &queuea<dqi_sky> (PPR::MISSILE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,13 +53,17 @@ void dqi_sky::draw() {
|
||||
|
||||
int sk = get_skybrightness();
|
||||
|
||||
unordered_map<cell*, color_t> colors;
|
||||
unordered_map<cell*, pair<color_t, color_t>> colors;
|
||||
#ifdef USE_UNORDERED_MAP
|
||||
colors.reserve(isize(sky));
|
||||
#endif
|
||||
for(sky_item& si: sky) colors[si.c] = darkena(gradient(0, si.color, 0, sk, 255), 0, 0xFF);
|
||||
for(sky_item& si: sky) colors[si.c] =
|
||||
make_pair(darkena(gradient(0, si.color, 0, sk, 255), 0, 0xFF),
|
||||
darkena(si.skycolor, 0, 0xFF)
|
||||
);
|
||||
|
||||
hyperpoint skypoint = cpush0(2, cgi.SKY);
|
||||
hyperpoint hellpoint = cpush0(2, -cgi.SKY);
|
||||
|
||||
vector<glhr::colored_vertex> this_poly;
|
||||
|
||||
@ -72,12 +77,42 @@ void dqi_sky::draw() {
|
||||
auto c = si.c;
|
||||
for(int i=0; i<c->type; i++) {
|
||||
|
||||
if(1) {
|
||||
cellwalker cw0(c, i);
|
||||
cellwalker cw2 = cw0;
|
||||
cw2--; cw2 += wstep;
|
||||
if(!colors.count(cw2.at)) {
|
||||
this_poly.clear();
|
||||
transmatrix T1 = unshift(si.T);
|
||||
T1 = Tsh * T1;
|
||||
auto cw = cw0;
|
||||
while(colors.count(cw.at)) {
|
||||
color_t col = colors[cw.at].second;
|
||||
this_poly.emplace_back(T1 * skypoint, colors[cw.at].first);
|
||||
this_poly.emplace_back(T1 * hellpoint, col);
|
||||
T1 = T1 * currentmap->adj(cw.at, cw.spin);
|
||||
cw += wstep; cw++;
|
||||
}
|
||||
|
||||
int k = isize(this_poly);
|
||||
for(int j=2; j<k; j+=2) {
|
||||
skyvertices.push_back(this_poly[j-2]);
|
||||
skyvertices.push_back(this_poly[j-1]);
|
||||
skyvertices.push_back(this_poly[j]);
|
||||
skyvertices.push_back(this_poly[j-1]);
|
||||
skyvertices.push_back(this_poly[j]);
|
||||
skyvertices.push_back(this_poly[j+1]);
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if(1) {
|
||||
cellwalker cw0(c, i);
|
||||
cellwalker cw = cw0;
|
||||
do {
|
||||
cw += wstep; cw++;
|
||||
if(cw.at < c || !colors.count(si.c)) goto next;
|
||||
if(cw.at < c || !colors.count(cw.at)) goto next;
|
||||
}
|
||||
while(cw != cw0);
|
||||
|
||||
@ -86,7 +121,7 @@ void dqi_sky::draw() {
|
||||
transmatrix T1 = unshift(si.T);
|
||||
T1 = Tsh * T1;
|
||||
do {
|
||||
this_poly.emplace_back(T1 * skypoint, colors[cw.at]);
|
||||
this_poly.emplace_back(T1 * skypoint, colors[cw.at].first);
|
||||
T1 = T1 * currentmap->adj(cw.at, cw.spin);
|
||||
cw += wstep; cw++;
|
||||
}
|
||||
@ -125,20 +160,17 @@ color_t skycolor(cell *c) {
|
||||
int cd = (euclid || stdhyperbolic) ? getCdata(c, 1) : 0;
|
||||
int z = (cd * 5) & 127;
|
||||
if(z >= 64) z = 127 - z;
|
||||
if(c->land == laHell)
|
||||
return z < 32 ? gradient(0x400000, 0xFF0000, 0, z, 32) : gradient(0xFF0000, 0xFFFF00, 32, z, 63);
|
||||
else
|
||||
return gradient(0x4040FF, 0xFFFFFF, 0, z, 63);
|
||||
return gradient(0x4040FF, 0xFFFFFF, 0, z, 63);
|
||||
}
|
||||
|
||||
void celldrawer::draw_ceiling() {
|
||||
|
||||
if(pmodel != mdPerspective || sphere) return;
|
||||
|
||||
auto add_to_sky = [this] (color_t col) {
|
||||
auto add_to_sky = [this] (color_t col, color_t col2) {
|
||||
if(cgflags & qIDEAL)
|
||||
draw_shapevec(c, V, qfi.fshape->levels[SIDE_HIGH], darkena(col, 0, 0xFF), PPR::WALL);
|
||||
else if(sky) sky->sky.emplace_back(c, V, col);
|
||||
else if(sky) sky->sky.emplace_back(c, V, col, col2);
|
||||
};
|
||||
|
||||
switch(ceiling_category(c)) {
|
||||
@ -148,7 +180,7 @@ void celldrawer::draw_ceiling() {
|
||||
if(fieldpattern::fieldval_uniq(c) % 3 == 0) {
|
||||
queuepolyat(V * zpush(cgi.SKY+1), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY);
|
||||
}
|
||||
add_to_sky(0x00000F);
|
||||
add_to_sky(0x00000F, 0x00000F);
|
||||
if(c->land == laAsteroids) {
|
||||
if(fieldpattern::fieldval_uniq(c) % 9 < 3) {
|
||||
queuepolyat(V * zpush(-1-cgi.SKY), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY);
|
||||
@ -163,10 +195,12 @@ void celldrawer::draw_ceiling() {
|
||||
case 2: {
|
||||
if(euclid) return;
|
||||
color_t col;
|
||||
color_t skycol;
|
||||
|
||||
switch(c->land) {
|
||||
case laWineyard:
|
||||
col = 0x4040FF;
|
||||
skycol = 0x8080FF;
|
||||
if(emeraldval(c) / 4 == 11) {
|
||||
queuepolyat(V * zpush(cgi.SKY+1), cgi.shSun, 0xFFFF00FF, PPR::SKY);
|
||||
}
|
||||
@ -174,22 +208,23 @@ void celldrawer::draw_ceiling() {
|
||||
|
||||
case laFrog:
|
||||
col = 0x4040FF;
|
||||
skycol = 0x8080FF;
|
||||
if(zebra40(c) / 4 == 1) {
|
||||
queuepolyat(V * zpush(cgi.SKY+1), cgi.shSun, 0xFFFF00FF, PPR::SKY);
|
||||
}
|
||||
break;
|
||||
|
||||
case laPower:
|
||||
col = c->landparam ? 0xFF2010 : 0x000020;
|
||||
skycol = col = c->landparam ? 0xFF2010 : 0x000020;
|
||||
break;
|
||||
|
||||
case laDesert:
|
||||
case laRedRock:
|
||||
col = 0x4040FF;
|
||||
skycol = (0xCDA98F & 0xFEFEFE) / 2;
|
||||
break;
|
||||
|
||||
case laAlchemist:
|
||||
col = fcol;
|
||||
skycol = col = fcol;
|
||||
break;
|
||||
|
||||
case laVariant: {
|
||||
@ -199,22 +234,38 @@ void celldrawer::draw_ceiling() {
|
||||
if((b >> a) & 1)
|
||||
col += variant::features[a].color_change;
|
||||
col = col & 0x00FF00;
|
||||
skycol = col;
|
||||
break;
|
||||
}
|
||||
|
||||
case laDragon:
|
||||
col = c->wall == waChasm ? 0xFFFFFF : 0x4040FF;
|
||||
skycol = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
case laHell: {
|
||||
int a = 0;
|
||||
forCellEx(c1, c) if(among(c1->wall, waSulphur, waSulphurC)) a++;
|
||||
ld z = a * 1. / c->type;
|
||||
if(z < .5)
|
||||
col = gradient(0x400000, 0xFF0000, 0, z, .5);
|
||||
else
|
||||
col = gradient(0xFF0000, 0xFFFF00, .5, z, 1);
|
||||
skycol = col;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
col = skycolor(c);
|
||||
skycol = 0xA0A0FF;
|
||||
}
|
||||
}
|
||||
add_to_sky(col);
|
||||
add_to_sky(col, skycol);
|
||||
return;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
add_to_sky(0);
|
||||
add_to_sky(0, 0);
|
||||
if(camera_level <= cgi.WALL) return;
|
||||
if(c->land == laMercuryRiver) fcol = linf[laTerracotta].color, fd = 1;
|
||||
if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(fcol, fd, 0xFF), PPR::WALL);
|
||||
@ -229,7 +280,7 @@ void celldrawer::draw_ceiling() {
|
||||
}
|
||||
|
||||
case 4: {
|
||||
add_to_sky(0x00000F);
|
||||
add_to_sky(0x00000F, 0x00000F);
|
||||
if(camera_level <= cgi.HIGH2) return;
|
||||
auto ispal = [&] (cell *c0) { return c0->land == laPalace && among(c0->wall, waPalace, waClosedGate, waOpenGate); };
|
||||
color_t wcol2 = 0xFFD500;
|
||||
@ -255,7 +306,7 @@ void celldrawer::draw_ceiling() {
|
||||
}
|
||||
|
||||
case 6: {
|
||||
add_to_sky(skycolor(c));
|
||||
add_to_sky(skycolor(c), 0x4040C0);
|
||||
if(camera_level <= cgi.HIGH2) return;
|
||||
color_t wcol2 = winf[waRuinWall].color;
|
||||
if(c->landparam == 1)
|
||||
@ -264,15 +315,15 @@ void celldrawer::draw_ceiling() {
|
||||
if(c->landparam != 2)
|
||||
forCellIdEx(c2, i, c) if(c2->landparam == 2)
|
||||
placeSidewall(c, i, SIDE_HIGH2, V, darkena(wcol2, fd, 0xFF));
|
||||
if(c->landparam == 0)
|
||||
if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_HIGH], darkena(wcol2, fd, 0xFF), PPR::WALL);
|
||||
/* if(c->landparam == 0)
|
||||
if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_HIGH], darkena(wcol2, fd, 0xFF), PPR::WALL); */
|
||||
if(c->landparam == 1)
|
||||
if(qfi.fshape) draw_shapevec(c, V, qfi.fshape->levels[SIDE_WALL], darkena(wcol2, fd, 0xFF), PPR::WALL);
|
||||
break;
|
||||
}
|
||||
|
||||
case 7: {
|
||||
add_to_sky(0x00000F);
|
||||
add_to_sky(0x00000F, 0x00000F);
|
||||
if(fieldpattern::fieldval_uniq(c) % 5 < 2) {
|
||||
queuepolyat(V * zpush(cgi.SKY+1), cgi.shNightStar, 0xFFFFFFFF, PPR::SKY);
|
||||
}
|
||||
@ -292,7 +343,7 @@ void celldrawer::draw_ceiling() {
|
||||
}
|
||||
|
||||
case 5: {
|
||||
add_to_sky(0x00000F);
|
||||
add_to_sky(0x00000F, 0x00000F);
|
||||
if(camera_level <= cgi.WALL) return;
|
||||
|
||||
if(pseudohept(c)) {
|
||||
@ -309,5 +360,95 @@ void celldrawer::draw_ceiling() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EX struct renderbuffer *airbuf;
|
||||
|
||||
EX void make_air() {
|
||||
if(!sky) return;
|
||||
const int AIR_TEXTURE = 512;
|
||||
if(!airbuf) {
|
||||
airbuf = new renderbuffer(AIR_TEXTURE, AIR_TEXTURE, true);
|
||||
if(!airbuf->valid) {
|
||||
delete airbuf;
|
||||
airbuf = nullptr;
|
||||
println(hlog, "unable to make airbuf");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(1) {
|
||||
//shot::take("airtest.png", drawqueue);
|
||||
dynamicval<videopar> v(vid, vid);
|
||||
dynamicval<bool> vi(inHighQual, true);
|
||||
|
||||
vid.xres = AIR_TEXTURE;
|
||||
vid.yres = AIR_TEXTURE;
|
||||
calcparam();
|
||||
models::configure();
|
||||
|
||||
resetbuffer rb;
|
||||
airbuf->enable();
|
||||
current_display->set_viewport(0);
|
||||
|
||||
airbuf->clear(0xFFFF00FF);
|
||||
|
||||
pconf.alpha = 1;
|
||||
pconf.scale = 1;
|
||||
pconf.camera_angle = 0;
|
||||
pconf.stretch = 1;
|
||||
pmodel = mdDisk;
|
||||
|
||||
vid.always3 = false;
|
||||
geom3::apply_always3();
|
||||
check_cgi();
|
||||
cgi.require_shapes();
|
||||
|
||||
eGeometry orig = geometry;
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
for(auto& g: sky->sky) {
|
||||
transmatrix S;
|
||||
if(1) {
|
||||
geometry = gSpace534;
|
||||
S = g.T.T;
|
||||
S = radar_transform * S;
|
||||
geometry = orig;
|
||||
swapmatrix(S);
|
||||
}
|
||||
|
||||
auto& h = cgi.shFullFloor.b[shvid(g.c)];
|
||||
|
||||
dqi_poly p;
|
||||
p.V = shiftless(S);
|
||||
p.offset = h.s;
|
||||
p.cnt = h.e - h.s;
|
||||
p.tab = &cgi.ourshape;
|
||||
p.color = (g.skycolor << 8) | 0xFF;
|
||||
p.outline = 0;
|
||||
|
||||
p.linewidth = 1;
|
||||
p.flags = POLY_FORCEWIDE;
|
||||
p.tinf = nullptr;
|
||||
|
||||
p.draw();
|
||||
}
|
||||
|
||||
if(vid.antialias & AA_LINES)
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
if(anyshiftclick) IMAGESAVE(airbuf->render(), "air.png");
|
||||
rb.reset();
|
||||
}
|
||||
|
||||
GLERR("after draw");
|
||||
geom3::apply_always3();
|
||||
check_cgi();
|
||||
calcparam();
|
||||
GLERR("after make_air");
|
||||
current_display->set_viewport(0);
|
||||
current_display->set_all(0,0);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user