1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-17 18:54:48 +00:00

ray:: improved ODS

This commit is contained in:
Zeno Rogue 2023-11-30 12:38:30 +01:00
parent 2dccf0d3ab
commit fe7e122613

View File

@ -15,7 +15,7 @@ EX namespace ray {
#if CAP_RAY
/** texture IDs */
GLuint txConnections = 0, txWallcolor = 0, txTextureMap = 0, txVolumetric = 0, txM = 0, txWall = 0, txPortalConnections = 0;
GLuint txConnections = 0, txWallcolor = 0, txTextureMap = 0, txVolumetric = 0, txM = 0, txWall = 0, txPortalConnections = 0, txStart = 0;
EX bool in_use;
EX bool comparison_mode;
@ -97,8 +97,6 @@ ld& maxstep_current() {
return maxstep_nil;
}
#define IN_ODS 0
eGeometry last_geometry;
vector<pair<int, cell*>> used_sample_list() {
@ -162,9 +160,9 @@ EX bool requested() {
#if HDR
struct raycaster : glhr::GLprogram {
GLint uStart, uStartid, uM, uLength, uIPD;
GLint uStart, uStartid, uM, uLength;
GLint uWallstart, uWallX, uWallY;
GLint tConnections, tWallcolor, tTextureMap, tVolumetric;
GLint tConnections, tWallcolor, tTextureMap, tVolumetric, tStart;
GLint uBinaryWidth, uPLevel, uLP, uStraighten, uReflectX, uReflectY;
GLint uLinearSightRange, uExpStart, uExpDecay;
GLint uBLevel;
@ -204,7 +202,6 @@ raycaster::raycaster(string vsh, string fsh) : GLprogram(vsh, fsh) {
uM = glGetUniformLocation(_program, "uM");
uLength = glGetUniformLocation(_program, "uLength");
uProjection = glGetUniformLocation(_program, "uProjection");
uIPD = glGetUniformLocation(_program, "uIPD");
uWallstart = glGetUniformLocation(_program, "uWallstart");
uWallX = glGetUniformLocation(_program, "uWallX");
@ -228,6 +225,7 @@ raycaster::raycaster(string vsh, string fsh) : GLprogram(vsh, fsh) {
tWallcolor = glGetUniformLocation(_program, "tWallcolor");
tTextureMap = glGetUniformLocation(_program, "tTextureMap");
tVolumetric = glGetUniformLocation(_program, "tVolumetric");
tStart = glGetUniformLocation(_program, "tStart");
tPortalConnections = glGetUniformLocation(_program, "tPortalConnections");
@ -1255,15 +1253,6 @@ void raygen::emit_iterate(int gid1) {
if(in_e2xe() && !eyes) fmain += "tangent.w = position.w = 0.;\n";
if(IN_ODS) fmain +=
" if(go == 0.) {\n"
" mediump float best = "+f_len()+"(position);\n"
" for(int i=0; i<sides; i++) {\n"
" mediump float cand = "+f_len()+"(" + getM("i") + " * position);\n"
" if(cand < best - .001) { dist = 0.; best = cand; which = i; }\n"
" }\n"
" }\n";
compute_which_and_dist(flat1, flat2);
vid.fixed_yz = false;
@ -1855,9 +1844,6 @@ void raygen::create() {
fsh =
"varying mediump vec4 at;\n"
"uniform mediump int uLength;\n"
"uniform mediump float uIPD;\n"
"uniform mediump mat4 uStart;\n"
"uniform mediump vec2 uStartid;\n"
"uniform mediump sampler2D tConnections;\n"
"uniform mediump sampler2D tWallcolor;\n"
"uniform mediump sampler2D tVolumetric;\n"
@ -1866,6 +1852,16 @@ void raygen::create() {
"uniform mediump vec4 uFogColor;\n"
"uniform mediump float uLinearSightRange, uExpStart, uExpDecay;\n";
if(vid.stereo_mode == sODS) {
fsh +=
"uniform mediump sampler2D tStart;\n";
}
else {
fsh +=
"uniform mediump mat4 uStart;\n"
"uniform mediump vec2 uStartid;\n";
}
if(intra::in) fsh +=
"uniform mediump sampler2D tPortalConnections;\n";
@ -1915,7 +1911,7 @@ void raygen::create() {
fsh += build_getter("mediump mat4", "uM", gms_limit);
#endif
if(gproduct || intra::in) fsh +=
if((gproduct || intra::in) && vid.stereo_mode != sODS) fsh +=
"uniform mediump mat4 uLP;\n";
if(gproduct || intra::in) fsh +=
@ -1952,21 +1948,32 @@ void raygen::create() {
if(use_reflect) fmain += " bool depthtoset = true;\n";
if(many_cell_types && vid.stereo_mode != sODS) fmain += " walloffset = uWallOffset; sides = uSides;\n";
fmain +=
" mediump float left = 1.;\n"
" gl_FragColor = vec4(0,0,0,1);\n";
if(IN_ODS) fmain +=
" mediump float lambda = at[0];\n" // -PI to PI
if(vid.stereo_mode == sODS) fmain +=
" mediump float phi;\n"
" mediump float eye;\n"
" if(at.y < 0.) { phi = at.y + PI/2.; eye = uIPD / 2.; }\n" // right
" else { phi = at.y - PI/2.; eye = -uIPD / 2.; }\n"
" mediump mat4 vw = uStart * xzspin(-lambda) * "+f_xpush()+"(eye) * yzspin(phi);\n"
" mediump vec4 at0 = vec4(0., 0., 1., 0.);\n";
// todo: will not work in product!
*/
" mediump float yb;\n"
" float xb = (at.x + 1.) / 2.;\n"
" if(at.y < 0.) { phi = at.y * PI + PI/2.; yb = 0.516525; }\n" // right
" else { phi = at.y * PI - PI/2.; yb = 0.016525; }\n" // left
" mediump mat4 vw;\n"
" mediump mat4 uLP;\n"
" mediump vec4 at0 = yzspin(phi) * vec4(0., 0., 1., 0.);\n"
" mediump vec4 pt = texture2D(tStart, vec2(xb, yb + 0.25));\n"
" mediump vec2 uStartid = pt.xy;\n"
" for(int i=0; i<4; i++) {\n"
" mediump vec4 v = texture2D(tStart, vec2(xb, yb + float(i) / 32.));\n"
" for(int j=0; j<4; j++) vw[j][i] = (v[j] - .5) * " + to_glsl(ray_scale) + ";\n"
" v = texture2D(tStart, vec2(xb, yb + 0.125 + float(i) / 32.));\n"
" for(int j=0; j<4; j++) uLP[j][i] = (v[j] - .5) * " + to_glsl(ray_scale) + ";\n"
" }\n"
" walloffset = int(pt.w * " + to_glsl(max_wall_offset) + ");\n"
" sides = int(pt.w * " + to_glsl(max_wall_offset * max_celltype) + ") - " + its(max_celltype) + " * walloffset;\n";
else if(vid.stereo_mode == sEquirectangular) fmain +=
" mediump float lambda = at.x * PI;\n" // -PI to PI
" mediump float phi = at.y * PI / 2.0;\n"
@ -2039,8 +2046,6 @@ void raygen::create() {
fmain += " mediump float zpos = 0.;\n";
}
if(many_cell_types) fmain += " walloffset = uWallOffset; sides = uSides;\n";
if(intra::in) {
int q = isize(intra::data);
@ -2527,6 +2532,35 @@ EX void load_walls(vector<glvertex>& wallx, vector<glvertex>& wally, vector<GLin
}
}
int ray_fixes_warn_from = 10;
EX void rayfix(cell*& cs, transmatrix& T, transmatrix& msm) {
int ray_fixes = 0;
auto ocs = cs;
hyperpoint TC0 = tile_center();
back:
for(int a=0; a<cs->type; a++)
if(hdist(currentmap->ray_iadj(cs, a) * T * C0, TC0) < hdist(T * C0, TC0)) {
T = currentmap->iadj(cs, a) * T;
if(our_raycaster->uToOrig != -1) {
transmatrix HT = currentmap->adj(cs, a);
HT = stretch::itranslate(tC0(HT)) * HT;
msm = HT * msm;
}
cs = cs->move(a);
ray_fixes++;
if(ray_fixes > 100) {
println(hlog, "major ray error");
return;
}
goto back;
}
if(ray_fixes >= ray_fixes_warn_from) println(hlog, "ray error x", ray_fixes, " centerover = ", ocs, " -> ", cs);
}
EX int ods_prec = 8192;
EX void cast() {
// may call itself recursively in case of bugs -- just in case...
dynamicval<int> dn(nesting, nesting+1);
@ -2538,7 +2572,7 @@ EX void cast() {
auto& o = our_raycaster;
if(need_many_cell_types() && o->uWallOffset == -1) {
if(need_many_cell_types() && o->uWallOffset == -1 && vid.stereo_mode != sODS) {
reset_raycaster();
cast();
return;
@ -2599,43 +2633,20 @@ EX void cast() {
transmatrix T = cview().T;
if(global_projection)
T = xpush(vid.ipd * global_projection/2) * T;
T = xpush(vid.ipd * global_projection/2) * T; // todo fix for intra
if(nonisotropic) T = NLP * T;
T = inverse(T);
virtualRebase(cs, T);
int ray_fixes = 0;
transmatrix msm = stretch::mstretch_matrix;
hyperpoint TC0 = tile_center();
back:
for(int a=0; a<cs->type; a++)
if(hdist(currentmap->ray_iadj(cs, a) * T * C0, TC0) < hdist(T * C0, TC0)) {
T = currentmap->iadj(cs, a) * T;
if(o->uToOrig != -1) {
transmatrix HT = currentmap->adj(cs, a);
HT = stretch::itranslate(tC0(HT)) * HT;
msm = HT * msm;
}
cs = cs->move(a);
ray_fixes++;
if(ray_fixes > 100) {
println(hlog, "major ray error");
return;
}
goto back;
}
if(ray_fixes) println(hlog, "ray error x", ray_fixes, " centerover = ", centerover, " -> ", cs);
rayfix(cs, T, msm);
glUniformMatrix4fv(o->uStart, 1, 0, glhr::tmtogl_transpose3(T).as_array());
if(vid.stereo_mode != sODS) glUniformMatrix4fv(o->uStart, 1, 0, glhr::tmtogl_transpose3(T).as_array());
if(o->uLP != -1) glUniformMatrix4fv(o->uLP, 1, 0, glhr::tmtogl_transpose3(inverse(NLP)).as_array());
GLERR("uniform mediump startid");
glUniform1f(o->uIPD, vid.ipd);
GLERR("uniform mediump IPD");
if(o->uITOA != -1) {
glUniformMatrix4fv(o->uITOA, 1, 0, glhr::tmtogl_transpose3(stretch::m_itoa).as_array());
@ -2757,7 +2768,7 @@ EX void cast() {
}
// we may learn about this now...
if(need_many_cell_types() && o->uWallOffset == -1) {
if(need_many_cell_types() && o->uWallOffset == -1 && vid.stereo_mode != sODS) {
reset_raycaster();
cast();
return;
@ -2766,7 +2777,88 @@ EX void cast() {
GLERR("uniform mediump start");
if(!o) { cast(); return; }
uniform2(o->uStartid, rmap->enc(rmap->ids[cs], 0));
if(vid.stereo_mode == sODS) {
vector<array<float, 4>> tstart(ods_prec * 32);
for(int y=0; y<2; y++)
for(int x=0; x<ods_prec; x++) {
// ...
ld lambda = ((x + 0.5) / ods_prec * 2 - 1) * M_PI;
// 0: -M_PI, ods_prec: M_PI -> ok
int xb = x + y * ods_prec * 16;
dynamicval<cell*> tco(centerover);
dynamicval<int> tfd(walking::floor_dir);
dynamicval<cell*> tof(walking::on_floor_of);
dynamicval<ld> tis(intra::scale);
dynamicval<transmatrix> tN(NLP, NLP);
dynamicval<transmatrix> tV(View, View);
dynamicval<transmatrix> tC(current_display->which_copy, current_display->which_copy);
dynamicval<transmatrix> trt(current_display->radar_transform);
int id = intra::current;
cell *cov = centerover;
finalizer fin([&] {
if(intra::current != id) {
intra::switch_to(id);
}
centerover = cov;
});
auto T1 = T;
View = inverse(T1);
// if(nonisotropic) View = inverse(NLP) * View;
centerover = cs;
ld eye = y == 0 ? vid.ipd / 2. : -vid.ipd / 2.;
rotate_view(cspin(0, 2, -lambda));
shift_view(xtangent(eye));
if(nonisotropic) {
auto T = View;
transmatrix T2 = eupush( tC0(view_inverse(T)) );
NLP = T * T2;
}
T1 = inverse(View);
virtualRebase(centerover, T1);
rayfix(centerover, T1, msm);
T1 = protect_prod(T1);
for(int a=0; a<4; a++)
for(int b=0; b<4; b++) {
tstart[xb + a * ods_prec][b] = T1[a][b]/ray_scale + .5;
}
auto mLP = protect_prod(inverse(NLP));
for(int a=0; a<4; a++)
for(int b=0; b<4; b++) {
tstart[xb + (a+4) * ods_prec][b] = mLP[a][b]/ray_scale + .5;
}
auto enc = rmap->enc(rmap->ids[centerover], 0);
tstart[xb + 8 * ods_prec][0] = enc[0];
tstart[xb + 8 * ods_prec][1] = enc[1];
int wo1 = intra::full_wall_offset(centerover);
int sides = centerover->type + (WDIM == 2 ? 2 : 0);
tstart[xb + 8 * ods_prec][3] = (wo1 * 1. / max_wall_offset) + (sides + .5) * 1. / max_wall_offset / max_celltype;
}
if(vid.stereo_mode != sODS) glUniformMatrix4fv(o->uStart, 1, 0, glhr::tmtogl_transpose3(T).as_array());
bind_array(tstart, o->tStart, txStart, 10, ods_prec);
}
else
uniform2(o->uStartid, rmap->enc(rmap->ids[cs], 0));
}
#if CAP_VERTEXBUFFER