1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-23 21:07:17 +00:00

redesigned shader system

This commit is contained in:
Zeno Rogue 2019-10-21 22:34:20 +02:00
parent 7babf20ef4
commit 09fcd14aa7
13 changed files with 1310 additions and 1359 deletions

View File

@ -38,8 +38,7 @@ struct display_data {
bool sidescreen;
ld tanfov;
GLfloat scrdist, scrdist_text;
flagtype next_shader_flags;
ld eyewidth();
bool stereo_active();
@ -85,8 +84,6 @@ namespace stereo {
ld ipd;
ld lr_eyewidth, anaglyph_eyewidth;
ld fov, tanfov;
GLfloat scrdist;
}
bool display_data::in_anaglyph() { return vid.stereo_mode == sAnaglyph; }
@ -226,25 +223,6 @@ void setcameraangle(bool b) { }
#if CAP_GL
EX bool shaderside_projection;
EX void start_projection(int ed, bool perspective) {
glhr::use_projection();
glhr::new_projection();
shaderside_projection = perspective;
auto cd = current_display;
if(ed && vid.stereo_mode == sLR) {
glhr::projection_multiply(glhr::translate(ed, 0, 0));
glhr::projection_multiply(glhr::scale(2, 1, 1));
}
ld tx = (cd->xcenter-cd->xtop)*2./cd->xsize - 1;
ld ty = (cd->ycenter-cd->ytop)*2./cd->ysize - 1;
glhr::projection_multiply(glhr::translate(tx, -ty, 0));
}
#if CAP_VR
EX hookset<bool()> *hooks_vr_eye_view, *hooks_vr_eye_projection;
#endif
@ -257,15 +235,6 @@ EX void eyewidth_translate(int ed) {
if(ed) glhr::projection_multiply(glhr::translate(-ed * current_display->eyewidth(), 0, 0));
}
glhr::glmatrix model_orientation_gl() {
glhr::glmatrix s = glhr::id;
for(int a=0; a<GDIM; a++)
models::apply_orientation(s[a][1], s[a][0]);
if(GDIM == 3) for(int a=0; a<GDIM; a++)
models::apply_orientation_yz(s[a][2], s[a][1]);
return s;
}
tuple<int, eModel, display_data*, int> last_projection;
EX bool new_projection_needed;
#if HDR
@ -275,7 +244,7 @@ inline void reset_projection() { new_projection_needed = true; }
void display_data::set_all(int ed) {
auto t = this;
auto current_projection = tie(ed, pmodel, t, current_rbuffer);
if(new_projection_needed || last_projection != current_projection) {
if(new_projection_needed || !glhr::current_glprogram || (next_shader_flags & GF_which) != (glhr::current_glprogram->shader_flags & GF_which) || current_projection != last_projection) {
last_projection = current_projection;
set_projection(ed);
set_mask(ed);
@ -284,194 +253,6 @@ void display_data::set_all(int ed) {
}
}
void display_data::set_projection(int ed) {
DEBBI(DF_GRAPH, ("current_display->set_projection"));
bool pers3 = false;
bool apply_models = !among(pmodel, mdUnchanged, mdFlatten, mdRug);
shaderside_projection = false;
glhr::new_shader_projection = glhr::shader_projection::standard;
bool in_solnih = false;
if(vid.consider_shader_projection && pmodel == mdDisk && !spherespecial && !(hyperbolic && vid.alpha <= -1) && MDIM == 3)
shaderside_projection = true;
else if(vid.consider_shader_projection && !glhr::noshaders) {
if(pmodel == (nonisotropic ? mdHyperboloid : mdDisk) && !spherespecial && !(hyperbolic && vid.alpha <= -1) && GDIM == 3 && apply_models)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::ball;
if(pmodel == mdBand && hyperbolic && apply_models)
shaderside_projection = true, glhr::new_shader_projection = (GDIM == 2 ? glhr::shader_projection::band : glhr::shader_projection::band3);
if(pmodel == mdHalfplane && hyperbolic && apply_models && GDIM == 2)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::halfplane;
if(pmodel == mdHalfplane && hyperbolic && apply_models && GDIM == 3 && vid.alpha == 1)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::halfplane3;
if(GDIM == 3 && hyperbolic && apply_models && pmodel == mdPerspective)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardH3, pers3 = true;
if(GDIM == 3 && translatable && apply_models && pmodel == mdPerspective)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardR3, pers3 = true;
if(GDIM == 3 && apply_models && pmodel == mdPerspective && in_s2xe())
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardR3, pers3 = true;
if(GDIM == 3 && apply_models && pmodel == mdPerspective && in_h2xe())
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardEH2, pers3 = true;
if(GDIM == 3 && apply_models && pmodel == mdGeodesic && solnih) {
shaderside_projection = true, pers3 = true, in_solnih = true;
if(sol && nih)
glhr::new_shader_projection = glhr::shader_projection::standardSolvNIH;
else if(sol)
glhr::new_shader_projection = glhr::shader_projection::standardSolv;
else
glhr::new_shader_projection = glhr::shader_projection::standardNIH;
}
if(GDIM == 3 && apply_models && pmodel == mdGeodesic && sl2)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardSL2, pers3 = true;
if(GDIM == 3 && apply_models && pmodel == mdGeodesic && nil)
shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::standardNil, pers3 = true;
if(GDIM == 3 && sphere && apply_models && pmodel == mdPerspective) {
shaderside_projection = true; pers3 = true;
int sp = spherephase & 3;
if(sp == 0) glhr::new_shader_projection = glhr::shader_projection::standardS30;
if(sp == 1) glhr::new_shader_projection = glhr::shader_projection::standardS31;
if(sp == 2) glhr::new_shader_projection = glhr::shader_projection::standardS32;
if(sp == 3) glhr::new_shader_projection = glhr::shader_projection::standardS33;
}
}
if(pmodel == mdFlatten) shaderside_projection = true, glhr::new_shader_projection = glhr::shader_projection::flatten;
start_projection(ed, shaderside_projection);
if(pmodel == mdRug) return;
#if CAP_SOLV
if(in_solnih) {
auto &tab = solnihv::get_tabled();
GLuint invexpid = tab.get_texture_id();
glActiveTexture(GL_TEXTURE0 + glhr::INVERSE_EXP_BINDING);
glBindTexture(GL_TEXTURE_3D, invexpid);
glActiveTexture(GL_TEXTURE0 + 0);
glhr::set_solv_prec(tab.PRECX, tab.PRECY, tab.PRECZ);
}
#endif
if(glhr::new_shader_projection == glhr::shader_projection::standardSL2) {
glhr::set_index_sl(0);
glhr::set_sl_iterations(slr::steps);
}
auto cd = current_display;
if(!shaderside_projection || glhr::new_shader_projection == glhr::shader_projection::flatten) {
if(GDIM == 3 && apply_models) {
glhr::projection_multiply(glhr::ortho(cd->xsize/2, -cd->ysize/2, 1));
glhr::id_modelview();
}
else {
glhr::projection_multiply(glhr::ortho(cd->xsize/2, -cd->ysize/2, abs(current_display->scrdist) + 30000));
if(ed) {
glhr::glmatrix m = glhr::id;
m[2][0] -= ed;
glhr::projection_multiply(m);
}
glhr::id_modelview();
}
}
else {
if(hyperbolic && vid.alpha > -1 && GDIM == 2) {
// Because of the transformation from H3 to the Minkowski hyperboloid,
// points with negative Z can be generated in some 3D settings.
// This happens for points below the camera, but above the plane.
// These points should still be viewed, though, so we disable the
// depth clipping
glhr::projection_multiply(glhr::scale(1,1,0));
}
eyewidth_translate(ed);
#if CAP_VR
if(callhandlers(false, hooks_vr_eye_projection)) ; else
#endif
if(pers3) {
glhr::projection_multiply(glhr::frustum(current_display->tanfov, current_display->tanfov * cd->ysize / cd->xsize));
glhr::projection_multiply(glhr::scale(1, -1, -1));
if(nisot::local_perspective_used()) {
if(prod) {
for(int i=0; i<3; i++) nisot::local_perspective[3][i] = nisot::local_perspective[i][3] = 0;
nisot::local_perspective[3][3] = 1;
}
glhr::projection_multiply(glhr::tmtogl_transpose(nisot::local_perspective));
}
}
else if(MDIM == 4) {
glhr::glmatrix M = glhr::ortho(cd->xsize/current_display->radius/2, -cd->ysize/current_display->radius/2, 1);
using models::clip_max;
using models::clip_min;
M[2][2] = 2 / (clip_max - clip_min);
M[3][2] = (clip_min + clip_max) / (clip_max - clip_min);
glhr::projection_multiply(M);
if(nisot::local_perspective_used())
glhr::projection_multiply(glhr::tmtogl_transpose(nisot::local_perspective));
}
else {
glhr::projection_multiply(glhr::frustum(cd->xsize / cd->ysize, 1));
GLfloat sc = current_display->radius / (cd->ysize/2.);
glhr::projection_multiply(glhr::scale(sc, -sc, -1));
}
if(ed) {
if(pers3) {
if(anyshiftclick)
glhr::projection_multiply(glhr::tmtogl(xpush(vid.ipd * ed/2)));
else {
glhr::using_eyeshift = true;
glhr::eyeshift = glhr::tmtogl(xpush(vid.ipd * ed/2));
}
}
else
glhr::projection_multiply(glhr::translate(vid.ipd * ed/2, 0, 0));
}
if(pers3) {
glhr::fog_max(1/sightranges[geometry], darkena(backcolor, 0, 0xFF));
}
if(glhr::new_shader_projection == glhr::shader_projection::ball)
glhr::set_ualpha(vid.alpha);
if(among(glhr::new_shader_projection, glhr::shader_projection::band, glhr::shader_projection::band3)) {
glhr::projection_multiply(model_orientation_gl());
glhr::projection_multiply(glhr::scale(2 / M_PI, 2 / M_PI, GDIM == 3 ? 2/M_PI : 1));
}
if(among(glhr::new_shader_projection, glhr::shader_projection::halfplane, glhr::shader_projection::halfplane3)) {
glhr::projection_multiply(model_orientation_gl());
glhr::projection_multiply(glhr::translate(0, 1, 0));
glhr::projection_multiply(glhr::scale(-1, 1, 1));
glhr::projection_multiply(glhr::scale(models::halfplane_scale, models::halfplane_scale, GDIM == 3 ? models::halfplane_scale : 1));
glhr::projection_multiply(glhr::translate(0, 0.5, 0));
}
}
if(vid.camera_angle && !among(pmodel, mdUnchanged, mdFlatten, mdRug)) {
ld cam = vid.camera_angle * degree;
GLfloat cc = cos(cam);
GLfloat ss = sin(cam);
GLfloat yzspin[16] = {
1, 0, 0, 0,
0, cc, ss, 0,
0, -ss, cc, 0,
0, 0, 0, 1
};
glhr::projection_multiply(glhr::as_glmatrix(yzspin));
}
}
void display_data::set_mask(int ed) {
if(ed == 0 || vid.stereo_mode != sAnaglyph) {
glColorMask( GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE );
@ -1156,7 +937,7 @@ EX void drawCircle(int x, int y, int size, color_t color, color_t fillcolor IS(0
glflush();
glhr::be_nontextured();
glhr::id_modelview();
dynamicval<eModel> em(pmodel, mdUnchanged);
dynamicval<eModel> em(pmodel, mdPixel);
glcoords.clear();
x -= current_display->xcenter; y -= current_display->ycenter;
int pts = size * 4;
@ -1164,7 +945,7 @@ EX void drawCircle(int x, int y, int size, color_t color, color_t fillcolor IS(0
if(ISMOBILE && pts > 72) pts = 72;
for(int r=0; r<pts; r++) {
float rr = (M_PI * 2 * r) / pts;
glcoords.push_back(glhr::makevertex(x + size * sin(rr), y + size * vid.stretch * cos(rr), current_display->scrdist));
glcoords.push_back(glhr::makevertex(x + size * sin(rr), y + size * vid.stretch * cos(rr), 0));
}
current_display->set_all(0);
glhr::vertices(glcoords);

View File

@ -313,7 +313,7 @@ enum eModel {
// 25
mdMollweide, mdCentralCyl, mdCollignon,
// 26..
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial, mdRug, mdFlatten
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
};
typedef unsigned long long flagtype;

View File

@ -126,7 +126,6 @@ EX int shapes_merged;
color_t triangle_color, line_color;
vector<glvertex> triangle_vertices;
vector<glvertex> line_vertices;
EX void glapplymatrix(const transmatrix& V);
#endif
EX void glflush() {
@ -159,14 +158,14 @@ EX void glflush() {
if(isize(text_vertices)) {
// printf("%08X | %d texts, %d vertices\n", text_color, texts_merged, isize(text_vertices));
glhr::be_textured();
dynamicval<eModel> pm(pmodel, mdUnchanged);
current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> m(pmodel, mdPixel);
if(!svg::in) current_display->set_all(0);
glBindTexture(GL_TEXTURE_2D, text_texture);
glhr::color2(text_color);
glhr::set_depthtest(false);
for(int ed = (current_display->stereo_active() && text_shift)?-1:0; ed<2; ed+=2) {
glhr::set_modelview(glhr::translate(-ed*text_shift-current_display->xcenter,-current_display->ycenter, current_display->scrdist));
glhr::set_modelview(glhr::translate(-ed*text_shift-current_display->xcenter,-current_display->ycenter, 0));
current_display->set_mask(ed);
glhr::current_vertices = NULL;
@ -357,7 +356,7 @@ void coords_to_poly() {
}
void addpoly(const transmatrix& V, const vector<glvertex> &tab, int ofs, int cnt) {
if(pmodel == mdFlatten) {
if(pmodel == mdPixel) {
for(int i=ofs; i<ofs+cnt; i++) {
hyperpoint h = glhr::gltopoint(tab[i]);
h[3] = 1;
@ -475,68 +474,6 @@ void drawTexturedTriangle(SDL_Surface *s, int *px, int *py, glvertex *tv, color_
#if CAP_GL
EX void glapplymatrix(const transmatrix& V) {
GLfloat mat[16];
int id = 0;
if(prod && pmodel == mdPerspective) {
for(int y=0; y<3; y++) {
for(int x=0; x<3; x++) mat[id++] = V[x][y];
mat[id++] = 0;
}
mat[12] = 0;
mat[13] = 0;
mat[14] = 0;
mat[15] = 1;
glhr::set_modelview(glhr::as_glmatrix(mat));
return;
}
if(in_perspective() && MDIM == 4) {
if(spherephase & 4) {
for(int y=0; y<4; y++) {
for(int x=0; x<4; x++) mat[id++] = -V[x][y];
}
}
else {
for(int y=0; y<4; y++) {
for(int x=0; x<4; x++) mat[id++] = V[x][y];
}
}
glhr::set_modelview(glhr::as_glmatrix(mat));
return;
}
if(MDIM == 4) {
for(int y=0; y<4; y++)
for(int x=0; x<4; x++) mat[id++] = V[x][y];
}
else {
for(int y=0; y<3; y++) {
for(int x=0; x<3; x++) mat[id++] = V[x][y];
mat[id++] = 0;
}
mat[12] = 0;
mat[13] = 0;
if(glhr::current_shader_projection != glhr::shader_projection::band)
mat[14] = GLfloat(vid.alpha);
else
mat[14] = 0;
mat[15] = 1;
}
if(vid.stretch != 1) mat[1] *= vid.stretch, mat[5] *= vid.stretch, mat[9] *= vid.stretch, mat[13] *= vid.stretch;
if(models::model_has_orientation()) {
if(GDIM == 3) for(int a=0; a<4; a++)
models::apply_orientation_yz(mat[a*4+1], mat[a*4+2]);
for(int a=0; a<4; a++)
models::apply_orientation(mat[a*4], mat[a*4+1]);
}
glhr::set_modelview(glhr::as_glmatrix(mat));
}
EX int global_projection;
int min_slr, max_slr = 0;
@ -593,8 +530,10 @@ void dqi_poly::gldraw() {
current_display->set_all(ed);
bool draw = color;
if(shaderside_projection) {
if(glhr::current_shader_projection == glhr::shader_projection::band && V[2][2] > 1e8) continue;
flagtype sp = get_shader_flags();
if(sp & SF_DIRECT) {
if((sp & SF_BAND) && V[2][2] > 1e8) continue;
glapplymatrix(V);
}
@ -627,18 +566,17 @@ void dqi_poly::gldraw() {
glStencilFunc( GL_NOTEQUAL, 1, 1);
GLfloat xx = vid.xres;
GLfloat yy = vid.yres;
GLfloat dist = shaderside_projection ? current_display->scrdist : 0;
vector<glvertex> scr = {
glhr::makevertex(-xx, -yy, dist),
glhr::makevertex(+xx, -yy, dist),
glhr::makevertex(+xx, +yy, dist),
glhr::makevertex(-xx, +yy, dist)
glhr::makevertex(-xx, -yy, 0),
glhr::makevertex(+xx, -yy, 0),
glhr::makevertex(+xx, +yy, 0),
glhr::makevertex(-xx, +yy, 0)
};
glhr::vertices(scr);
glhr::id_modelview();
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4);
glhr::vertices(v);
if(shaderside_projection) glapplymatrix(V);
if(sp & SF_DIRECT) glapplymatrix(V);
}
else {
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
@ -681,7 +619,7 @@ EX ld linewidthat(const hyperpoint& h) {
if(!(vid.antialias & AA_LINEWIDTH)) return 1;
else if(hyperbolic && pmodel == mdDisk && vid.alpha == 1 && !ISWEB) {
double dz = h[LDIM];
if(dz < 1 || abs(dz-current_display->scrdist) < 1e-6) return 1;
if(dz < 1) return 1;
else {
double dx = sqrt(dz * dz - 1);
double dfc = dx/(dz+1);
@ -898,7 +836,7 @@ void compute_side_by_area() {
}
ld get_width(dqi_poly* p) {
if((p->flags & POLY_FORCEWIDE) || pmodel == mdUnchanged)
if((p->flags & POLY_FORCEWIDE) || pmodel == mdPixel)
return p->linewidth;
else if(p->flags & POLY_PRECISE_WIDE) {
ld maxwidth = 0;
@ -1241,7 +1179,7 @@ EX }
void dqi_poly::draw() {
if(flags & POLY_DEBUG) debug_this();
if(in_s2xe() && vid.usingGL && pmodel == mdPerspective && (current_display->set_all(global_projection), shaderside_projection)) {
if(in_s2xe() && vid.usingGL && pmodel == mdPerspective && (current_display->set_all(global_projection), (get_shader_flags() & SF_DIRECT))) {
s2xe::draw_s2xe(this);
return;
}
@ -1331,7 +1269,7 @@ void dqi_poly::draw() {
if(cpha == 1) pha = 0;
}
}
dynamicval<eModel> d1(pmodel, mdUnchanged);
dynamicval<eModel> d1(pmodel, mdPixel);
dynamicval<transmatrix> d2(V, Id);
dynamicval<int> d3(offset, 0);
dynamicval<decltype(tab)> d4(tab, tab);
@ -1351,7 +1289,7 @@ void dqi_poly::draw() {
} */
#if CAP_GL
if(vid.usingGL && (current_display->set_all(global_projection), shaderside_projection)) {
if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT)) {
if(sl2 && pmodel == mdGeodesic) {
ld z = atan2(V[2][3], V[3][3]);
auto zr = sightranges[geometry];
@ -1472,7 +1410,7 @@ void dqi_poly::draw() {
ld h = atan2(glcoords[0][0], glcoords[0][1]);
for(int i=0; i<=360; i++) {
ld a = i * degree + h;
glcoords.push_back(glhr::makevertex(current_display->radius * sin(a), current_display->radius * vid.stretch * cos(a), current_display->scrdist));
glcoords.push_back(glhr::makevertex(current_display->radius * sin(a), current_display->radius * vid.stretch * cos(a), 0));
}
poly_flags ^= POLY_INVERSE;
}
@ -1567,7 +1505,7 @@ EX void prettypoint(const hyperpoint& h) {
}
EX void prettylinesub(const hyperpoint& h1, const hyperpoint& h2, int lev) {
if(lev >= 0 && pmodel != mdFlatten) {
if(lev >= 0 && pmodel != mdPixel) {
hyperpoint h3 = midz(h1, h2);
prettylinesub(h1, h3, lev-1);
prettylinesub(h3, h2, lev-1);

View File

@ -1003,7 +1003,6 @@ void geometry_information::make_floor_textures_here() {
// gradient vertices
vector<glhr::colored_vertex> gv;
current_display->scrdist = 0;
gv.emplace_back(-1, -1, 0, 0, 0);
gv.emplace_back(+1, -1, 0, 0, 0);
gv.emplace_back(+1, +1, 1, 1, 1);
@ -1011,13 +1010,16 @@ void geometry_information::make_floor_textures_here() {
gv.emplace_back(+1, +1, 1, 1, 1);
gv.emplace_back(-1, +1, 1, 1, 1);
glhr::switch_mode(glhr::gmVarColored, glhr::shader_projection::standard);
current_display->set_all(0);
glhr::new_projection();
glhr::id_modelview();
glhr::prepare(gv);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLES, 0, isize(gv));
if(1) {
current_display->next_shader_flags = GF_VARCOLOR;
dynamicval<eModel> m(pmodel, mdPixel);
current_display->set_all(0);
glhr::new_projection();
glhr::id_modelview();
glhr::prepare(gv);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLES, 0, isize(gv));
}
shOverFloor.pstrength = 20;
shFeatherFloor.pstrength = 40;

821
glhr.cpp Normal file
View File

@ -0,0 +1,821 @@
// Hyperbolic Rogue -- low-level OpenGL routines
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
/** \file glhr.cpp
* \brief low-level OpenGL routines
*
* If CAP_SHADER is 0, OpenGL 1.0 is used.
* If CAP_SHADER is 1, we are using GLSL shaders.
*/
#include "hyper.h"
namespace hr {
#ifndef DEBUG_GL
#define DEBUG_GL 0
#endif
// Copyright (C) 2011-2018 Zeno Rogue, see 'hyper.cpp' for details
EX void glError(const char* GLcall, const char* file, const int line) {
GLenum errCode = glGetError();
if(errCode!=GL_NO_ERROR) {
fprintf(stderr, "OPENGL ERROR #%i: in file %s on line %i :: %s\n",errCode,file, line, GLcall);
}
}
#ifndef CAP_VERTEXBUFFER
#define CAP_VERTEXBUFFER (ISWEB)
#endif
#if HDR
#if CAP_SHADER && CAP_NOSHADER
#define WITHSHADER(x, y) if(glhr::noshaders) y else x
#else
#if CAP_NOSHADER
#define WITHSHADER(x, y) if(1) y
#else
#define WITHSHADER(x, y) if(1) x
#endif
#endif
#endif
EX namespace glhr {
#if HDR
struct glmatrix {
GLfloat a[4][4];
GLfloat* operator[] (int i) { return a[i]; }
const GLfloat* operator[] (int i) const { return a[i]; }
GLfloat* as_array() { return a[0]; }
const GLfloat* as_array() const { return a[0]; }
array<float, 16>& as_stdarray() { return *(array<float, 16>*)this; }
};
glvertex pointtogl(const hyperpoint& t);
inline glvertex makevertex(GLfloat x, GLfloat y, GLfloat z) {
#if SHDIM == 3
return make_array(x, y, z);
#else
return make_array<GLfloat>(x, y, z, 1);
#endif
}
struct colored_vertex {
glvertex coords;
glvec4 color;
colored_vertex(GLfloat x, GLfloat y, GLfloat r, GLfloat g, GLfloat b) {
coords[0] = x;
coords[1] = y;
coords[2] = 0;
coords[3] = 1;
color[0] = r;
color[1] = g;
color[2] = b;
color[3] = 1;
}
colored_vertex(hyperpoint h, color_t col) {
coords = pointtogl(h);
for(int i=0; i<4; i++)
color[i] = part(col, 3-i) / 255.0;
}
};
struct textured_vertex {
glvertex coords;
glvec2 texture;
};
struct ct_vertex {
glvertex coords;
glvec4 color;
glvec2 texture;
ct_vertex(const hyperpoint& h, ld x1, ld y1, ld col) {
coords = pointtogl(h);
texture[0] = x1;
texture[1] = y1;
color[0] = color[1] = color[2] = col;
color[3] = 1;
}
};
#endif
#if CAP_SHADER
EX bool noshaders = false;
#else
EX bool noshaders = true;
#endif
bool glew = false;
bool current_depthtest, current_depthwrite;
ld fogbase;
#if HDR
typedef const void *constvoidptr;
#endif
EX constvoidptr current_vertices, buffered_vertices;
ld current_linewidth;
GLuint buf_current, buf_buffered;
void display(const glmatrix& m) {
for(int i=0; i<4; i++) {
for(int j=0; j<4; j++)
printf("%10.5f", m[i][j]);
printf("\n");
}
printf("\n");
}
glmatrix operator * (glmatrix m1, glmatrix m2) {
glmatrix res;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++) {
res[i][j] = 0;
for(int k=0; k<4; k++)
res[i][j] += m1[i][k] * m2[k][j];
}
return res;
}
EX glmatrix id = {{{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}}};
EX glmatrix scale(ld x, ld y, ld z) {
glmatrix tmp;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp[i][j] = (i==j);
tmp[0][0] = x;
tmp[1][1] = y;
tmp[2][2] = z;
return tmp;
}
EX glmatrix tmtogl(const transmatrix& T) {
glmatrix tmp;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp[i][j] = T[i][j];
return tmp;
}
EX glmatrix tmtogl_transpose(const transmatrix& T) {
glmatrix tmp;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp[i][j] = T[j][i];
return tmp;
}
EX glmatrix ortho(ld x, ld y, ld z) {
return scale(1/x, 1/y, 1/z);
}
EX glmatrix& as_glmatrix(GLfloat o[16]) {
glmatrix& tmp = (glmatrix&) (o[0]);
return tmp;
}
EX glmatrix frustum(ld x, ld y, ld vnear IS(1e-3), ld vfar IS(1e9)) {
GLfloat frustum[16] = {
GLfloat(1 / x), 0, 0, 0,
0, GLfloat(1 / y), 0, 0,
0, 0, GLfloat(-(vnear+vfar)/(vfar-vnear)), -1,
0, 0, GLfloat(-2*vnear*vfar/(vfar-vnear)), 0};
return as_glmatrix(frustum);
}
EX glmatrix translate(ld x, ld y, ld z) {
glmatrix tmp;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
tmp[i][j] = (i==j);
tmp[3][0] = x;
tmp[3][1] = y;
tmp[3][2] = z;
return tmp;
}
// ** legacy **
// /* shaders */
glmatrix projection;
EX void new_projection() {
WITHSHADER({
projection = id;
}, {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
return;
})
}
EX void projection_multiply(const glmatrix& m) {
WITHSHADER({
projection = m * projection;
}, {
glMatrixMode(GL_PROJECTION);
glMultMatrixf(m.as_array());
})
}
EX void init();
// https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/attributes.php
#if HDR
struct GLprogram : std::enable_shared_from_this<GLprogram> {
GLuint _program;
GLuint vertShader, fragShader;
GLint uFog, uFogColor, uColor, tTexture, tInvExpTable, uMV, uProjection, uAlpha, uFogBase, uPP;
GLint uPRECX, uPRECY, uPRECZ, uIndexSL, uIterations;
bool uses_mvp;
flagtype shader_flags;
string _vsh, _fsh;
GLprogram(string vsh, string fsh);
~GLprogram();
};
#endif
EX shared_ptr<GLprogram> current_glprogram = nullptr;
EX int compileShader(int type, const string& s) {
GLint status;
#if DEBUG_GL
printf("===\n%s\n===\n", s.c_str());
#endif
GLint shader = glCreateShader(type);
const char *ss = s.c_str();
glShaderSource(shader, 1, &ss, NULL);
glCompileShader(shader);
GLint logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
std::vector<char> log(logLength);
glGetShaderInfoLog(shader, logLength, &logLength, log.data());
if(logLength > 0)
printf("compiler log (%d): '%s'\n", logLength, log.data());
}
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == 0) {
glDeleteShader(shader);
printf("failed to compile shader\n");
println(hlog, s);
shader = 0;
}
return shader;
}
GLprogram::GLprogram(string vsh, string fsh) {
if(noshaders) {
uFog = -1;
uProjection = -1;
uPP = -1;
uMV = -1;
uPRECX = -1;
uIterations = -1;
uAlpha = -1;
return;
}
_vsh = vsh; _fsh = fsh;
_program = glCreateProgram();
add_fixed_functions(vsh);
add_fixed_functions(fsh);
// printf("creating program %d\n", _program);
vertShader = compileShader(GL_VERTEX_SHADER, vsh.c_str());
fragShader = compileShader(GL_FRAGMENT_SHADER, fsh.c_str());
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
glBindAttribLocation(_program, aPosition, "aPosition");
glBindAttribLocation(_program, aTexture, "aTexture");
glBindAttribLocation(_program, aColor, "aColor");
GLint status;
glLinkProgram(_program);
GLint logLength;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
std::vector<char> log(logLength);
glGetProgramInfoLog(_program, logLength, &logLength, log.data());
if(logLength > 0)
printf("linking log (%d): %s\n", logLength, log.data());
}
glGetProgramiv(_program, GL_LINK_STATUS, &status);
if (status == 0) {
printf("failed to link shader\n");
exit(1);
}
// glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); ??
// glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); ??
uMV = glGetUniformLocation(_program, "uMV");
uProjection = glGetUniformLocation(_program, "uP");
uPP = glGetUniformLocation(_program, "uPP");
uFog = glGetUniformLocation(_program, "uFog");
uFogColor = glGetUniformLocation(_program, "uFogColor");
uFogBase = glGetUniformLocation(_program, "uFogBase");
uAlpha = glGetUniformLocation(_program, "uAlpha");
uColor = glGetUniformLocation(_program, "uColor");
tTexture = glGetUniformLocation(_program, "tTexture");
tInvExpTable = glGetUniformLocation(_program, "tInvExpTable");
uPRECX = glGetUniformLocation(_program, "PRECX");
uPRECY = glGetUniformLocation(_program, "PRECY");
uPRECZ = glGetUniformLocation(_program, "PRECZ");
uIndexSL = glGetUniformLocation(_program, "uIndexSL");
uIterations = glGetUniformLocation(_program, "uIterations");
}
GLprogram::~GLprogram() {
glDeleteProgram(_program);
if(vertShader) glDeleteShader(vertShader), vertShader = 0;
if(fragShader) glDeleteShader(fragShader), fragShader = 0;
}
EX void set_index_sl(ld x) {
glUniform1f(glhr::current_glprogram->uIndexSL, x);
}
EX void set_sl_iterations(int steps) {
glUniform1i(glhr::current_glprogram->uIterations, steps);
}
EX void set_solv_prec(int x, int y, int z) {
glUniform1i(glhr::current_glprogram->tInvExpTable, INVERSE_EXP_BINDING);
glUniform1f(glhr::current_glprogram->uPRECX, x);
glUniform1f(glhr::current_glprogram->uPRECY, y);
glUniform1f(glhr::current_glprogram->uPRECZ, z);
}
EX glmatrix current_matrix, current_modelview, current_projection;
bool operator == (const glmatrix& m1, const glmatrix& m2) {
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
if(m1[i][j] != m2[i][j]) return false;
return true;
}
bool operator != (const glmatrix& m1, const glmatrix& m2) {
return !(m1 == m2);
}
EX glmatrix eyeshift;
EX bool using_eyeshift;
EX void set_modelview(const glmatrix& modelview) {
#if CAP_NOSHADER
if(noshaders) {
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(modelview.as_array());
return;
}
#endif
auto& cur = current_glprogram;
if(!cur) return;
if(using_eyeshift) {
glmatrix mvp = modelview * eyeshift;
#if MINIMIZE_GL_CALLS
if(mvp == current_matrix) return;
current_matrix = mvp;
#endif
glUniformMatrix4fv(cur->uMV, 1, 0, mvp.as_array());
}
else if(modelview != current_modelview) {
current_modelview = modelview;
glUniformMatrix4fv(cur->uMV, 1, 0, modelview.as_array());
}
if(projection != current_projection) {
current_projection = projection;
glUniformMatrix4fv(cur->uProjection, 1, 0, projection.as_array());
}
}
EX void id_modelview() {
#if CAP_NOSHADER
if(noshaders) {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return;
}
#endif
set_modelview(id);
}
EX array<GLfloat, 4> acolor(color_t color, ld scale IS(1)) {
array<GLfloat, 4> cols;
for(int i=0; i<4; i++)
cols[i] = part(color, 3-i) / 255.0 * scale;
return cols;
}
EX void color2(color_t color, ld scale IS(1)) {
auto cols = acolor(color, scale);
WITHSHADER({
if(!current_glprogram) return;
glUniform4f(current_glprogram->uColor, cols[0], cols[1], cols[2], cols[3]);
}, {
glColor4f(cols[0], cols[1], cols[2], cols[3]);
}
)
}
EX void colorClear(color_t color) {
glClearColor(part(color, 3) / 255.0, part(color, 2) / 255.0, part(color, 1) / 255.0, part(color, 0) / 255.0);
}
EX void full_enable(GLprogram *p) {
auto& cur = current_glprogram;
flagtype oldflags = cur ? cur->shader_flags : 0;
if(p == &*cur) return;
cur = p->shared_from_this();
GLERR("pre_switch_mode");
WITHSHADER({
glUseProgram(cur->_program);
GLERR("after_enable");
}, {
});
reset_projection();
flagtype newflags = cur->shader_flags;
tie(oldflags, newflags) = make_pair(oldflags & ~newflags, newflags & ~oldflags);
if(newflags & GF_TEXTURE) {
GLERR("xsm");
WITHSHADER({
glEnableVertexAttribArray(aTexture);
GLERR("xsm");
}, {
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLERR("xsm");
})
}
if(oldflags & GF_TEXTURE) {
GLERR("xsm");
WITHSHADER({
glDisableVertexAttribArray(aTexture);
GLERR("xsm");
}, {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
GLERR("xsm");
})
}
if(newflags & GF_VARCOLOR) {
WITHSHADER({
GLERR("xsm");
glEnableVertexAttribArray(aColor);
}, {
GLERR("xsm");
glEnableClientState(GL_COLOR_ARRAY);
GLERR("xsm");
})
}
if(oldflags & GF_VARCOLOR) {
WITHSHADER({
glDisableVertexAttribArray(aColor);
GLERR("xsm");
}, {
glDisableClientState(GL_COLOR_ARRAY);
GLERR("xsm");
})
}
if(newflags & GF_LIGHTFOG) {
#ifdef GLES_ONLY
#define glFogi glFogx
#endif
WITHSHADER({}, {
/*GLfloat light_ambient[] = { 3.5, 3.5, 3.5, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
GLERR("lighting");
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); */
glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0);
})
}
if(oldflags & GF_LIGHTFOG) {
WITHSHADER({}, {glDisable(GL_FOG);})
}
WITHSHADER({
glUniform1f(cur->uFogBase, 1); fogbase = 1;
}, {})
GLERR("after_switch_mode");
current_vertices = NULL;
WITHSHADER({
current_matrix[0][0] = -1e8; // invalid
current_modelview[0][0] = -1e8;
current_projection[0][0] = -1e8;
}, {})
id_modelview();
current_linewidth = -1;
/* if(current_depthwrite) glDepthMask(GL_TRUE);
else glDepthMask(GL_FALSE);
if(current_depthtest) glEnable(GL_DEPTH_TEST);
else glDisable(GL_DEPTH_TEST); */
}
EX void fog_max(ld fogmax, color_t fogcolor) {
WITHSHADER({
glUniform1f(current_glprogram->uFog, 1 / fogmax);
GLfloat cols[4];
for(int i=0; i<4; i++) cols[i] = part(fogcolor, 3-i) / 255.0;
glUniform4f(current_glprogram->uFogColor, cols[0], cols[1], cols[2], cols[3]);
}, {
glFogf(GL_FOG_END, fogmax);
})
}
EX void set_fogbase(ld _fogbase) {
WITHSHADER({
if(fogbase != _fogbase) {
fogbase = _fogbase;
glUniform1f(current_glprogram->uFogBase, fogbase);
}
}, {})
}
EX void set_ualpha(ld alpha) {
WITHSHADER({
glUniform1f(current_glprogram->uAlpha, alpha);
}, {})
}
void init() {
#if CAP_GLEW
if(!glew) {
glew = true;
printf("Initializing GLEW\n");
GLenum err = glewInit();
if (GLEW_OK != err) {
addMessage("Failed to initialize GLEW");
printf("Failed to initialize GLEW\n");
return;
}
printf("CreateProgram = %p\n", __glewCreateProgram);
if(!__glewCreateProgram) noshaders = true;
}
#endif
projection = id;
WITHSHADER(glEnableVertexAttribArray(aPosition);, glEnableClientState(GL_VERTEX_ARRAY);)
// #endif
#if CAP_VERTEXBUFFER
glGenBuffers(1, &buf_current);
glGenBuffers(1, &buf_buffered);
current_vertices = NULL;
buffered_vertices = (void*) &buffered_vertices; // point to nothing
glBindBuffer(GL_ARRAY_BUFFER, buf_current);
#endif
}
EX hyperpoint gltopoint(const glvertex& t) {
hyperpoint h;
h[0] = t[0]; h[1] = t[1]; h[2] = t[2];
if(SHDIM == 4 && MAXMDIM == 4) h[3] = t[3];
return h;
}
EX glvertex pointtogl(const hyperpoint& t) {
glvertex h;
h[0] = t[0]; h[1] = t[1]; h[2] = t[2];
if(SHDIM == 4) h[3] = (MDIM == 4) ? t[3] : 1;
return h;
}
#if CAP_VERTEXBUFFER
template<class T> void bindbuffer(T& v) {
if(current_vertices == buffered_vertices || current_vertices == nullptr) {
glBindBuffer(GL_ARRAY_BUFFER, buf_current);
}
current_vertices = &v[0];
glBufferData(GL_ARRAY_BUFFER, isize(v) * sizeof(v[0]), &v[0], GL_DYNAMIC_DRAW);
}
#define PTR(attrib, q, field) \
glVertexAttribPointer(attrib, q, GL_FLOAT, GL_FALSE, sizeof(v[0]), (void*) ((char*) &v[0].field - (char*) &v[0]));
#endif
EX void vertices(const vector<glvertex>& v, int vshift IS(0)) {
#if CAP_VERTEXBUFFER
if(&v[0] == buffered_vertices) {
if(&v[0] == current_vertices) return;
current_vertices = buffered_vertices;
glBindBuffer(GL_ARRAY_BUFFER, buf_buffered);
glVertexAttribPointer(glhr::aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
return;
}
bindbuffer(v);
glVertexAttribPointer(glhr::aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
#else
if(current_vertices == &v[vshift]) return;
current_vertices = &v[vshift];
WITHSHADER(
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &v[vshift]);,
glVertexPointer(SHDIM, GL_FLOAT, sizeof(glvertex), &v[0]);
)
#endif
}
EX void vertices_texture(const vector<glvertex>& v, const vector<glvertex>& t, int vshift IS(0), int tshift IS(0)) {
#if CAP_VERTEXBUFFER
int q = min(isize(v)-vshift, isize(t)-tshift);
vector<textured_vertex> tv(q);
for(int i=0; i<q; i++)
tv[i].coords = v[vshift+i],
tv[i].texture[0] = t[tshift+i][0],
tv[i].texture[1] = t[tshift+i][1];
prepare(tv);
#else
vertices(v, vshift);
WITHSHADER(
glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), &t[tshift]);,
glTexCoordPointer(SHDIM, GL_FLOAT, 0, &t[tshift]);
)
#endif
}
EX void prepare(vector<colored_vertex>& v) {
#if CAP_VERTEXBUFFER
bindbuffer(v);
PTR(glhr::aPosition, SHDIM, coords);
PTR(glhr::aColor, 4, color);
#else
if(current_vertices == &v[0]) return;
current_vertices = &v[0];
WITHSHADER({
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(colored_vertex), &v[0].coords);
glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, sizeof(colored_vertex), &v[0].color);
}, {
glVertexPointer(SHDIM, GL_FLOAT, sizeof(colored_vertex), &v[0].coords);
glColorPointer(4, GL_FLOAT, sizeof(colored_vertex), &v[0].color);
})
#endif
}
EX void prepare(vector<textured_vertex>& v) {
#if CAP_VERTEXBUFFER
bindbuffer(v);
PTR(glhr::aPosition, SHDIM, coords);
PTR(glhr::aTexture, 2, texture);
#else
if(current_vertices == &v[0]) return;
current_vertices = &v[0];
WITHSHADER({
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(textured_vertex), &v[0].coords);
glVertexAttribPointer(aTexture, SHDIM, GL_FLOAT, GL_FALSE, sizeof(textured_vertex), &v[0].texture);
}, {
glVertexPointer(SHDIM, GL_FLOAT, sizeof(textured_vertex), &v[0].coords);
glTexCoordPointer(2, GL_FLOAT, sizeof(textured_vertex), &v[0].texture);
})
#endif
// color2(col);
}
EX void prepare(vector<ct_vertex>& v) {
#if CAP_VERTEXBUFFER
bindbuffer(v);
PTR(glhr::aPosition, SHDIM, coords);
PTR(glhr::aColor, 4, color);
PTR(glhr::aTexture, 2, texture);
#else
if(current_vertices == &v[0]) return;
current_vertices = &v[0];
WITHSHADER({
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].coords);
glVertexAttribPointer(aColor, 4, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].color);
glVertexAttribPointer(aTexture, 2, GL_FLOAT, GL_FALSE, sizeof(ct_vertex), &v[0].texture);
}, {
glVertexPointer(SHDIM, GL_FLOAT, sizeof(ct_vertex), &v[0].coords);
glTexCoordPointer(2, GL_FLOAT, sizeof(ct_vertex), &v[0].texture);
glColorPointer(4, GL_FLOAT, sizeof(ct_vertex), &v[0].color);
})
#endif
}
EX void store_in_buffer(vector<glvertex>& v) {
#if CAP_VERTEXBUFFER
if(!buf_buffered) {
printf("no buffer yet\n");
return;
}
printf("storing %d in buffer: %p\n", isize(v), &v[0]);
current_vertices = buffered_vertices = &v[0];
glBindBuffer(GL_ARRAY_BUFFER, buf_buffered);
glVertexAttribPointer(glhr::aPosition, SHDIM, GL_FLOAT, GL_FALSE, sizeof(glvertex), 0);
glBufferData(GL_ARRAY_BUFFER, isize(v) * sizeof(glvertex), &v[0], GL_STATIC_DRAW);
printf("Stored.\n");
#endif
}
EX void set_depthtest(bool b) {
if(b != current_depthtest) {
current_depthtest = b;
if(b) glEnable(GL_DEPTH_TEST);
else glDisable(GL_DEPTH_TEST);
}
}
EX void set_depthwrite(bool b) {
if(b != current_depthwrite) { // <- this does not work ask intended for some reason...
current_depthwrite = b;
if(b) glDepthMask(GL_TRUE);
else glDepthMask(GL_FALSE);
}
}
EX void set_linewidth(ld lw) {
if(lw != current_linewidth) {
current_linewidth = lw;
glLineWidth(lw);
}
}
EX void switch_to_text(const vector<glvertex>& v, const vector<glvertex>& t) {
current_display->next_shader_flags = GF_TEXTURE;
dynamicval<eModel> pm(pmodel, mdPixel);
if(!svg::in) current_display->set_all(0);
vertices_texture(v, t, 0, 0);
}
EX void be_nontextured() { current_display->next_shader_flags = 0; }
EX void be_textured() { current_display->next_shader_flags = GF_TEXTURE; }
EX }
EX vector<glhr::textured_vertex> text_vertices;
EX void texture_vertices(GLfloat *f, int qty, int stride IS(2)) {
WITHSHADER(
glVertexAttribPointer(aTexture, stride, GL_FLOAT, GL_FALSE, stride * sizeof(GLfloat), f);,
glTexCoordPointer(stride, GL_FLOAT, 0, f);
)
}
EX void oldvertices(GLfloat *f, int qty) {
WITHSHADER(
glVertexAttribPointer(aPosition, SHDIM, GL_FLOAT, GL_FALSE, SHDIM * sizeof(GLfloat), f);,
glVertexPointer(SHDIM, GL_FLOAT, 0, f);
)
}
}
#define glMatrixMode DISABLED
#define glLoadIdentity DISABLED
#define glMultMatrixf DISABLED
#define glScalef DISABLED
#define glTranslatef DISABLED
#define glPushMatrix DISABLED
#define glPopMatrix DISABLED

View File

@ -3076,9 +3076,9 @@ void drawaura() {
}
}
glflush();
dynamicval<eModel> p(pmodel, GDIM == 2 && pmodel == mdDisk ? mdDisk : mdUnchanged);
current_display->next_shader_flags = GF_VARCOLOR;
dynamicval<eModel> m(pmodel, mdPixel);
current_display->set_all(0);
glhr::switch_mode(glhr::gmVarColored, glhr::shader_projection::standard);
glhr::id_modelview();
glhr::prepare(auravertices);
glhr::set_depthtest(false);
@ -4898,7 +4898,7 @@ void dqi_sky::draw() {
for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
if(global_projection && global_projection != ed) continue;
glhr::switch_mode(glhr::gmVarColored, glhr::new_shader_projection);
current_display->next_shader_flags = GF_VARCOLOR;
current_display->set_all(ed);
if(global_projection)
glhr::projection_multiply(glhr::tmtogl(xpush(-vid.ipd * global_projection/2)));
@ -7641,11 +7641,6 @@ EX void calcparam() {
cd->tanfov = tan(vid.fov * degree / 2);
if(pmodel)
cd->scrdist = vid.xres / 2 / cd->tanfov;
else
cd->scrdist = cd->radius;
callhooks(hooks_calcparam);
reset_projection();
}

View File

@ -389,7 +389,7 @@ EX void draw_radar(bool cornermode) {
bool scompass = nonisotropic && !hybri;
dynamicval<eGeometry> g(geometry, gEuclid);
dynamicval<eModel> pm(pmodel, mdUnchanged);
dynamicval<eModel> pm(pmodel, mdDisk);
dynamicval<bool> ga(vid.always3, false);
dynamicval<geometryinfo1> gi(ginf[gEuclid].g, giEuclid2);
initquickqueue();

View File

@ -23,6 +23,7 @@
#include "hyper.h"
#include "classes.cpp"
#include "glhr.cpp"
#include "shaders.cpp"
#include "hprint.cpp"
#include "util.cpp"

View File

@ -36,7 +36,7 @@ EX bool non_spatial_model() {
return true;
if(pmodel == mdSpiral && euclid)
return true;
return vid.consider_shader_projection && shaderside_projection && pmodel;
return pmodel && vid.consider_shader_projection && (get_shader_flags() & SF_DIRECT);
}
hyperpoint perspective_to_space(hyperpoint h, ld alpha, eGeometryClass gc) {
@ -120,7 +120,7 @@ void apply_depth(hyperpoint &f, ld z) {
f[2] = z;
else {
z = z * current_display->radius;
ld mul = current_display->scrdist / (current_display->scrdist + z);
ld mul = current_display->radius / (current_display->radius + z);
f[0] = f[0] * mul;
f[1] = f[1] * mul;
f[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius + vid.ipd * mul / 2;
@ -336,8 +336,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
return;
}
case mdUnchanged:
case mdFlatten:
case mdPixel:
ret = H / current_display->radius;
return;
@ -836,7 +835,7 @@ EX void applymodel(hyperpoint H, hyperpoint& ret) {
}
}
case mdGUARD: case mdRug: break;
case mdGUARD: case mdManual: break;
}
ghcheck(ret,H_orig);
@ -1526,7 +1525,7 @@ void addball(ld a, ld b, ld c) {
}
void ballgeometry() {
queuereset(vid.usingGL ? mdDisk : mdUnchanged, PPR::CIRCLE);
queuereset(mdPixel, PPR::CIRCLE);
for(int i=0; i<60; i++)
addball(i * M_PI/30, 10, 0);
for(double d=10; d>=-10; d-=.2)
@ -1586,12 +1585,17 @@ transmatrix screenpos(ld x, ld y) {
return V;
}
EX eModel flat_model() { return MDIM == 4 ? mdFlatten : mdDisk; }
/**
In 3D, we use the standard translation matrices to place stuff on the screen.
In 2D, this does not work (as HyperRogue reduces matrices to 3x3) so we use the native disk projection
*/
EX eModel flat_model() { return MDIM == 4 ? mdPixel : mdDisk; }
EX transmatrix atscreenpos(ld x, ld y, ld size) {
transmatrix V = Id;
if(pmodel == mdFlatten) {
if(pmodel == mdPixel) {
V[0][3] += (x - current_display->xcenter);
V[1][3] += (y - current_display->ycenter);
V[0][0] = size * 2 * cgi.hcrossf / cgi.crossf;
@ -1603,7 +1607,7 @@ EX transmatrix atscreenpos(ld x, ld y, ld size) {
V[1][2] += (y - current_display->ycenter);
V[0][0] = size * 2 * cgi.hcrossf / cgi.crossf;
V[1][1] = size * 2 * cgi.hcrossf / cgi.crossf;
V[2][2] = current_display->scrdist;
V[2][2] = current_display->radius;
if(S3 == OINF) V[0][0] /= 5, V[1][1] /= 5;
}
@ -1647,7 +1651,7 @@ EX void draw_model_elements() {
}
case mdTwoHybrid: {
queuereset(mdUnchanged, PPR::CIRCLE);
queuereset(mdPixel, PPR::CIRCLE);
for(int mode=0; mode<4; mode++) {
for(int s=-200; s<=200; s ++) {
@ -1747,7 +1751,7 @@ void queuestraight(hyperpoint X, int style, color_t lc, color_t fc, PPR p) {
ld mul1 = hypot(vid.xres, vid.yres) / hypot_d(2, H1);
queuereset(mdUnchanged, p);
queuereset(mdPixel, p);
curvepoint(H0 + spin(M_PI/2) * H0 * mul0);
curvepoint(H0 - spin(M_PI/2) * H0 * mul0);
curvepoint(H1 + spin(M_PI/2) * H1 * mul1);
@ -1794,7 +1798,7 @@ EX void draw_boundary(int w) {
case mdTwoPoint: {
if(twopoint_do_flips || current_display->stereo_active() || !sphere) return;
queuereset(vid.usingGL ? mdDisk : mdUnchanged, p);
queuereset(mdPixel, p);
for(int b=-1; b<=1; b+=2)
for(ld a=-90; a<=90+1e-6; a+=pow(.5, vid.linequality)) {
@ -1851,7 +1855,7 @@ EX void draw_boundary(int w) {
case mdHemisphere: {
if(hyperbolic) {
queuereset(mdUnchanged, p);
queuereset(mdPixel, p);
for(int i=0; i<=360; i++) {
ld s = sin(i * degree);
curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * (models::cos_ball * s >= 0 - 1e-6 ? 1 : abs(models::sin_ball)), 0));
@ -1859,7 +1863,7 @@ EX void draw_boundary(int w) {
queuecurve(lc, fc, p);
queuereset(pmodel, p);
p = PPR::CIRCLE; fc = 0;
queuereset(mdUnchanged, p);
queuereset(mdPixel, p);
for(int i=0; i<=360; i++) {
ld s = sin(i * degree);
@ -1869,7 +1873,7 @@ EX void draw_boundary(int w) {
queuereset(pmodel, p);
}
if(euclid || sphere) {
queuereset(mdUnchanged, p);
queuereset(mdPixel, p);
for(int i=0; i<=360; i++) {
curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * sin(i * degree), 0));
}
@ -1938,7 +1942,7 @@ EX void draw_boundary(int w) {
auto& sm = models::spiral_multiplier;
ld u = hypot(1, imag(sm) / real(sm));
if(real(sm)) {
queuereset(mdUnchanged, p);
queuereset(mdPixel, p);
for(ld a=-10; a<=10; a+=0.01 / (1 << vid.linequality) / u) {
cld z = exp(cld(a, a * imag(sm) / real(sm) + M_PI));
hyperpoint ret = point2(real(z), imag(z));

View File

@ -281,7 +281,7 @@ EX namespace models {
#if CAP_QUEUE && CAP_CURVE
dialog::extra_options = [] () {
initquickqueue();
queuereset(mdUnchanged, PPR::LINE);
queuereset(mdPixel, PPR::LINE);
for(int a=-1; a<=1; a++) {
curvepoint(point2(-M_PI/2 * current_display->radius, a*current_display->radius));
curvepoint(point2(+M_PI/2 * current_display->radius, a*current_display->radius));
@ -632,6 +632,7 @@ EX namespace models {
dialog::add_action(edit_stretch);
dialog::addBoolItem(XLAT("use GPU to compute projections"), vid.consider_shader_projection, 'G');
bool shaderside_projection = get_shader_flags() & SF_DIRECT;
if(vid.consider_shader_projection && !shaderside_projection)
dialog::lastItem().value = XLAT("N/A");
if(vid.consider_shader_projection && shaderside_projection && pmodel)

View File

@ -1393,7 +1393,7 @@ EX void drawRugScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_BLEND);
glhr::switch_mode(glhr::gmLightFog, glhr::shader_projection::standard);
current_display->next_shader_flags = GF_LIGHTFOG | GF_TEXTURE;
glhr::set_depthtest(true);
glhr::set_depthwrite(true);
glDepthFunc(invert_depth ? GL_GREATER : GL_LESS);
@ -1405,7 +1405,7 @@ EX void drawRugScene() {
if(ed == 1 && vid.stereo_mode == sAnaglyph)
glClear(GL_DEPTH_BUFFER_BIT);
dynamicval<eModel> p(pmodel, mdRug);
dynamicval<eModel> p(pmodel, mdManual);
current_display->set_all(ed);
eyewidth_translate(ed);

File diff suppressed because it is too large Load Diff

View File

@ -669,7 +669,7 @@ void texture_config::drawRawTexture() {
rtver[i].coords[2] = 0;
rtver[i].coords[3] = 1;
}
glhr::set_modelview(glhr::translate(0, 0, current_display->scrdist));
glhr::id_modelview();
glhr::prepare(rtver);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);