1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 01:20:37 +00:00

refactored drawing to a texture; HQ shots can now be saved using OpenGL

This commit is contained in:
Zeno Rogue 2018-02-01 13:42:47 +01:00
parent 84980e55fc
commit 8e8ece7162
4 changed files with 62 additions and 153 deletions

View File

@ -32,7 +32,7 @@ TTF_Font *font[256];
#endif #endif
#if CAP_SDL #if CAP_SDL
SDL_Surface *s; SDL_Surface *s, *s_screen;
int qpixel_pixel_outside; int qpixel_pixel_outside;
@ -220,13 +220,13 @@ void selectEyeMask(int ed) {
} }
} }
void setGLProjection() { void setGLProjection(int col) {
DEBB(DF_GRAPH, (debugfile,"setGLProjection\n")); DEBB(DF_GRAPH, (debugfile,"setGLProjection\n"));
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
unsigned char *c = (unsigned char*) (&backcolor); unsigned char *c = (unsigned char*) (&col);
glClearColor(c[2] / 255.0, c[1] / 255.0, c[0]/255.0, 1); glClearColor(c[2] / 255.0, c[1] / 255.0, c[0]/255.0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -956,7 +956,7 @@ void IMAGESAVE(SDL_Surface *s, const char *fname) {
} }
#endif #endif
hookset<void(SDL_Surface*)> *hooks_hqshot; hookset<void(renderbuffer*)> *hooks_hqshot;
#if CAP_SDL #if CAP_SDL
void saveHighQualityShot(const char *fname, const char *caption, int fade) { void saveHighQualityShot(const char *fname, const char *caption, int fade) {
@ -988,26 +988,30 @@ void saveHighQualityShot(const char *fname, const char *caption, int fade) {
while(vid.xres & 15) vid.xres++; while(vid.xres & 15) vid.xres++;
} }
vid.usingGL = false;
// if(vid.pmodel == 0) vid.scale = 0.99; // if(vid.pmodel == 0) vid.scale = 0.99;
calcparam(); calcparam();
#if CAP_ROGUEVIZ #if CAP_ROGUEVIZ
rogueviz::fixparam(); rogueviz::fixparam();
#endif #endif
// printf("format = %d, %d x %d\n", pngformat, vid.xres, vid.yres); renderbuffer glbuf(vid.xres, vid.yres, vid.usingGL);
glbuf.enable();
dynamicval<SDL_Surface*> v5(s, SDL_CreateRGBSurface(SDL_SWSURFACE,vid.xres,vid.yres,32,0,0,0,0)); // printf("format = %d, %d x %d\n", pngformat, vid.xres, vid.yres);
darken = 0; darken = 0;
int numi = (fname?1:2); int numi = (fname?1:2);
for(int i=0; i<numi; i++) { for(int i=0; i<numi; i++) {
SDL_FillRect(s, NULL, numi==1 ? backcolor : i ? 0xFFFFFF : 0); glbuf.clear(numi==1 ? backcolor : i ? 0xFFFFFF : 0);
if(rug::rugged)
rug::drawRugScene();
else
drawfullmap(); drawfullmap();
callhooks(hooks_hqshot, s); callhooks(hooks_hqshot, &glbuf);
if(fade < 255) if(fade < 255)
for(int y=0; y<vid.yres; y++) for(int y=0; y<vid.yres; y++)
@ -1024,13 +1028,12 @@ void saveHighQualityShot(const char *fname, const char *caption, int fade) {
char buf[128]; strftime(buf, 128, "bigshota-%y%m%d-%H%M%S" IMAGEEXT, localtime(&timer)); char buf[128]; strftime(buf, 128, "bigshota-%y%m%d-%H%M%S" IMAGEEXT, localtime(&timer));
buf[7] += i; buf[7] += i;
if(!fname) fname = buf; if(!fname) fname = buf;
IMAGESAVE(s, fname); IMAGESAVE(glbuf.render(), fname);
if(i == 0) addMessage(XLAT("Saved the high quality shot to %1", fname)); if(i == 0) addMessage(XLAT("Saved the high quality shot to %1", fname));
} }
SDL_FreeSurface(s); glbuf.disable();
} }
#endif #endif
@ -1069,13 +1072,13 @@ void setvideomode() {
int sizeflag = (vid.full ? SDL_FULLSCREEN : SDL_RESIZABLE); int sizeflag = (vid.full ? SDL_FULLSCREEN : SDL_RESIZABLE);
s= SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | sizeflag); s = s_screen = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | sizeflag);
if(vid.full && !s) { if(vid.full && !s) {
vid.xres = vid.xscr; vid.xres = vid.xscr;
vid.yres = vid.yscr; vid.yres = vid.yscr;
do_setfsize(); do_setfsize();
s = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | SDL_FULLSCREEN); s = s_screen = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | SDL_FULLSCREEN);
} }
if(!s) { if(!s) {
@ -1084,7 +1087,7 @@ void setvideomode() {
vid.yres = 480; vid.yres = 480;
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
vid.antialias &= ~AA_MULTI; vid.antialias &= ~AA_MULTI;
s = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | SDL_RESIZABLE); s = s_screen = SDL_SetVideoMode(vid.xres, vid.yres, 32, flags | SDL_RESIZABLE);
} }
#if CAP_GL #if CAP_GL

