1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-01-11 18:00:34 +00:00

stereographic projection added

This commit is contained in:
Zeno Rogue 2021-03-21 11:28:10 +01:00
parent 421ff4a94a
commit 0f081fb1ab
5 changed files with 63 additions and 7 deletions

View File

@ -1027,6 +1027,7 @@ 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(panini_alpha, "panini_alpha", 0); param_f(panini_alpha, "panini_alpha", 0);
param_f(stereo_alpha, "stereo_alpha", 0);
callhooks(hooks_configfile); callhooks(hooks_configfile);
@ -1863,14 +1864,15 @@ EX void explain_detail() {
} }
EX ld max_fov_angle() { EX ld max_fov_angle() {
if(panini_alpha >= 1 || panini_alpha <= -1) return 360; auto& p = panini_alpha ? panini_alpha : stereo_alpha;
return acos(-panini_alpha) * 2 / degree; if(p >= 1 || p <= -1) return 360;
return acos(-p) * 2 / degree;
} }
EX void add_edit_fov(char key IS('f'), bool pop IS(false)) { EX void add_edit_fov(char key IS('f'), bool pop IS(false)) {
string sfov = fts(vid.fov) + "°"; string sfov = fts(vid.fov) + "°";
if(panini_alpha) { if(panini_alpha || stereo_alpha) {
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);
@ -1897,7 +1899,22 @@ EX void add_edit_fov(char key IS('f'), bool pop IS(false)) {
"The Panini projection is an alternative perspective projection " "The Panini projection is an alternative perspective projection "
"which allows very wide field-of-view values. HyperRogue uses " "which allows very wide field-of-view values. HyperRogue uses "
"a quick implementation, so parameter values too close to 1 may " "a quick implementation, so parameter values too close to 1 may "
"be buggy; try e.g. 0.9 instead.") "be buggy (outside of raycasting); try e.g. 0.9 instead.")
);
dialog::reaction = reset_all_shaders;
dialog::extra_options = [] {
add_edit_fov('F', true);
};
});
dialog::addSelItem(XLAT("spherical perspective projection"), fts(stereo_alpha), 'S');
dialog::add_action([] {
popScreen();
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. HyperRogue uses "
"a quick implementation, so parameter values too close to 1 may "
"be buggy (outside of raycasting); try e.g. 0.9 instead.")
); );
dialog::reaction = reset_all_shaders; dialog::reaction = reset_all_shaders;
dialog::extra_options = [] { dialog::extra_options = [] {

View File

@ -23,6 +23,7 @@ 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 panini_alpha = 0;
EX ld stereo_alpha = 0;
EX int detaillevel = 0; EX int detaillevel = 0;
@ -3742,7 +3743,7 @@ EX bool clip_checked = false;
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) return; if(!frustum_culling || PIU(sphere) || experimental || vid.stereo_mode == sODS || panini_alpha || stereo_alpha) 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;
@ -4980,7 +4981,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); cd->tanfov = sin(fov) / (cos(fov) + (panini_alpha ? panini_alpha : stereo_alpha));
callhooks(hooks_calcparam); callhooks(hooks_calcparam);
reset_projection(); reset_projection();

View File

@ -892,6 +892,10 @@ EX namespace models {
PHASEFROM(2); PHASEFROM(2);
shift_arg_formula(panini_alpha, reset_all_shaders); shift_arg_formula(panini_alpha, reset_all_shaders);
} }
else if(argis("-salpha")) {
PHASEFROM(2);
shift_arg_formula(stereo_alpha, reset_all_shaders);
}
else if(argis("-zoom")) { else if(argis("-zoom")) {
PHASEFROM(2); shift_arg_formula(vpconf.scale); PHASEFROM(2); shift_arg_formula(vpconf.scale);
} }

View File

@ -436,7 +436,23 @@ void enable_raycaster() {
"at0.xyz *= hz+alpha;\n" "at0.xyz *= hz+alpha;\n"
"at0.z = hz;\n}" "at0.z = hz;\n}"
" else at0.z = 0.;\n" " else at0.z = 0.;\n"
"\n" "\n"
;
else if(stereo_alpha) fmain +=
"mediump float hr = at0.x*at0.x+at0.y*at0.y;\n"
"mediump float alpha = " + to_glsl(stereo_alpha) + ";\n"
"mediump float A = 1. + hr;\n"
"mediump float B = -2.*hr*alpha;\n"
"mediump float C = 1. - hr*alpha*alpha;\n"
"B /= A; C /= A;\n"
"mediump float hz = B / 2. + sqrt(C + B*B/4.);\n"
"if(abs(hz) > 1e-3) {"
"at0.xyz *= hz+alpha;\n"
"at0.z = hz;\n}"
" else at0.z = 0.;\n"
"\n"
; ;
fmain += fmain +=
@ -1241,6 +1257,9 @@ void enable_raycaster() {
if(panini_alpha) if(panini_alpha)
fmain += panini_shader(); fmain += panini_shader();
else if(stereo_alpha)
fmain += stereo_shader();
#ifndef GLES_ONLY #ifndef GLES_ONLY
fmain += fmain +=
" gl_FragDepth = (" + to_glsl(-vnear-vfar)+"+t.w*" + to_glsl(2*vnear*vfar)+"/t.z)/" + to_glsl(vnear-vfar)+";\n" " gl_FragDepth = (" + to_glsl(-vnear-vfar)+"+t.w*" + to_glsl(2*vnear*vfar)+"/t.z)/" + to_glsl(vnear-vfar)+";\n"

View File

@ -77,6 +77,17 @@ EX string panini_shader() {
"t.w = 1.;\n"; "t.w = 1.;\n";
} }
EX string stereo_shader() {
return
"t.w += 1.; t *= 2. / t.w; t.w -= 1.;\n"
"float s = t.z;\n"
"float l = length(t.xyz);\n"
"t /= max(l, 1e-2);\n"
"t.z += " + glhr::to_glsl(panini_alpha) + ";\n"
"t *= l;\n"
"t.w = 1.;\n";
}
shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) { shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
string varying, vsh, fsh, vmain = "void main() {\n", fmain = "void main() {\n"; string varying, vsh, fsh, vmain = "void main() {\n", fmain = "void main() {\n";
@ -415,6 +426,10 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
vmain += panini_shader(); vmain += panini_shader();
shader_flags |= SF_ORIENT; shader_flags |= SF_ORIENT;
} }
else if((shader_flags & SF_PERS3) && stereo_alpha) {
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
vmain += stereo_shader();
}
vmain += "gl_Position = uP * t;\n"; vmain += "gl_Position = uP * t;\n";
} }