mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 13:07:16 +00:00
cleaned up stereo/high-FOV projections
This commit is contained in:
parent
2add515fbf
commit
34d3d67ace
64
config.cpp
64
config.cpp
@ -1345,11 +1345,13 @@ EX void initConfig() {
|
|||||||
addsaver(vid.desaturate, "desaturate", 0);
|
addsaver(vid.desaturate, "desaturate", 0);
|
||||||
|
|
||||||
param_enum(vid.stereo_mode, "stereo_mode", "stereo-mode", vid.stereo_mode)
|
param_enum(vid.stereo_mode, "stereo_mode", "stereo-mode", vid.stereo_mode)
|
||||||
->editable({{"OFF", ""}, {"anaglyph", ""}, {"side-by-side", ""}
|
->editable({
|
||||||
#if CAP_ODS
|
{"OFF", "linear perspective"}, {"anaglyph", "for red-cyan glasses"}, {"side-by-side", "for mobile VR"},
|
||||||
, {"ODS", ""}
|
{"ODS", "for rendering 360° VR videos (implemented only in raycaster and some other parts)"},
|
||||||
#endif
|
{"Panini", "Projection believed to be used by Italian painters. Allows very high FOV angles while rendering more straight lines as straight than the stereographic projection."},
|
||||||
}, "stereo mode", 'm');
|
{"stereographic", "Stereographic projection allows very high FOV angles."},
|
||||||
|
{"equirectangular", "for rendering 360° videos (implemented only in raycaster)"}
|
||||||
|
}, "stereo/high-FOV mode", 'm');
|
||||||
|
|
||||||
param_f(vid.plevel_factor, "plevel_factor", 0.7);
|
param_f(vid.plevel_factor, "plevel_factor", 0.7);
|
||||||
|
|
||||||
@ -1577,11 +1579,12 @@ EX void initConfig() {
|
|||||||
param_f(camera_rot_speed, "camrot", "camera-rot-speed", 1);
|
param_f(camera_rot_speed, "camrot", "camera-rot-speed", 1);
|
||||||
param_f(third_person_rotation, "third_person_rotation", 0);
|
param_f(third_person_rotation, "third_person_rotation", 0);
|
||||||
|
|
||||||
param_f(panini_alpha, "panini_alpha", 0)
|
param_f(vid.stereo_param, "stereo_param", 0.9)
|
||||||
|
->editable(-1, 1, 0.9, "stereographic/Panini parameter", "1 for full stereographic/Panini projection. Lower values reduce the effect.\n\n"
|
||||||
|
"HyperRogue uses "
|
||||||
|
"a quick implementation, so parameter values too close to 1 may "
|
||||||
|
"be buggy (outside of raycasting); try e.g. 0.9 instead.", 'd')
|
||||||
->set_reaction(reset_all_shaders);
|
->set_reaction(reset_all_shaders);
|
||||||
param_f(stereo_alpha, "stereo_alpha", 0)
|
|
||||||
->set_reaction(reset_all_shaders);
|
|
||||||
param_b(equirectangular, "equirectangular");
|
|
||||||
|
|
||||||
callhooks(hooks_configfile);
|
callhooks(hooks_configfile);
|
||||||
|
|
||||||
@ -2473,7 +2476,7 @@ EX void explain_detail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX ld max_fov_angle() {
|
EX ld max_fov_angle() {
|
||||||
auto& p = panini_alpha ? panini_alpha : stereo_alpha;
|
auto p = get_stereo_param();
|
||||||
if(p >= 1 || p <= -1) return 360;
|
if(p >= 1 || p <= -1) return 360;
|
||||||
return acos(-p) * 2 / degree;
|
return acos(-p) * 2 / degree;
|
||||||
}
|
}
|
||||||
@ -2481,7 +2484,7 @@ EX ld max_fov_angle() {
|
|||||||
EX void add_edit_fov(char key IS('f')) {
|
EX void add_edit_fov(char key IS('f')) {
|
||||||
|
|
||||||
string sfov = fts(vid.fov) + "°";
|
string sfov = fts(vid.fov) + "°";
|
||||||
if(panini_alpha || stereo_alpha) {
|
if(get_stereo_param()) {
|
||||||
sfov += " / " + fts(max_fov_angle()) + "°";
|
sfov += " / " + fts(max_fov_angle()) + "°";
|
||||||
}
|
}
|
||||||
dialog::addSelItem(XLAT("field of view"), sfov, key);
|
dialog::addSelItem(XLAT("field of view"), sfov, key);
|
||||||
@ -2498,37 +2501,11 @@ EX void add_edit_fov(char key IS('f')) {
|
|||||||
);
|
);
|
||||||
dialog::bound_low(1e-8);
|
dialog::bound_low(1e-8);
|
||||||
dialog::bound_up(max_fov_angle() - 0.01);
|
dialog::bound_up(max_fov_angle() - 0.01);
|
||||||
string quick =
|
dialog::get_di().extra_options = [] {
|
||||||
XLAT(
|
add_edit(vid.stereo_mode, 'M');
|
||||||
"HyperRogue uses "
|
if(among(vid.stereo_mode, sPanini, sStereographic)) {
|
||||||
"a quick implementation, so parameter values too close to 1 may "
|
add_edit(vid.stereo_param, 'P');
|
||||||
"be buggy (outside of raycasting); try e.g. 0.9 instead."
|
}
|
||||||
);
|
|
||||||
dialog::get_di().extra_options = [quick] {
|
|
||||||
dialog::addSelItem(XLAT("Panini projection"), fts(panini_alpha), 'P');
|
|
||||||
dialog::add_action([quick] {
|
|
||||||
dialog::editNumber(panini_alpha, 0, 1, 0.1, 0, "Panini parameter",
|
|
||||||
XLAT(
|
|
||||||
"The Panini projection is an alternative perspective projection "
|
|
||||||
"which allows very wide field-of-view values.\n\n") + quick
|
|
||||||
);
|
|
||||||
#if CAP_GL
|
|
||||||
dialog::get_di().reaction = reset_all_shaders;
|
|
||||||
#endif
|
|
||||||
dialog::get_di().extra_options = [] { add_edit_fov('F'); };
|
|
||||||
});
|
|
||||||
dialog::addSelItem(XLAT("spherical perspective projection"), fts(stereo_alpha), 'S');
|
|
||||||
dialog::add_action([quick] {
|
|
||||||
dialog::editNumber(stereo_alpha, 0, 1, 0.1, 0, "spherical perspective parameter",
|
|
||||||
XLAT(
|
|
||||||
"Set to 1 to get stereographic projection, "
|
|
||||||
"which allows very wide field-of-view values.\n\n") + quick
|
|
||||||
);
|
|
||||||
#if CAP_GL
|
|
||||||
dialog::get_di().reaction = reset_all_shaders;
|
|
||||||
#endif
|
|
||||||
dialog::get_di().extra_options = [] { add_edit_fov('F'); };
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2554,6 +2531,9 @@ EX void showStereo() {
|
|||||||
case sLR:
|
case sLR:
|
||||||
dialog::addSelItem(XLAT("distance between images"), fts(vid.lr_eyewidth), 'd');
|
dialog::addSelItem(XLAT("distance between images"), fts(vid.lr_eyewidth), 'd');
|
||||||
break;
|
break;
|
||||||
|
case sPanini: case sStereographic:
|
||||||
|
add_edit(vid.stereo_param);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dialog::addBreak(100);
|
dialog::addBreak(100);
|
||||||
break;
|
break;
|
||||||
|
17
graph.cpp
17
graph.cpp
@ -22,10 +22,6 @@ EX bool spatial_graphics;
|
|||||||
EX bool wmspatial, wmescher, wmplain, wmblack, wmascii, wmascii3;
|
EX bool wmspatial, wmescher, wmplain, wmblack, wmascii, wmascii3;
|
||||||
EX bool mmspatial, mmhigh, mmmon, mmitem;
|
EX bool mmspatial, mmhigh, mmmon, mmitem;
|
||||||
|
|
||||||
EX ld panini_alpha = 0;
|
|
||||||
EX ld stereo_alpha = 0;
|
|
||||||
EX bool equirectangular;
|
|
||||||
|
|
||||||
EX int detaillevel = 0;
|
EX int detaillevel = 0;
|
||||||
|
|
||||||
EX bool first_cell_to_draw = true;
|
EX bool first_cell_to_draw = true;
|
||||||
@ -4122,10 +4118,14 @@ EX ld threshold, xyz_threshold;
|
|||||||
|
|
||||||
EX bool clip_checked = false;
|
EX bool clip_checked = false;
|
||||||
|
|
||||||
|
EX bool other_stereo_mode() {
|
||||||
|
return among(vid.stereo_mode, sODS, sPanini, sStereographic, sEquirectangular);
|
||||||
|
}
|
||||||
|
|
||||||
void make_clipping_planes() {
|
void make_clipping_planes() {
|
||||||
#if MAXMDIM >= 4
|
#if MAXMDIM >= 4
|
||||||
clip_checked = false;
|
clip_checked = false;
|
||||||
if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha || stereo_alpha || gproduct || embedded_plane) return;
|
if(!frustum_culling || PIU(sphere) || experimental || other_stereo_mode() || gproduct || embedded_plane) return;
|
||||||
|
|
||||||
if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe())
|
if(WDIM == 3 && pmodel == mdPerspective && !nonisotropic && !in_s2xe())
|
||||||
threshold = sin_auto(cgi.corner_bonus), xyz_threshold = 0, clip_checked = true;
|
threshold = sin_auto(cgi.corner_bonus), xyz_threshold = 0, clip_checked = true;
|
||||||
@ -5496,6 +5496,11 @@ EX ld min_scale = 1e-6;
|
|||||||
|
|
||||||
EX int forced_center_down = ISANDROID ? 2 : ISIOS ? 40 : 40;
|
EX int forced_center_down = ISANDROID ? 2 : ISIOS ? 40 : 40;
|
||||||
|
|
||||||
|
EX ld get_stereo_param() {
|
||||||
|
if(among(vid.stereo_mode, sPanini, sStereographic)) return vid.stereo_param;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
EX void calcparam() {
|
EX void calcparam() {
|
||||||
|
|
||||||
DEBBI(DF_GRAPH, ("calc param"));
|
DEBBI(DF_GRAPH, ("calc param"));
|
||||||
@ -5557,7 +5562,7 @@ EX void calcparam() {
|
|||||||
cd->ycenter += cd->scrsize * pconf.yposition;
|
cd->ycenter += cd->scrsize * pconf.yposition;
|
||||||
|
|
||||||
ld fov = vid.fov * degree / 2;
|
ld fov = vid.fov * degree / 2;
|
||||||
cd->tanfov = sin(fov) / (cos(fov) + (panini_alpha ? panini_alpha : stereo_alpha));
|
cd->tanfov = sin(fov) / (cos(fov) + get_stereo_param());
|
||||||
|
|
||||||
callhooks(hooks_calcparam);
|
callhooks(hooks_calcparam);
|
||||||
reset_projection();
|
reset_projection();
|
||||||
|
3
hyper.h
3
hyper.h
@ -250,7 +250,7 @@ struct charstyle {
|
|||||||
bool lefthanded;
|
bool lefthanded;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eStereo { sOFF, sAnaglyph, sLR, sODS };
|
enum eStereo { sOFF, sAnaglyph, sLR, sODS, sPanini, sStereographic, sEquirectangular };
|
||||||
|
|
||||||
enum eModel : int;
|
enum eModel : int;
|
||||||
|
|
||||||
@ -395,6 +395,7 @@ struct videopar {
|
|||||||
int cells_generated_limit; // limit on cells generated per frame
|
int cells_generated_limit; // limit on cells generated per frame
|
||||||
|
|
||||||
eStereo stereo_mode;
|
eStereo stereo_mode;
|
||||||
|
ld stereo_param;
|
||||||
ld ipd;
|
ld ipd;
|
||||||
ld lr_eyewidth, anaglyph_eyewidth;
|
ld lr_eyewidth, anaglyph_eyewidth;
|
||||||
ld fov;
|
ld fov;
|
||||||
|
18
legacy.cpp
18
legacy.cpp
@ -457,6 +457,24 @@ int read_legacy_args_anim() {
|
|||||||
} */
|
} */
|
||||||
/* skiprope:legacy.cpp pconf.skiprope += skiprope_rotation * t * TAU / period; */
|
/* skiprope:legacy.cpp pconf.skiprope += skiprope_rotation * t * TAU / period; */
|
||||||
}
|
}
|
||||||
|
else if(argis("-palpha")) {
|
||||||
|
PHASEFROM(2);
|
||||||
|
#if CAP_GL
|
||||||
|
shift_arg_formula(vid.stereo_param, reset_all_shaders);
|
||||||
|
#else
|
||||||
|
shift_arg_formula(vid.stereo_param);
|
||||||
|
#endif
|
||||||
|
vid.stereo_mode = sPanini;
|
||||||
|
}
|
||||||
|
else if(argis("-salpha")) {
|
||||||
|
PHASEFROM(2);
|
||||||
|
#if CAP_GL
|
||||||
|
shift_arg_formula(vid.stereo_param, reset_all_shaders);
|
||||||
|
#else
|
||||||
|
shift_arg_formula(vid.stereo_param);
|
||||||
|
#endif
|
||||||
|
vid.stereo_mode = sStereographic;
|
||||||
|
}
|
||||||
else return 1;
|
else return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
18
models.cpp
18
models.cpp
@ -234,7 +234,7 @@ EX namespace models {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EX bool has_orientation(eModel m) {
|
EX bool has_orientation(eModel m) {
|
||||||
if(is_perspective(m) && panini_alpha) return true;
|
if(is_perspective(m) && vid.stereo_mode == sPanini) return true;
|
||||||
if(nonisotropic) return false;
|
if(nonisotropic) return false;
|
||||||
return (mdinf[m].flags & mf::orientation);
|
return (mdinf[m].flags & mf::orientation);
|
||||||
}
|
}
|
||||||
@ -884,22 +884,6 @@ EX namespace models {
|
|||||||
PHASEFROM(2);
|
PHASEFROM(2);
|
||||||
shift_arg_formula(vpconf.skiprope);
|
shift_arg_formula(vpconf.skiprope);
|
||||||
}
|
}
|
||||||
else if(argis("-palpha")) {
|
|
||||||
PHASEFROM(2);
|
|
||||||
#if CAP_GL
|
|
||||||
shift_arg_formula(panini_alpha, reset_all_shaders);
|
|
||||||
#else
|
|
||||||
shift_arg_formula(panini_alpha);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(argis("-salpha")) {
|
|
||||||
PHASEFROM(2);
|
|
||||||
#if CAP_GL
|
|
||||||
shift_arg_formula(stereo_alpha, reset_all_shaders);
|
|
||||||
#else
|
|
||||||
shift_arg_formula(stereo_alpha);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(argis("-zoom")) {
|
else if(argis("-zoom")) {
|
||||||
PHASEFROM(2); shift_arg_formula(vpconf.scale);
|
PHASEFROM(2); shift_arg_formula(vpconf.scale);
|
||||||
}
|
}
|
||||||
|
@ -1434,10 +1434,10 @@ void raygen::emit_iterate(int gid1) {
|
|||||||
fsh += "uniform mediump float uLevelLines;\n";
|
fsh += "uniform mediump float uLevelLines;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(panini_alpha)
|
if(vid.stereo_mode == sPanini)
|
||||||
fmain += panini_shader();
|
fmain += panini_shader();
|
||||||
|
|
||||||
else if(stereo_alpha)
|
else if(vid.stereo_mode == sStereographic)
|
||||||
fmain += stereo_shader();
|
fmain += stereo_shader();
|
||||||
|
|
||||||
#ifndef GLES_ONLY
|
#ifndef GLES_ONLY
|
||||||
@ -1965,8 +1965,9 @@ void raygen::create() {
|
|||||||
" mediump mat4 vw = uStart * xzspin(-lambda) * "+f_xpush()+"(eye) * yzspin(phi);\n"
|
" mediump mat4 vw = uStart * xzspin(-lambda) * "+f_xpush()+"(eye) * yzspin(phi);\n"
|
||||||
" mediump vec4 at0 = vec4(0., 0., 1., 0.);\n";
|
" mediump vec4 at0 = vec4(0., 0., 1., 0.);\n";
|
||||||
// todo: will not work in product!
|
// todo: will not work in product!
|
||||||
|
*/
|
||||||
|
|
||||||
else if(equirectangular) fmain +=
|
else if(vid.stereo_mode == sEquirectangular) fmain +=
|
||||||
" mediump float lambda = at.x * PI;\n" // -PI to PI
|
" mediump float lambda = at.x * PI;\n" // -PI to PI
|
||||||
" mediump float phi = at.y * PI / 2.0;\n"
|
" mediump float phi = at.y * PI / 2.0;\n"
|
||||||
" mediump mat4 vw = uStart;\n"
|
" mediump mat4 vw = uStart;\n"
|
||||||
@ -1978,10 +1979,10 @@ void raygen::create() {
|
|||||||
" mediump vec4 at0 = at;\n"
|
" mediump vec4 at0 = at;\n"
|
||||||
" at0.y = -at.y;\n"
|
" at0.y = -at.y;\n"
|
||||||
" at0.w = 0.;\n";
|
" at0.w = 0.;\n";
|
||||||
|
|
||||||
if(panini_alpha) fmain +=
|
if(vid.stereo_mode == sPanini) fmain +=
|
||||||
"mediump float hr = at0.x*at0.x;\n"
|
"mediump float hr = at0.x*at0.x;\n"
|
||||||
"mediump float alpha = " + to_glsl(panini_alpha) + ";\n"
|
"mediump float alpha = " + to_glsl(get_stereo_param()) + ";\n"
|
||||||
"mediump float A = 1. + hr;\n"
|
"mediump float A = 1. + hr;\n"
|
||||||
"mediump float B = -2.*hr*alpha;\n"
|
"mediump float B = -2.*hr*alpha;\n"
|
||||||
"mediump float C = 1. - hr*alpha*alpha;\n"
|
"mediump float C = 1. - hr*alpha*alpha;\n"
|
||||||
@ -1995,9 +1996,9 @@ void raygen::create() {
|
|||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
else if(stereo_alpha) fmain +=
|
else if(vid.stereo_mode == sStereographic) fmain +=
|
||||||
"mediump float hr = at0.x*at0.x+at0.y*at0.y;\n"
|
"mediump float hr = at0.x*at0.x+at0.y*at0.y;\n"
|
||||||
"mediump float alpha = " + to_glsl(stereo_alpha) + ";\n"
|
"mediump float alpha = " + to_glsl(get_stereo_param()) + ";\n"
|
||||||
"mediump float A = 1. + hr;\n"
|
"mediump float A = 1. + hr;\n"
|
||||||
"mediump float B = -2.*hr*alpha;\n"
|
"mediump float B = -2.*hr*alpha;\n"
|
||||||
"mediump float C = 1. - hr*alpha*alpha;\n"
|
"mediump float C = 1. - hr*alpha*alpha;\n"
|
||||||
@ -2579,7 +2580,7 @@ EX void cast() {
|
|||||||
#else
|
#else
|
||||||
if(0) ;
|
if(0) ;
|
||||||
#endif
|
#endif
|
||||||
else if(equirectangular) {
|
else if(among(vid.stereo_mode, sODS, sEquirectangular)) {
|
||||||
glUniformMatrix4fv(o->uProjection, 1, 0, glhr::tmtogl_transpose(Id).as_array());
|
glUniformMatrix4fv(o->uProjection, 1, 0, glhr::tmtogl_transpose(Id).as_array());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -77,7 +77,7 @@ EX string panini_shader() {
|
|||||||
"float s = t.z;\n"
|
"float s = t.z;\n"
|
||||||
"float l = length(t.xyz);\n"
|
"float l = length(t.xyz);\n"
|
||||||
"t /= max(length(t.xz), 1e-2);\n"
|
"t /= max(length(t.xz), 1e-2);\n"
|
||||||
"t.z += " + glhr::to_glsl(panini_alpha) + ";\n"
|
"t.z += " + glhr::to_glsl(get_stereo_param()) + ";\n"
|
||||||
"t *= l;\n"
|
"t *= l;\n"
|
||||||
"t.w = 1.;\n";
|
"t.w = 1.;\n";
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ EX string stereo_shader() {
|
|||||||
"float s = t.z;\n"
|
"float s = t.z;\n"
|
||||||
"float l = length(t.xyz);\n"
|
"float l = length(t.xyz);\n"
|
||||||
"t /= max(l, 1e-2);\n"
|
"t /= max(l, 1e-2);\n"
|
||||||
"t.z += " + glhr::to_glsl(stereo_alpha) + ";\n"
|
"t.z += " + glhr::to_glsl(get_stereo_param()) + ";\n"
|
||||||
"t *= l;\n"
|
"t *= l;\n"
|
||||||
"t.w = 1.;\n";
|
"t.w = 1.;\n";
|
||||||
}
|
}
|
||||||
@ -515,13 +515,13 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
|||||||
if(shader_flags & GF_LEVELS) vmain += "vPos = t;\n";
|
if(shader_flags & GF_LEVELS) vmain += "vPos = t;\n";
|
||||||
if(treset) vmain += "t[3] = 1.0;\n";
|
if(treset) vmain += "t[3] = 1.0;\n";
|
||||||
|
|
||||||
if((shader_flags & SF_PERS3) && panini_alpha && !vrhr::rendering_eye()) {
|
if((shader_flags & SF_PERS3) && vid.stereo_mode == sPanini && !vrhr::rendering_eye()) {
|
||||||
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
|
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
|
||||||
/* panini */
|
/* panini */
|
||||||
vmain += panini_shader();
|
vmain += panini_shader();
|
||||||
shader_flags |= SF_ORIENT;
|
shader_flags |= SF_ORIENT;
|
||||||
}
|
}
|
||||||
else if((shader_flags & SF_PERS3) && stereo_alpha && !vrhr::rendering_eye()) {
|
else if((shader_flags & SF_PERS3) && vid.stereo_mode == sStereographic && !vrhr::rendering_eye()) {
|
||||||
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
|
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
|
||||||
vmain += stereo_shader();
|
vmain += stereo_shader();
|
||||||
shader_flags |= SF_ORIENT;
|
shader_flags |= SF_ORIENT;
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CAP_ODS
|
#ifndef CAP_ODS
|
||||||
#define CAP_ODS 0
|
#define CAP_ODS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CAP_VIDEO
|
#ifndef CAP_VIDEO
|
||||||
|
Loading…
Reference in New Issue
Block a user