View File

@ -57,6 +57,7 @@ bool inv::on;
#include "nofont.cpp" #include "nofont.cpp"
#endif #endif
#include "basegraph.cpp" #include "basegraph.cpp"
#include "renderbuffer.cpp"
#include "help.cpp" #include "help.cpp"
#include "config.cpp" #include "config.cpp"
#include "scores.cpp" #include "scores.cpp"

25
hyper.h
View File

@ -798,7 +798,10 @@ namespace polygonal {
void selectEyeGL(int ed); void selectEyeGL(int ed);
void selectEyeMask(int ed); void selectEyeMask(int ed);
extern int ticks; extern int ticks;
void setGLProjection();
extern unsigned backcolor, bordcolor, forecolor;
void setGLProjection(int col = backcolor);
// passable flags // passable flags
@ -1433,8 +1436,6 @@ extern cell *recallCell;
extern eLand cheatdest; extern eLand cheatdest;
void cheatMoveTo(eLand l); void cheatMoveTo(eLand l);
extern unsigned backcolor, bordcolor, forecolor;
extern bool overgenerate; extern bool overgenerate;
void doOvergenerate(); void doOvergenerate();
@ -2508,3 +2509,21 @@ template<class T, class U> void eliminate_if(vector<T>& data, U pred) {
bool is_cell_removed(cell *c); bool is_cell_removed(cell *c);
void set_if_removed(cell*& c, cell *val); void set_if_removed(cell*& c, cell *val);
struct renderbuffer {
int x, y, tx, ty;
GLuint FramebufferName;
GLuint renderedTexture;
GLuint depth_stencil_rb;
SDL_Surface *srf;
Uint32 *expanded_data;
void make_surface();
renderbuffer(int x, int y, bool gl);
~renderbuffer();
void enable();
void disable();
SDL_Surface *render();
void use_as_texture();
void clear(int col);
};

128
rug.cpp
View File

@ -9,28 +9,6 @@
#define TEXTURESIZE (texturesize) #define TEXTURESIZE (texturesize)
#define HTEXTURESIZE (texturesize/2) #define HTEXTURESIZE (texturesize/2)
#if !CAP_GLEW
#if ISLINUX
extern "C" {
GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
}
#endif
#if ISMAC
#define glFramebufferTexture glFramebufferTextureEXT
#endif
#endif
namespace rug { namespace rug {
struct rug_exception { }; struct rug_exception { };
@ -1083,81 +1061,17 @@ void drawTriangle(triangle& t) {
} }
} }
GLuint FramebufferName = 0; renderbuffer *glbuf;
GLuint renderedTexture = 0;
GLuint depth_stencil_rb = 0;
SDL_Surface *texture;
Uint32 *expanded_data;
void initTexture() {
if(!rendernogl) {
#if !ISPANDORA
FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, TEXTURESIZE, TEXTURESIZE, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifdef TEX
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
#else
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderedTexture, 0);
#endif
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers);
glGenRenderbuffers(1, &depth_stencil_rb);
glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, TEXTURESIZE, TEXTURESIZE);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_stencil_rb);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth_stencil_rb);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
addMessage("Failed to initialize the framebuffer");
rugged = false;
}
#endif
}
else {
texture = SDL_CreateRGBSurface(SDL_SWSURFACE,TEXTURESIZE,TEXTURESIZE,32,0,0,0,0);
glGenTextures( 1, &renderedTexture );
glBindTexture( GL_TEXTURE_2D, renderedTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
expanded_data = new Uint32[TEXTURESIZE * TEXTURESIZE];
}
}
void prepareTexture() { void prepareTexture() {
videopar svid = vid; videopar svid = vid;
setVidParam(); setVidParam();
if(rendernogl) { glbuf->enable();
vid.usingGL = false;
SDL_Surface *sav = s;
s = texture;
SDL_FillRect(s, NULL, 0);
drawfullmap(); glbuf->clear(0);
s = sav;
for(int y=0; y<TEXTURESIZE; y++) for(int x=0; x<TEXTURESIZE; x++)
expanded_data[y*TEXTURESIZE + x] = qpixel(texture, x, TEXTURESIZE-1-y) | 0xFF000000;
glBindTexture( GL_TEXTURE_2D, renderedTexture);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEXTURESIZE, TEXTURESIZE, 0, GL_BGRA, GL_UNSIGNED_BYTE, expanded_data );
}
else {
#if !ISPANDORA
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glViewport(0,0,TEXTURESIZE,TEXTURESIZE);
setGLProjection();
ptds.clear(); ptds.clear();
drawthemap(); drawthemap();
if(mousing && !renderonce) { if(mousing && !renderonce) {
@ -1171,26 +1085,8 @@ void prepareTexture() {
queueline(tC0(V * spin(i*M_PI/32) * xpush(finger_range)), tC0(V * spin((i+1)*M_PI/32) * xpush(finger_range)), 0xFFFFFFFF, 0); queueline(tC0(V * spin(i*M_PI/32) * xpush(finger_range)), tC0(V * spin((i+1)*M_PI/32) * xpush(finger_range)), 0xFFFFFFFF, 0);
} }
drawqueue(); drawqueue();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
}
vid = svid; vid = svid;
if(!rendernogl) glViewport(0,0,vid.xres,vid.yres); glbuf->disable();
}
void closeTexture() {
if(rendernogl) {
SDL_FreeSurface(texture);
glDeleteTextures(1, &renderedTexture);
delete[] expanded_data;
}
else {
#if !ISPANDORA
glDeleteTextures(1, &renderedTexture);
glDeleteRenderbuffers(1, &depth_stencil_rb);
glDeleteFramebuffers(1, &FramebufferName);
#endif
}
} }
double xview, yview; double xview, yview;
@ -1215,7 +1111,7 @@ void drawRugScene() {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
glBindTexture(GL_TEXTURE_2D, renderedTexture); glbuf->use_as_texture();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
@ -1310,20 +1206,10 @@ void drawRugScene() {
transmatrix currentrot; transmatrix currentrot;
void init() { void init() {
#if CAP_GLEW
if(!glew) {
glew = true;
GLenum err = glewInit();
if (GLEW_OK != err) {
addMessage("Failed to initialize GLEW");
return;
}
}
#endif
if(rugged) return; if(rugged) return;
rugged = true; rugged = true;
if(scale < .01 || scale > 100) scale = 1; if(scale < .01 || scale > 100) scale = 1;
initTexture(); glbuf = new renderbuffer(TEXTURESIZE, TEXTURESIZE, vid.usingGL && !rendernogl);
if(renderonce) prepareTexture(); if(renderonce) prepareTexture();
if(!rugged) return; if(!rugged) return;
@ -1364,7 +1250,7 @@ void init() {
void close() { void close() {
if(!rugged) return; if(!rugged) return;
rugged = false; rugged = false;
closeTexture(); delete glbuf;
triangles.clear(); triangles.clear();
for(int i=0; i<size(points); i++) delete points[i]; for(int i=0; i<size(points); i++) delete points[i];
points.clear(); points.clear();