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:
parent
7babf20ef4
commit
09fcd14aa7
227
basegraph.cpp
227
basegraph.cpp
@ -38,8 +38,7 @@ struct display_data {
|
|||||||
bool sidescreen;
|
bool sidescreen;
|
||||||
|
|
||||||
ld tanfov;
|
ld tanfov;
|
||||||
|
flagtype next_shader_flags;
|
||||||
GLfloat scrdist, scrdist_text;
|
|
||||||
|
|
||||||
ld eyewidth();
|
ld eyewidth();
|
||||||
bool stereo_active();
|
bool stereo_active();
|
||||||
@ -85,8 +84,6 @@ namespace stereo {
|
|||||||
ld ipd;
|
ld ipd;
|
||||||
ld lr_eyewidth, anaglyph_eyewidth;
|
ld lr_eyewidth, anaglyph_eyewidth;
|
||||||
ld fov, tanfov;
|
ld fov, tanfov;
|
||||||
|
|
||||||
GLfloat scrdist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool display_data::in_anaglyph() { return vid.stereo_mode == sAnaglyph; }
|
bool display_data::in_anaglyph() { return vid.stereo_mode == sAnaglyph; }
|
||||||
@ -226,25 +223,6 @@ void setcameraangle(bool b) { }
|
|||||||
|
|
||||||
#if CAP_GL
|
#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
|
#if CAP_VR
|
||||||
EX hookset<bool()> *hooks_vr_eye_view, *hooks_vr_eye_projection;
|
EX hookset<bool()> *hooks_vr_eye_view, *hooks_vr_eye_projection;
|
||||||
#endif
|
#endif
|
||||||
@ -257,15 +235,6 @@ EX void eyewidth_translate(int ed) {
|
|||||||
if(ed) glhr::projection_multiply(glhr::translate(-ed * current_display->eyewidth(), 0, 0));
|
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;
|
tuple<int, eModel, display_data*, int> last_projection;
|
||||||
EX bool new_projection_needed;
|
EX bool new_projection_needed;
|
||||||
#if HDR
|
#if HDR
|
||||||
@ -275,7 +244,7 @@ inline void reset_projection() { new_projection_needed = true; }
|
|||||||
void display_data::set_all(int ed) {
|
void display_data::set_all(int ed) {
|
||||||
auto t = this;
|
auto t = this;
|
||||||
auto current_projection = tie(ed, pmodel, t, current_rbuffer);
|
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;
|
last_projection = current_projection;
|
||||||
set_projection(ed);
|
set_projection(ed);
|
||||||
set_mask(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) {
|
void display_data::set_mask(int ed) {
|
||||||
if(ed == 0 || vid.stereo_mode != sAnaglyph) {
|
if(ed == 0 || vid.stereo_mode != sAnaglyph) {
|
||||||
glColorMask( GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE );
|
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();
|
glflush();
|
||||||
glhr::be_nontextured();
|
glhr::be_nontextured();
|
||||||
glhr::id_modelview();
|
glhr::id_modelview();
|
||||||
dynamicval<eModel> em(pmodel, mdUnchanged);
|
dynamicval<eModel> em(pmodel, mdPixel);
|
||||||
glcoords.clear();
|
glcoords.clear();
|
||||||
x -= current_display->xcenter; y -= current_display->ycenter;
|
x -= current_display->xcenter; y -= current_display->ycenter;
|
||||||
int pts = size * 4;
|
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;
|
if(ISMOBILE && pts > 72) pts = 72;
|
||||||
for(int r=0; r<pts; r++) {
|
for(int r=0; r<pts; r++) {
|
||||||
float rr = (M_PI * 2 * r) / pts;
|
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);
|
current_display->set_all(0);
|
||||||
glhr::vertices(glcoords);
|
glhr::vertices(glcoords);
|
||||||
|
@ -313,7 +313,7 @@ enum eModel {
|
|||||||
// 25
|
// 25
|
||||||
mdMollweide, mdCentralCyl, mdCollignon,
|
mdMollweide, mdCentralCyl, mdCollignon,
|
||||||
// 26..
|
// 26..
|
||||||
mdGUARD, mdUnchanged, mdHyperboloidFlat, mdPolynomial, mdRug, mdFlatten
|
mdGUARD, mdPixel, mdHyperboloidFlat, mdPolynomial, mdManual
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef unsigned long long flagtype;
|
typedef unsigned long long flagtype;
|
||||||
|
102
drawing.cpp
102
drawing.cpp
@ -126,7 +126,6 @@ EX int shapes_merged;
|
|||||||
color_t triangle_color, line_color;
|
color_t triangle_color, line_color;
|
||||||
vector<glvertex> triangle_vertices;
|
vector<glvertex> triangle_vertices;
|
||||||
vector<glvertex> line_vertices;
|
vector<glvertex> line_vertices;
|
||||||
EX void glapplymatrix(const transmatrix& V);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EX void glflush() {
|
EX void glflush() {
|
||||||
@ -159,14 +158,14 @@ EX void glflush() {
|
|||||||
|
|
||||||
if(isize(text_vertices)) {
|
if(isize(text_vertices)) {
|
||||||
// printf("%08X | %d texts, %d vertices\n", text_color, texts_merged, isize(text_vertices));
|
// printf("%08X | %d texts, %d vertices\n", text_color, texts_merged, isize(text_vertices));
|
||||||
glhr::be_textured();
|
current_display->next_shader_flags = GF_TEXTURE;
|
||||||
dynamicval<eModel> pm(pmodel, mdUnchanged);
|
dynamicval<eModel> m(pmodel, mdPixel);
|
||||||
if(!svg::in) current_display->set_all(0);
|
if(!svg::in) current_display->set_all(0);
|
||||||
glBindTexture(GL_TEXTURE_2D, text_texture);
|
glBindTexture(GL_TEXTURE_2D, text_texture);
|
||||||
glhr::color2(text_color);
|
glhr::color2(text_color);
|
||||||
glhr::set_depthtest(false);
|
glhr::set_depthtest(false);
|
||||||
for(int ed = (current_display->stereo_active() && text_shift)?-1:0; ed<2; ed+=2) {
|
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);
|
current_display->set_mask(ed);
|
||||||
|
|
||||||
glhr::current_vertices = NULL;
|
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) {
|
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++) {
|
for(int i=ofs; i<ofs+cnt; i++) {
|
||||||
hyperpoint h = glhr::gltopoint(tab[i]);
|
hyperpoint h = glhr::gltopoint(tab[i]);
|
||||||
h[3] = 1;
|
h[3] = 1;
|
||||||
@ -475,68 +474,6 @@ void drawTexturedTriangle(SDL_Surface *s, int *px, int *py, glvertex *tv, color_
|
|||||||
|
|
||||||
#if CAP_GL
|
#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;
|
EX int global_projection;
|
||||||
|
|
||||||
int min_slr, max_slr = 0;
|
int min_slr, max_slr = 0;
|
||||||
@ -593,8 +530,10 @@ void dqi_poly::gldraw() {
|
|||||||
current_display->set_all(ed);
|
current_display->set_all(ed);
|
||||||
bool draw = color;
|
bool draw = color;
|
||||||
|
|
||||||
if(shaderside_projection) {
|
flagtype sp = get_shader_flags();
|
||||||
if(glhr::current_shader_projection == glhr::shader_projection::band && V[2][2] > 1e8) continue;
|
|
||||||
|
if(sp & SF_DIRECT) {
|
||||||
|
if((sp & SF_BAND) && V[2][2] > 1e8) continue;
|
||||||
glapplymatrix(V);
|
glapplymatrix(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,18 +566,17 @@ void dqi_poly::gldraw() {
|
|||||||
glStencilFunc( GL_NOTEQUAL, 1, 1);
|
glStencilFunc( GL_NOTEQUAL, 1, 1);
|
||||||
GLfloat xx = vid.xres;
|
GLfloat xx = vid.xres;
|
||||||
GLfloat yy = vid.yres;
|
GLfloat yy = vid.yres;
|
||||||
GLfloat dist = shaderside_projection ? current_display->scrdist : 0;
|
|
||||||
vector<glvertex> scr = {
|
vector<glvertex> scr = {
|
||||||
glhr::makevertex(-xx, -yy, dist),
|
glhr::makevertex(-xx, -yy, 0),
|
||||||
glhr::makevertex(+xx, -yy, dist),
|
glhr::makevertex(+xx, -yy, 0),
|
||||||
glhr::makevertex(+xx, +yy, dist),
|
glhr::makevertex(+xx, +yy, 0),
|
||||||
glhr::makevertex(-xx, +yy, dist)
|
glhr::makevertex(-xx, +yy, 0)
|
||||||
};
|
};
|
||||||
glhr::vertices(scr);
|
glhr::vertices(scr);
|
||||||
glhr::id_modelview();
|
glhr::id_modelview();
|
||||||
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, 0, 4);
|
||||||
glhr::vertices(v);
|
glhr::vertices(v);
|
||||||
if(shaderside_projection) glapplymatrix(V);
|
if(sp & SF_DIRECT) glapplymatrix(V);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
|
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
|
||||||
@ -681,7 +619,7 @@ EX ld linewidthat(const hyperpoint& h) {
|
|||||||
if(!(vid.antialias & AA_LINEWIDTH)) return 1;
|
if(!(vid.antialias & AA_LINEWIDTH)) return 1;
|
||||||
else if(hyperbolic && pmodel == mdDisk && vid.alpha == 1 && !ISWEB) {
|
else if(hyperbolic && pmodel == mdDisk && vid.alpha == 1 && !ISWEB) {
|
||||||
double dz = h[LDIM];
|
double dz = h[LDIM];
|
||||||
if(dz < 1 || abs(dz-current_display->scrdist) < 1e-6) return 1;
|
if(dz < 1) return 1;
|
||||||
else {
|
else {
|
||||||
double dx = sqrt(dz * dz - 1);
|
double dx = sqrt(dz * dz - 1);
|
||||||
double dfc = dx/(dz+1);
|
double dfc = dx/(dz+1);
|
||||||
@ -898,7 +836,7 @@ void compute_side_by_area() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ld get_width(dqi_poly* p) {
|
ld get_width(dqi_poly* p) {
|
||||||
if((p->flags & POLY_FORCEWIDE) || pmodel == mdUnchanged)
|
if((p->flags & POLY_FORCEWIDE) || pmodel == mdPixel)
|
||||||
return p->linewidth;
|
return p->linewidth;
|
||||||
else if(p->flags & POLY_PRECISE_WIDE) {
|
else if(p->flags & POLY_PRECISE_WIDE) {
|
||||||
ld maxwidth = 0;
|
ld maxwidth = 0;
|
||||||
@ -1241,7 +1179,7 @@ EX }
|
|||||||
void dqi_poly::draw() {
|
void dqi_poly::draw() {
|
||||||
if(flags & POLY_DEBUG) debug_this();
|
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);
|
s2xe::draw_s2xe(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1331,7 +1269,7 @@ void dqi_poly::draw() {
|
|||||||
if(cpha == 1) pha = 0;
|
if(cpha == 1) pha = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dynamicval<eModel> d1(pmodel, mdUnchanged);
|
dynamicval<eModel> d1(pmodel, mdPixel);
|
||||||
dynamicval<transmatrix> d2(V, Id);
|
dynamicval<transmatrix> d2(V, Id);
|
||||||
dynamicval<int> d3(offset, 0);
|
dynamicval<int> d3(offset, 0);
|
||||||
dynamicval<decltype(tab)> d4(tab, tab);
|
dynamicval<decltype(tab)> d4(tab, tab);
|
||||||
@ -1351,7 +1289,7 @@ void dqi_poly::draw() {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
#if CAP_GL
|
#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) {
|
if(sl2 && pmodel == mdGeodesic) {
|
||||||
ld z = atan2(V[2][3], V[3][3]);
|
ld z = atan2(V[2][3], V[3][3]);
|
||||||
auto zr = sightranges[geometry];
|
auto zr = sightranges[geometry];
|
||||||
@ -1472,7 +1410,7 @@ void dqi_poly::draw() {
|
|||||||
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
ld h = atan2(glcoords[0][0], glcoords[0][1]);
|
||||||
for(int i=0; i<=360; i++) {
|
for(int i=0; i<=360; i++) {
|
||||||
ld a = i * degree + h;
|
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;
|
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) {
|
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);
|
hyperpoint h3 = midz(h1, h2);
|
||||||
prettylinesub(h1, h3, lev-1);
|
prettylinesub(h1, h3, lev-1);
|
||||||
prettylinesub(h3, h2, lev-1);
|
prettylinesub(h3, h2, lev-1);
|
||||||
|
@ -1003,21 +1003,23 @@ void geometry_information::make_floor_textures_here() {
|
|||||||
|
|
||||||
// gradient vertices
|
// gradient vertices
|
||||||
vector<glhr::colored_vertex> gv;
|
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, 0, 0, 0);
|
gv.emplace_back(+1, -1, 0, 0, 0);
|
||||||
gv.emplace_back(+1, +1, 1, 1, 1);
|
gv.emplace_back(+1, +1, 1, 1, 1);
|
||||||
gv.emplace_back(-1, -1, 0, 0, 0);
|
gv.emplace_back(-1, -1, 0, 0, 0);
|
||||||
gv.emplace_back(+1, +1, 1, 1, 1);
|
gv.emplace_back(+1, +1, 1, 1, 1);
|
||||||
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);
|
if(1) {
|
||||||
current_display->set_all(0);
|
current_display->next_shader_flags = GF_VARCOLOR;
|
||||||
glhr::new_projection();
|
dynamicval<eModel> m(pmodel, mdPixel);
|
||||||
glhr::id_modelview();
|
current_display->set_all(0);
|
||||||
glhr::prepare(gv);
|
glhr::new_projection();
|
||||||
glhr::set_depthtest(false);
|
glhr::id_modelview();
|
||||||
glDrawArrays(GL_TRIANGLES, 0, isize(gv));
|
glhr::prepare(gv);
|
||||||
|
glhr::set_depthtest(false);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, isize(gv));
|
||||||
|
}
|
||||||
|
|
||||||
shOverFloor.pstrength = 20;
|
shOverFloor.pstrength = 20;
|
||||||
shFeatherFloor.pstrength = 40;
|
shFeatherFloor.pstrength = 40;
|
||||||
|
821
glhr.cpp
Normal file
821
glhr.cpp
Normal 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
|
||||||
|
|
11
graph.cpp
11
graph.cpp
@ -3076,9 +3076,9 @@ void drawaura() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
glflush();
|
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);
|
current_display->set_all(0);
|
||||||
glhr::switch_mode(glhr::gmVarColored, glhr::shader_projection::standard);
|
|
||||||
glhr::id_modelview();
|
glhr::id_modelview();
|
||||||
glhr::prepare(auravertices);
|
glhr::prepare(auravertices);
|
||||||
glhr::set_depthtest(false);
|
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) {
|
for(int ed = current_display->stereo_active() ? -1 : 0; ed<2; ed+=2) {
|
||||||
if(global_projection && global_projection != ed) continue;
|
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);
|
current_display->set_all(ed);
|
||||||
if(global_projection)
|
if(global_projection)
|
||||||
glhr::projection_multiply(glhr::tmtogl(xpush(-vid.ipd * global_projection/2)));
|
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);
|
cd->tanfov = tan(vid.fov * degree / 2);
|
||||||
|
|
||||||
if(pmodel)
|
|
||||||
cd->scrdist = vid.xres / 2 / cd->tanfov;
|
|
||||||
else
|
|
||||||
cd->scrdist = cd->radius;
|
|
||||||
|
|
||||||
callhooks(hooks_calcparam);
|
callhooks(hooks_calcparam);
|
||||||
reset_projection();
|
reset_projection();
|
||||||
}
|
}
|
||||||
|
2
hud.cpp
2
hud.cpp
@ -389,7 +389,7 @@ EX void draw_radar(bool cornermode) {
|
|||||||
bool scompass = nonisotropic && !hybri;
|
bool scompass = nonisotropic && !hybri;
|
||||||
|
|
||||||
dynamicval<eGeometry> g(geometry, gEuclid);
|
dynamicval<eGeometry> g(geometry, gEuclid);
|
||||||
dynamicval<eModel> pm(pmodel, mdUnchanged);
|
dynamicval<eModel> pm(pmodel, mdDisk);
|
||||||
dynamicval<bool> ga(vid.always3, false);
|
dynamicval<bool> ga(vid.always3, false);
|
||||||
dynamicval<geometryinfo1> gi(ginf[gEuclid].g, giEuclid2);
|
dynamicval<geometryinfo1> gi(ginf[gEuclid].g, giEuclid2);
|
||||||
initquickqueue();
|
initquickqueue();
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
|
|
||||||
#include "classes.cpp"
|
#include "classes.cpp"
|
||||||
|
#include "glhr.cpp"
|
||||||
#include "shaders.cpp"
|
#include "shaders.cpp"
|
||||||
#include "hprint.cpp"
|
#include "hprint.cpp"
|
||||||
#include "util.cpp"
|
#include "util.cpp"
|
||||||
|
36
hypgraph.cpp
36
hypgraph.cpp
@ -36,7 +36,7 @@ EX bool non_spatial_model() {
|
|||||||
return true;
|
return true;
|
||||||
if(pmodel == mdSpiral && euclid)
|
if(pmodel == mdSpiral && euclid)
|
||||||
return true;
|
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) {
|
hyperpoint perspective_to_space(hyperpoint h, ld alpha, eGeometryClass gc) {
|
||||||
@ -120,7 +120,7 @@ void apply_depth(hyperpoint &f, ld z) {
|
|||||||
f[2] = z;
|
f[2] = z;
|
||||||
else {
|
else {
|
||||||
z = z * current_display->radius;
|
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[0] = f[0] * mul;
|
||||||
f[1] = f[1] * mul;
|
f[1] = f[1] * mul;
|
||||||
f[2] = vid.xres * current_display->eyewidth() / 2 / current_display->radius + vid.ipd * mul / 2;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case mdUnchanged:
|
case mdPixel:
|
||||||
case mdFlatten:
|
|
||||||
ret = H / current_display->radius;
|
ret = H / current_display->radius;
|
||||||
return;
|
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);
|
ghcheck(ret,H_orig);
|
||||||
@ -1526,7 +1525,7 @@ void addball(ld a, ld b, ld c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ballgeometry() {
|
void ballgeometry() {
|
||||||
queuereset(vid.usingGL ? mdDisk : mdUnchanged, PPR::CIRCLE);
|
queuereset(mdPixel, PPR::CIRCLE);
|
||||||
for(int i=0; i<60; i++)
|
for(int i=0; i<60; i++)
|
||||||
addball(i * M_PI/30, 10, 0);
|
addball(i * M_PI/30, 10, 0);
|
||||||
for(double d=10; d>=-10; d-=.2)
|
for(double d=10; d>=-10; d-=.2)
|
||||||
@ -1586,12 +1585,17 @@ transmatrix screenpos(ld x, ld y) {
|
|||||||
return V;
|
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) {
|
EX transmatrix atscreenpos(ld x, ld y, ld size) {
|
||||||
transmatrix V = Id;
|
transmatrix V = Id;
|
||||||
|
|
||||||
if(pmodel == mdFlatten) {
|
if(pmodel == mdPixel) {
|
||||||
V[0][3] += (x - current_display->xcenter);
|
V[0][3] += (x - current_display->xcenter);
|
||||||
V[1][3] += (y - current_display->ycenter);
|
V[1][3] += (y - current_display->ycenter);
|
||||||
V[0][0] = size * 2 * cgi.hcrossf / cgi.crossf;
|
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[1][2] += (y - current_display->ycenter);
|
||||||
V[0][0] = size * 2 * cgi.hcrossf / cgi.crossf;
|
V[0][0] = size * 2 * cgi.hcrossf / cgi.crossf;
|
||||||
V[1][1] = 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;
|
if(S3 == OINF) V[0][0] /= 5, V[1][1] /= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1647,7 +1651,7 @@ EX void draw_model_elements() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case mdTwoHybrid: {
|
case mdTwoHybrid: {
|
||||||
queuereset(mdUnchanged, PPR::CIRCLE);
|
queuereset(mdPixel, PPR::CIRCLE);
|
||||||
|
|
||||||
for(int mode=0; mode<4; mode++) {
|
for(int mode=0; mode<4; mode++) {
|
||||||
for(int s=-200; s<=200; s ++) {
|
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);
|
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(H0 - spin(M_PI/2) * H0 * mul0);
|
curvepoint(H0 - spin(M_PI/2) * H0 * mul0);
|
||||||
curvepoint(H1 + spin(M_PI/2) * H1 * mul1);
|
curvepoint(H1 + spin(M_PI/2) * H1 * mul1);
|
||||||
@ -1794,7 +1798,7 @@ EX void draw_boundary(int w) {
|
|||||||
|
|
||||||
case mdTwoPoint: {
|
case mdTwoPoint: {
|
||||||
if(twopoint_do_flips || current_display->stereo_active() || !sphere) return;
|
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(int b=-1; b<=1; b+=2)
|
||||||
for(ld a=-90; a<=90+1e-6; a+=pow(.5, vid.linequality)) {
|
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: {
|
case mdHemisphere: {
|
||||||
if(hyperbolic) {
|
if(hyperbolic) {
|
||||||
queuereset(mdUnchanged, p);
|
queuereset(mdPixel, p);
|
||||||
for(int i=0; i<=360; i++) {
|
for(int i=0; i<=360; i++) {
|
||||||
ld s = sin(i * degree);
|
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));
|
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);
|
queuecurve(lc, fc, p);
|
||||||
queuereset(pmodel, p);
|
queuereset(pmodel, p);
|
||||||
p = PPR::CIRCLE; fc = 0;
|
p = PPR::CIRCLE; fc = 0;
|
||||||
queuereset(mdUnchanged, p);
|
queuereset(mdPixel, p);
|
||||||
|
|
||||||
for(int i=0; i<=360; i++) {
|
for(int i=0; i<=360; i++) {
|
||||||
ld s = sin(i * degree);
|
ld s = sin(i * degree);
|
||||||
@ -1869,7 +1873,7 @@ EX void draw_boundary(int w) {
|
|||||||
queuereset(pmodel, p);
|
queuereset(pmodel, p);
|
||||||
}
|
}
|
||||||
if(euclid || sphere) {
|
if(euclid || sphere) {
|
||||||
queuereset(mdUnchanged, p);
|
queuereset(mdPixel, p);
|
||||||
for(int i=0; i<=360; i++) {
|
for(int i=0; i<=360; i++) {
|
||||||
curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * sin(i * degree), 0));
|
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;
|
auto& sm = models::spiral_multiplier;
|
||||||
ld u = hypot(1, imag(sm) / real(sm));
|
ld u = hypot(1, imag(sm) / real(sm));
|
||||||
if(real(sm)) {
|
if(real(sm)) {
|
||||||
queuereset(mdUnchanged, p);
|
queuereset(mdPixel, p);
|
||||||
for(ld a=-10; a<=10; a+=0.01 / (1 << vid.linequality) / u) {
|
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));
|
cld z = exp(cld(a, a * imag(sm) / real(sm) + M_PI));
|
||||||
hyperpoint ret = point2(real(z), imag(z));
|
hyperpoint ret = point2(real(z), imag(z));
|
||||||
|
@ -281,7 +281,7 @@ EX namespace models {
|
|||||||
#if CAP_QUEUE && CAP_CURVE
|
#if CAP_QUEUE && CAP_CURVE
|
||||||
dialog::extra_options = [] () {
|
dialog::extra_options = [] () {
|
||||||
initquickqueue();
|
initquickqueue();
|
||||||
queuereset(mdUnchanged, PPR::LINE);
|
queuereset(mdPixel, PPR::LINE);
|
||||||
for(int a=-1; a<=1; a++) {
|
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));
|
||||||
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::add_action(edit_stretch);
|
||||||
|
|
||||||
dialog::addBoolItem(XLAT("use GPU to compute projections"), vid.consider_shader_projection, 'G');
|
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)
|
if(vid.consider_shader_projection && !shaderside_projection)
|
||||||
dialog::lastItem().value = XLAT("N/A");
|
dialog::lastItem().value = XLAT("N/A");
|
||||||
if(vid.consider_shader_projection && shaderside_projection && pmodel)
|
if(vid.consider_shader_projection && shaderside_projection && pmodel)
|
||||||
|
4
rug.cpp
4
rug.cpp
@ -1393,7 +1393,7 @@ EX void drawRugScene() {
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
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_depthtest(true);
|
||||||
glhr::set_depthwrite(true);
|
glhr::set_depthwrite(true);
|
||||||
glDepthFunc(invert_depth ? GL_GREATER : GL_LESS);
|
glDepthFunc(invert_depth ? GL_GREATER : GL_LESS);
|
||||||
@ -1405,7 +1405,7 @@ EX void drawRugScene() {
|
|||||||
if(ed == 1 && vid.stereo_mode == sAnaglyph)
|
if(ed == 1 && vid.stereo_mode == sAnaglyph)
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
dynamicval<eModel> p(pmodel, mdRug);
|
dynamicval<eModel> p(pmodel, mdManual);
|
||||||
current_display->set_all(ed);
|
current_display->set_all(ed);
|
||||||
eyewidth_translate(ed);
|
eyewidth_translate(ed);
|
||||||
|
|
||||||
|
1438
shaders.cpp
1438
shaders.cpp
File diff suppressed because it is too large
Load Diff
@ -669,7 +669,7 @@ void texture_config::drawRawTexture() {
|
|||||||
rtver[i].coords[2] = 0;
|
rtver[i].coords[2] = 0;
|
||||||
rtver[i].coords[3] = 1;
|
rtver[i].coords[3] = 1;
|
||||||
}
|
}
|
||||||
glhr::set_modelview(glhr::translate(0, 0, current_display->scrdist));
|
glhr::id_modelview();
|
||||||
glhr::prepare(rtver);
|
glhr::prepare(rtver);
|
||||||
glhr::set_depthtest(false);
|
glhr::set_depthtest(false);
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
Loading…
Reference in New Issue
Block a user