From 5a7cceb19d023596b650cefb13552f52ac4d4cf1 Mon Sep 17 00:00:00 2001 From: Plagman Date: Sat, 6 Jan 2007 01:29:45 +0000 Subject: [PATCH] Second draft of depth peeling code. It should be in a usable state, although still slow as hell. git-svn-id: https://svn.eduke32.com/eduke32@446 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/build/include/baselayer.h | 5 + polymer/build/include/build.h | 2 + polymer/build/include/glbuild.h | 16 ++ polymer/build/src/baselayer.c | 17 +- polymer/build/src/engine.c | 299 +++++------------------------- polymer/build/src/glbuild.c | 58 ++++-- polymer/build/src/mdsprite.c | 13 +- polymer/build/src/polymost.c | 178 +++++++++++++----- polymer/build/src/sdlayer.c | 21 +++ polymer/build/src/winlayer.c | 11 ++ polymer/eduke32/source/config.c | 5 + 11 files changed, 302 insertions(+), 323 deletions(-) diff --git a/polymer/build/include/baselayer.h b/polymer/build/include/baselayer.h index ac15c9b4e..292bf02d1 100644 --- a/polymer/build/include/baselayer.h +++ b/polymer/build/include/baselayer.h @@ -41,6 +41,11 @@ struct glinfo { char texnpot; char multisample; char nvmultisamplehint; + char arbfp; + char depthtex; + char shadow; + char fbos; + char rect; }; extern struct glinfo glinfo; #endif diff --git a/polymer/build/include/build.h b/polymer/build/include/build.h index 0361b2b5b..9f8639f4a 100644 --- a/polymer/build/include/build.h +++ b/polymer/build/include/build.h @@ -490,6 +490,8 @@ extern long glusetexcache, glusetexcachecompression; extern long glmultisample, glnvmultisamplehint; extern long glwidescreen, glprojectionhacks; void gltexapplyprops (void); + +extern long r_depthpeeling, r_peelscount; #endif void hicinit(void); diff --git a/polymer/build/include/glbuild.h b/polymer/build/include/glbuild.h index 082e84905..780e5c69c 100644 --- a/polymer/build/include/glbuild.h +++ b/polymer/build/include/glbuild.h @@ -30,6 +30,14 @@ # define APIENTRY #endif +// those defines are somehow missing from glext.h +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 + +#define GL_TEXTURE_RECTANGLE 0x84F5 + extern void (APIENTRY * bglClearColor)( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); extern void (APIENTRY * bglClear)( GLbitfield mask ); extern void (APIENTRY * bglColorMask)( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ); @@ -132,9 +140,17 @@ extern void (APIENTRY * bglStencilFunc)(GLenum func, GLint ref, GLuint mask); extern void (APIENTRY * bglGenProgramsARB)(GLsizei, GLuint *); extern void (APIENTRY * bglBindProgramARB)(GLenum, GLuint); extern void (APIENTRY * bglProgramStringARB)(GLenum, GLenum, GLsizei, const GLvoid *); +extern void (APIENTRY * bglDeleteProgramsARB)(GLsizei n, const GLuint *programs); // Multitexturing extern void (APIENTRY * bglActiveTextureARB)(GLenum texture); + +// Frame Buffer Objects +extern void (APIENTRY * bglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers); +extern void (APIENTRY * bglBindFramebufferEXT)(GLenum target, GLuint framebuffer); +extern void (APIENTRY * bglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +extern GLenum (APIENTRY * bglCheckFramebufferStatusEXT)(GLenum target); +extern void (APIENTRY * bglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers); #ifdef RENDERTYPEWIN // Windows diff --git a/polymer/build/src/baselayer.c b/polymer/build/src/baselayer.c index f382b235e..9f7ba4fcc 100644 --- a/polymer/build/src/baselayer.c +++ b/polymer/build/src/baselayer.c @@ -21,6 +21,11 @@ struct glinfo glinfo = { 0, // non-power-of-two textures 0, // multisampling 0, // nvidia multisampling hint + 0, // ARBfp + 0, // depth textures + 0, // shadow comparison + 0, // Frame Buffer Objects + 0, // rectangle textures }; #endif @@ -89,6 +94,11 @@ static int osdcmd_glinfo(const osdfuncparm_t *parm) " Clamp-to-edge: %s\n" " Multisampling: %s\n" " Nvidia multisample hint: %s\n" + " ARBfp fragment programs: %s\n" + " Depth textures: %s\n" + " Shadow textures: %s\n" + " Frame Buffer Objects: %s\n" + " Rectangle textures: %s\n" " Extensions:\n", glinfo.version, glinfo.vendor, @@ -99,7 +109,12 @@ static int osdcmd_glinfo(const osdfuncparm_t *parm) glinfo.texcompr ? "supported": "not supported", glinfo.clamptoedge ? "supported": "not supported", glinfo.multisample ? "supported": "not supported", - glinfo.nvmultisamplehint ? "supported": "not supported" + glinfo.nvmultisamplehint ? "supported": "not supported", + glinfo.arbfp ? "supported": "not supported", + glinfo.depthtex ? "supported": "not supported", + glinfo.shadow ? "supported": "not supported", + glinfo.fbos ? "supported": "not supported", + glinfo.rect ? "supported": "not supported" ); s = Bstrdup(glinfo.extensions); diff --git a/polymer/build/src/engine.c b/polymer/build/src/engine.c index e14a64d8f..f4f4badc9 100644 --- a/polymer/build/src/engine.c +++ b/polymer/build/src/engine.c @@ -3130,7 +3130,6 @@ if (!davoxptr && i > 0) { davoxptr = (char *)voxoff[daindex][0]; i = 0; } } #endif - // // drawsprite (internal) // @@ -5740,7 +5739,9 @@ void drawrooms(long daposx, long daposy, long daposz, } //============================================================================= //POLYMOST BEGINS - polymost_drawrooms(); if (rendmode) { return; } + polymost_drawrooms(); + if (rendmode) + return; #endif //============================================================================= //POLYMOST ENDS @@ -5951,9 +5952,10 @@ int sameside(_equation* eq, _point2d* p1, _point2d* p2) return (0); } +#ifdef USE_OPENGL void drawpeel(int peel) { - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, peels[peel]); + bglBindTexture(GL_TEXTURE_RECTANGLE, peels[peel]); bglBegin(GL_QUADS); bglTexCoord2f(0.0f, 0.0f); bglVertex2f(-1.0f, -1.0f); @@ -5965,6 +5967,7 @@ void drawpeel(int peel) bglVertex2f(-1.0f, 1.0f); bglEnd(); } +#endif // // drawmasks @@ -6002,8 +6005,11 @@ killsprite: spritesy[i] = yp; } -if (!usegoodalpha) +#ifdef USE_OPENGL +if ((!r_depthpeeling) || (rendmode < 3)) +#endif { + gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1; for (gap>>=1;gap>0;gap>>=1) //Sort sprite list for (i=0;i=0;i--) @@ -6083,206 +6084,13 @@ if (!usegoodalpha) drawline256(xs+65536,ys-65536,xs-65536,ys+65536,31); }*/ - -if (!usegoodalpha) -{ - { // Removing previous sorting code -#ifdef POLYMOST - //Hack to make it draw all opaque quads first. This should reduce the chances of - //bad sorting causing transparent quads knocking out opaque quads behind it. - // - //Need to store alpha flag with all textures before this works right! - if (rendmode == 3) - { - for (i=spritesortcnt-1;i>=0;i--) - if ((!(tspriteptr[i]->cstat&2)) #ifdef USE_OPENGL - && (!gltexmayhavealpha(tspriteptr[i]->picnum,tspriteptr[i]->pal)) +if ((!r_depthpeeling) || (rendmode < 3)) #endif - ) - { drawsprite(i); tspriteptr[i] = 0; } //draw only if it is fully opaque - for (i=j=0;i=0;i--) - { - k = thewall[maskwall[i]]; - if ((!(wall[k].cstat&128)) -#ifdef USE_OPENGL - && (!gltexmayhavealpha(wall[k].overpicnum,wall[k].pal)) -#endif - ) - { drawmaskwall(i); maskwall[i] = -1; } //draw only if it is fully opaque - } - for (i=j=0;i 0) && (maskwallcnt > 0)) //While BOTH > 0 - { - j = maskwall[maskwallcnt-1]; - if (spritewallfront(tspriteptr[spritesortcnt-1],(long)thewall[j]) == 0) - drawsprite(--spritesortcnt); - else - { - //Check to see if any sprites behind the masked wall... - k = -1; - gap = 0; - for (i=spritesortcnt-2;i>=0;i--) - if ((xb1[j] <= (spritesx[i]>>8)) && ((spritesx[i]>>8) <= xb2[j])) - if (spritewallfront(tspriteptr[i],(long)thewall[j]) == 0) - { - drawsprite(i); - tspriteptr[i]->owner = -1; - k = i; - gap++; - } - if (k >= 0) //remove holes in sprite list - { - for (i=k;iowner >= 0) - { - if (i > k) - { - tspriteptr[k] = tspriteptr[i]; - spritesx[k] = spritesx[i]; - spritesy[k] = spritesy[i]; - } - k++; - } - spritesortcnt -= gap; - } - - //finally safe to draw the masked wall - drawmaskwall(--maskwallcnt); - } - } - while (spritesortcnt > 0) drawsprite(--spritesortcnt); - while (maskwallcnt > 0) drawmaskwall(--maskwallcnt); - } -} -else { - // PLAG : The heart of good transparency -> sorted rendering on all layers. - // that's why this code interleaves the drawing of all possible transparent entities - // bubblesort is used, shouldn't cause any problems cpu-wise since the lists are small - - // SPRITES PREPROCESSING - /*l = spritesortcnt; - indexes = malloc(l * sizeof(long)); - depths = malloc(l * sizeof(long)); - - // first pass to set base indexes and depths - i = l; - while (i > 0) - { - i--; - indexes[i] = --spritesortcnt; - depths[i] = (tspriteptr[spritesortcnt]->x - globalposx) * (tspriteptr[spritesortcnt]->x - globalposx) + - (tspriteptr[spritesortcnt]->y - globalposy) * (tspriteptr[spritesortcnt]->y - globalposy); - } - - // second pass (and possibly more) to z-sort - j = 0; - while (j == 0) - { - j = 1; - for(i=l-1;i>0;i--) - { - if (depths[i] < depths[i-1]) - { - swaplong(&indexes[i-1], &indexes[i]); - swaplong(&depths[i-1], &depths[i]); - j = 0; - } - } - }*/ - - // MASKS PREPROCESSING - //k = maskwallcnt; - - // first pass to set wall equations and init the tree - /*i = k; - while (i > 0) - { - i--; - - // leaf index - maskleaves[i].index = --maskwallcnt; - - // leaf boundaries - maskleaves[i].p1.x = wall[thewall[maskwall[maskleaves[i].index]]].x - globalposx; - maskleaves[i].p1.y = wall[thewall[maskwall[maskleaves[i].index]]].y - globalposy; - maskleaves[i].p2.x = wall[wall[thewall[maskwall[maskleaves[i].index]]].point2].x - globalposx; - maskleaves[i].p2.y = wall[wall[thewall[maskwall[maskleaves[i].index]]].point2].y - globalposy; - - // leaf equations - maskleaves[i].maskeq = equation(maskleaves[i].p1.x, maskleaves[i].p1.y, maskleaves[i].p2.x, maskleaves[i].p2.y); - maskleaves[i].p1eq = equation(0, 0, maskleaves[i].p1.x, maskleaves[i].p1.y); - maskleaves[i].p2eq = equation(0, 0, maskleaves[i].p2.x, maskleaves[i].p2.y); - - // drawing flag - maskleaves[i].drawing = 0; - - //OSD_Printf("Processed mask - %i\n", i); - } - - // second pass to connect the leaves together - i = k; - while (i > 0) - { - i--; - - m = 0; - j = k; - while (j > 0) - { - j--; - - if ((i != j) && (wallobstructswall(&maskleaves[i], &maskleaves[j]))) - maskleaves[i].branch[m++] = &maskleaves[j]; - } - maskleaves[i].branch[m] = NULL; - //OSD_Printf("Processed parents for mask %i\n", i); - }*/ - - // DRAWING - // in this code all sprites are drawn, and masks are inserted when needed - /*i = l - 1; - while (i >= 0) - { - //OSD_Printf("sprite - %i\n", depths[i]); - drawsprite(indexes[i]); - i--; - } - - // this codes draws the remaining (if any) masked walls, meaning those that are directly before the player - while (k > 0) - { - k--; - //OSD_Printf("Beginning drawing process for mask %i\n", k); - //drawmaskleaf(&maskleaves[k]); - drawmaskwall(k); - } - free(indexes); - free(depths);*/ - pos.x = globalposx; pos.y = globalposy; - //OSD_Printf("EIN OBSERVER POSITION : x=%i y=%i\n", pos.x, pos.y); - while (maskwallcnt) { maskwallcnt--; @@ -6292,21 +6100,13 @@ else dot2.x = wall[wall[thewall[maskwall[maskwallcnt]]].point2].x; dot2.y = wall[wall[thewall[maskwall[maskwallcnt]]].point2].y; - //OSD_Printf("EIN WALL : x1=%i y1=%i x2=%i y2=%i\n", dot.x, dot.y, dot2.x, dot2.y); - maskeq = equation(dot.x, dot.y, dot2.x, dot2.y); p1eq = equation(pos.x, pos.y, dot.x, dot.y); p2eq = equation(pos.x, pos.y, dot2.x, dot2.y); - //OSD_Printf("EIN WALL EQUATION : a=%f b=%f c=%f\n", maskeq.a, maskeq.b, maskeq.c); - //OSD_Printf("EIN WALL POINT1 TO POSITION EQUATION : a=%f b=%f c=%f\n", p1eq.a, p1eq.b, p1eq.c); - //OSD_Printf("EIN WALL POINT2 TO POSITION EQUATION : a=%f b=%f c=%f\n", p2eq.a, p2eq.b, p2eq.c); - middle.x = (dot.x + dot2.x) / 2; middle.y = (dot.y + dot2.y) / 2; - //OSD_Printf("EIN WALL MIDDLE POINT POSITION : x=%i y=%i\n", middle.x, middle.y); - i = spritesortcnt; while (i) { @@ -6316,8 +6116,6 @@ else spr.x = tspriteptr[i]->x; spr.y = tspriteptr[i]->y; - //OSD_Printf("EIN SPRITE POSITION : x=%i y=%i\n", spr.x, spr.y); - if ((sameside(&maskeq, &spr, &pos) == 0) && sameside(&p1eq, &middle, &spr) && sameside(&p2eq, &middle, &spr)) { drawsprite(i); @@ -6335,13 +6133,23 @@ else drawsprite(spritesortcnt); } - //while (spritesortcnt > 0) drawsprite(--spritesortcnt); - //while (maskwallcnt > 0) drawmaskwall(--maskwallcnt); -} /* goodalpha */ +} /* depthpeeling */ +#ifdef USE_OPENGL +else +{ + curpolygonoffset = 0; + while (spritesortcnt > 0) + { + bglDisable(GL_POLYGON_OFFSET_FILL); + drawsprite(--spritesortcnt); + } + bglDisable(GL_POLYGON_OFFSET_FILL); + while (maskwallcnt > 0) drawmaskwall(--maskwallcnt); +} +#endif - indrawroomsandmasks = 0; - enddrawing(); //}}} - if (usegoodalpha) +#ifdef USE_OPENGL + if ((r_depthpeeling) && (rendmode >= 3)) { bglEndList(); peelcompiling = 0; @@ -6351,40 +6159,30 @@ else bglAlphaFunc(GL_GREATER, 0.0f); i = 0; - while (i < numpeels) + while (i < r_peelscount) { if (i > 0) { - bglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); bglEnable(GL_FRAGMENT_PROGRAM_ARB); - bglActiveTextureARB(GL_TEXTURE1_ARB); - bglEnable(GL_TEXTURE_RECTANGLE_NV); - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, ztexture); + bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[(i - 1) % 2]); bglActiveTextureARB(GL_TEXTURE0_ARB); } - + if (i == (r_peelscount - 1)) + bglEnable(GL_BLEND); + + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]); + bglPushAttrib(GL_VIEWPORT_BIT); + bglViewport(0, 0, xdim, ydim); + + bglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); bglCallList(1); + bglPopAttrib(); + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + if (i > 0) - { - bglActiveTextureARB(GL_TEXTURE1_ARB); - bglDisable(GL_TEXTURE_RECTANGLE_NV); - bglActiveTextureARB(GL_TEXTURE0_ARB); - bglDisable(GL_FRAGMENT_PROGRAM_ARB); - } - - // save output to a peel - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, peels[i]); - bglCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0, xdim, ydim); - - if (i < (numpeels - 1)) - { - // save depth buffer - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, ztexture); - bglCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0, xdim, ydim); - } i++; } @@ -6392,7 +6190,6 @@ else bglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); bglEnable(GL_BLEND); - bglDisable(GL_ALPHA_TEST); bglDisable(GL_DEPTH_TEST); bglColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -6405,18 +6202,18 @@ else bglPushMatrix(); bglLoadIdentity(); - bglEnable(GL_TEXTURE_RECTANGLE_NV); + bglEnable(GL_TEXTURE_RECTANGLE); - if (curpeel == -1) + if (r_curpeel == -1) { - i = numpeels - 1; + i = r_peelscount - 1; while (i >= 0) drawpeel(i--); } else - drawpeel(curpeel); + drawpeel(r_curpeel); - bglDisable(GL_TEXTURE_RECTANGLE_NV); + bglDisable(GL_TEXTURE_RECTANGLE); bglEnable(GL_TEXTURE_2D); // restore the polymost projection @@ -6429,6 +6226,10 @@ else bglDeleteLists(1, 1); } +#endif + + indrawroomsandmasks = 0; + enddrawing(); //}}} } // @@ -7603,8 +7404,8 @@ if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); } #if defined(POLYMOST) && defined(USE_OPENGL) if (rendmode == 3) { - polymost_glinit(); polymost_glreset(); + polymost_glinit(); } if (rendmode == 4) polymer_glinit(); diff --git a/polymer/build/src/glbuild.c b/polymer/build/src/glbuild.c index 7876f6280..f4dcef032 100644 --- a/polymer/build/src/glbuild.c +++ b/polymer/build/src/glbuild.c @@ -117,10 +117,18 @@ void (APIENTRY * bglStencilFunc)(GLenum func, GLint ref, GLuint mask); void (APIENTRY * bglGenProgramsARB)(GLsizei, GLuint *); void (APIENTRY * bglBindProgramARB)(GLenum, GLuint); void (APIENTRY * bglProgramStringARB)(GLenum, GLenum, GLsizei, const GLvoid *); +void (APIENTRY * bglDeleteProgramsARB)(GLsizei n, const GLuint *programs); // Multitexturing void (APIENTRY * bglActiveTextureARB)(GLenum texture); +// Frame Buffer Objects +void (APIENTRY * bglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers); +void (APIENTRY * bglBindFramebufferEXT)(GLenum target, GLuint framebuffer); +void (APIENTRY * bglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLenum (APIENTRY * bglCheckFramebufferStatusEXT)(GLenum target); +void (APIENTRY * bglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers); + #ifdef RENDERTYPEWIN // Windows HGLRC (WINAPI * bwglCreateContext)(HDC); @@ -243,18 +251,18 @@ int loadgldriver(const char *driver) bglTranslatef = GETPROC("glTranslatef"); // Drawing - bglBegin = GETPROC("glBegin"); - bglEnd = GETPROC("glEnd"); - bglVertex2f = GETPROC("glVertex2f"); - bglVertex2i = GETPROC("glVertex2i"); - bglVertex3f = GETPROC("glVertex3f"); - bglVertex3d = GETPROC("glVertex3d"); - bglVertex3fv = GETPROC("glVertex3fv"); - bglVertex3dv = GETPROC("glVertex3dv"); - bglColor4f = GETPROC("glColor4f"); - bglColor4ub = GETPROC("glColor4ub"); - bglTexCoord2d = GETPROC("glTexCoord2d"); - bglTexCoord2f = GETPROC("glTexCoord2f"); + bglBegin = GETPROC("glBegin"); + bglEnd = GETPROC("glEnd"); + bglVertex2f = GETPROC("glVertex2f"); + bglVertex2i = GETPROC("glVertex2i"); + bglVertex3f = GETPROC("glVertex3f"); + bglVertex3d = GETPROC("glVertex3d"); + bglVertex3fv = GETPROC("glVertex3fv"); + bglVertex3dv = GETPROC("glVertex3dv"); + bglColor4f = GETPROC("glColor4f"); + bglColor4ub = GETPROC("glColor4ub"); + bglTexCoord2d = GETPROC("glTexCoord2d"); + bglTexCoord2f = GETPROC("glTexCoord2f"); // Lighting bglShadeModel = GETPROC("glShadeModel"); @@ -263,7 +271,7 @@ int loadgldriver(const char *driver) bglReadPixels = GETPROC("glReadPixels"); // Texture mapping - bglTexEnvf = GETPROC("glTexEnvf"); + bglTexEnvf = GETPROC("glTexEnvf"); bglGenTextures = GETPROC("glGenTextures"); bglDeleteTextures = GETPROC("glDeleteTextures"); bglBindTexture = GETPROC("glBindTexture"); @@ -282,10 +290,10 @@ int loadgldriver(const char *driver) bglFogfv = GETPROC("glFogfv"); // Display Lists - bglNewList = GETPROC("glNewList"); - bglEndList = GETPROC("glEndList"); - bglCallList = GETPROC("glCallList"); - bglDeleteLists = GETPROC("glDeleteLists"); + bglNewList = GETPROC("glNewList"); + bglEndList = GETPROC("glEndList"); + bglCallList = GETPROC("glCallList"); + bglDeleteLists = GETPROC("glDeleteLists"); // Vertex Arrays bglEnableClientState = GETPROC("glEnableClientState"); @@ -320,10 +328,18 @@ int loadglextensions(void) bglGenProgramsARB = GETPROCEXTSOFT("glGenProgramsARB"); bglBindProgramARB = GETPROCEXTSOFT("glBindProgramARB"); bglProgramStringARB = GETPROCEXTSOFT("glProgramStringARB"); + bglDeleteProgramsARB= GETPROCEXTSOFT("glDeleteProgramsARB"); // Multitexturing bglActiveTextureARB = GETPROCEXTSOFT("glActiveTextureARB"); + // Frame Buffer Objects + bglGenFramebuffersEXT = GETPROCEXTSOFT("glGenFramebuffersEXT"); + bglBindFramebufferEXT = GETPROCEXTSOFT("glBindFramebufferEXT"); + bglFramebufferTexture2DEXT = GETPROCEXTSOFT("glFramebufferTexture2DEXT"); + bglCheckFramebufferStatusEXT = GETPROCEXTSOFT("glCheckFramebufferStatusEXT"); + bglDeleteFramebuffersEXT = GETPROCEXTSOFT("glDeleteFramebuffersEXT"); + return err; } @@ -440,10 +456,18 @@ int unloadgldriver(void) bglGenProgramsARB = NULL; bglBindProgramARB = NULL; bglProgramStringARB = NULL; + bglDeleteProgramsARB= NULL; // Multitexturing bglActiveTextureARB = NULL; + // Frame Buffer Objects + bglGenFramebuffersEXT = NULL; + bglBindFramebufferEXT = NULL; + bglFramebufferTexture2DEXT = NULL; + bglCheckFramebufferStatusEXT = NULL; + bglDeleteFramebuffersEXT = NULL; + #ifdef RENDERTYPEWIN bwglCreateContext = NULL; bwglDeleteContext = NULL; diff --git a/polymer/build/src/mdsprite.c b/polymer/build/src/mdsprite.c index 59e5eff69..514e22407 100644 --- a/polymer/build/src/mdsprite.c +++ b/polymer/build/src/mdsprite.c @@ -1411,13 +1411,14 @@ if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } float al = 0.0; if (alphahackarray[globalpicnum] != 0) al=alphahackarray[globalpicnum]; - bglEnable(GL_BLEND); + if (!peelcompiling) + bglEnable(GL_BLEND); bglEnable(GL_ALPHA_TEST); bglAlphaFunc(GL_GREATER,al); } else { - if (tspr->cstat&2) bglEnable(GL_BLEND); else bglDisable(GL_BLEND); + if (tspr->cstat&2 && (!peelcompiling)) bglEnable(GL_BLEND); //else bglDisable(GL_BLEND); } bglColor4f(pc[0],pc[1],pc[2],pc[3]); //if (m->head.flags == 1337) @@ -1489,7 +1490,7 @@ if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } bglBindTexture(GL_TEXTURE_2D, i); //PLAG: delayed polygon-level sorted rendering - if (m->usesalpha && !(tspr->cstat & 1024) && !usegoodalpha) + if (m->usesalpha && !(tspr->cstat & 1024) && !r_depthpeeling) { indexes = malloc(sizeof(unsigned short) * s->numtris); maxdepths = malloc(sizeof(float) * s->numtris); @@ -1622,7 +1623,7 @@ if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } bglPopAttrib(); if (tspr->cstat&1024) { - bglDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS + bglDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS bglDepthRange(0.0,0.99999); } bglLoadIdentity(); @@ -2413,7 +2414,7 @@ if (grhalfxdown10x < 0) { mat[0] = -mat[0]; mat[4] = -mat[4]; mat[8] = -mat[8]; pc[1] *= (float)hictinting[globalpal].g / 255.0; pc[2] *= (float)hictinting[globalpal].b / 255.0; if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } else pc[3] = 1.0; - if (tspr->cstat&2) bglEnable(GL_BLEND); else bglDisable(GL_BLEND); + if (tspr->cstat&2 && (!peelcompiling)) bglEnable(GL_BLEND); //else bglDisable(GL_BLEND); //------------ //transform to Build coords @@ -2471,7 +2472,7 @@ if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } bglPopAttrib(); if (tspr->cstat&1024) { - bglDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS + bglDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS bglDepthRange(0.0,0.99999); } bglLoadIdentity(); diff --git a/polymer/build/src/polymost.c b/polymer/build/src/polymost.c index 967ab168a..cb50c21cc 100644 --- a/polymer/build/src/polymost.c +++ b/polymer/build/src/polymost.c @@ -127,10 +127,6 @@ static long lastglpolygonmode = 0; //FUK long glpolygonmode = 0; // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK long glwidescreen = 0; long glprojectionhacks = 1; -long usegoodalpha = 0; -long peelcompiling = 0; -long numpeels = 10; -long curpeel = -1; static GLuint polymosttext = 0; extern char nofog; @@ -139,6 +135,20 @@ long fullbrightloadingpass = 0; long fullbrightdrawingpass = 0; long shadeforfullbrightpass; +// Depth peeling control +long r_depthpeeling = 0; // cvar toggling general depth peeling usage +long r_peelscount = 5; // cvar controlling the number of peeling layers +long r_curpeel = -1; // cvar controlling the display of independant peeling layers +float curpolygonoffset; // internal polygon offset stack for drawing flat sprites to avoid depth fighting +long peelcompiling = 0; // internal control var to disable blending when compiling the peeling display list +long newpeelscount = 0; // temporary var for peels count changing during the game + +// Depth peeling data +GLuint ztexture[2]; // secondary Z-buffer identifier +GLuint *peels; // peels identifiers +GLuint *peelfbos; // peels FBOs identifiers +GLuint peelprogram; // ARBfp peeling fragment program + float fogresult; void fogcalc (const signed char *shade, const char *vis) @@ -596,11 +606,20 @@ void polymost_glreset () memset(gltexcachead,0,sizeof(gltexcachead)); glox1 = -1; -} -GLuint ztexture; -GLuint *peels; -GLuint peelprogram; + // Depth peeling cleanup + if (peels) + { + bglDeleteProgramsARB(1, &peelprogram); + bglDeleteFramebuffersEXT(r_peelscount, peelfbos); + bglDeleteTextures(r_peelscount, peels); + bglDeleteTextures(2, ztexture); + free(peels); + free(peelfbos); + + peels = NULL; + } +} // one-time initialisation of OpenGL for polymost void polymost_glinit() @@ -609,11 +628,13 @@ void polymost_glinit() int i; char peelprogramstring[] = "!!ARBfp1.0\n" + "OPTION ARB_fog_exp2;\n" + "OPTION ARB_fragment_program_shadow;\n" "TEMP texsample;\n" "TEMP depthresult;\n" "TEMP tempresult;\n" "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n" - "TEX depthresult, fragment.position, texture[1], RECT;\n" + "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n" "MUL tempresult, fragment.color, texsample;\n" "MUL tempresult.a, tempresult.a, depthresult.a;\n" "MOV result.color, tempresult;\n" @@ -652,33 +673,67 @@ void polymost_glinit() bglEnable(GL_MULTISAMPLE_ARB); } - //depth peeling init - if (usegoodalpha) + if (!glinfo.arbfp || !glinfo.depthtex || !glinfo.shadow || !glinfo.fbos || !glinfo.rect) { + OSD_Printf("Your OpenGL implementation doesn't support depth peeling. Forcing it off...\n", i); + r_depthpeeling = 0; + } + + //depth peeling initialization + if (r_depthpeeling) + { + if (newpeelscount) + { + r_peelscount = newpeelscount; + newpeelscount = 0; + } // create the secondary Z-buffer - bglGenTextures(1, &ztexture); - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, ztexture); - bglCopyTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + bglGenTextures(2, ztexture); - // create the various peeling layers - peels = malloc(numpeels * sizeof(GLuint)); - bglGenTextures(numpeels, peels); i = 0; - while (i < numpeels) + while (i < 2) { - bglBindTexture(GL_TEXTURE_RECTANGLE_NV, peels[i]); - bglCopyTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, 0, 0, xdim, ydim, 0); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); + bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[i]); + bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + + i++; + } + + // create the various peeling layers as well as the FBOs to render to them + peels = malloc(r_peelscount * sizeof(GLuint)); + bglGenTextures(r_peelscount, peels); + + peelfbos = malloc(r_peelscount * sizeof(GLuint)); + bglGenFramebuffersEXT(r_peelscount, peelfbos); + + i = 0; + while (i < r_peelscount) + { + bglBindTexture(GL_TEXTURE_RECTANGLE, peels[i]); + bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); + bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); + + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]); + bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, peels[i], 0); + if (i < (r_peelscount - 1)) + bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[i % 2], 0); + + if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) + { + OSD_Printf("FBO #%d initialization failed.\n", i); + } + + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); i++; } @@ -1556,7 +1611,7 @@ void drawpoly (double *dpx, double *dpy, long n, long method) } if ((!(method&3)) && (!fullbrightdrawingpass)) { - bglDisable(GL_BLEND); + //bglDisable(GL_BLEND); if (!peelcompiling) bglDisable(GL_ALPHA_TEST); } else { @@ -1753,11 +1808,12 @@ void drawpoly (double *dpx, double *dpy, long n, long method) { fullbrightdrawingpass = 2; shadeforfullbrightpass = globalshade; // save the current shade + bglFogf(GL_FOG_DENSITY,0.0f); // no fog globalshade = -128; // fullbright - bglDisable(GL_FOG); // no fog drawpoly(dpx, dpy, n_, method_); // draw them afterwards, then. :) - bglEnable(GL_FOG); globalshade = shadeforfullbrightpass; + fogcalc(&globalshade, &globalvisibility); + bglFogf(GL_FOG_DENSITY, fogresult); fullbrightdrawingpass = 0; } return; @@ -3510,6 +3566,12 @@ void polymost_drawrooms () #ifdef USE_OPENGL if (rendmode >= 3) { + if (r_depthpeeling) + { + bglNewList(1, GL_COMPILE); + peelcompiling = 1; + } + resizeglcheck(); //bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); @@ -3723,7 +3785,7 @@ void polymost_drawrooms () #ifdef USE_OPENGL if (rendmode >= 3) { - bglDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS + bglDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS //bglPolygonOffset(0,0); bglDepthRange(0.0,0.99999); //<- this is more widely supported than glPolygonOffset @@ -3959,9 +4021,13 @@ if (tspr->cstat&2) { if (!(tspr->cstat&512)) method = 2+4; else method = 3+4; } } break; } - //if (((tspr->cstat&2) || (gltexmayhavealpha(tspr->picnum,tspr->pal))) && ((tspr->cstat&48) != 0)) - // if (((tspr->cstat&2) || (gltexmayhavealpha(tspr->picnum,tspr->pal))) && ((tspr->cstat&48) != 0)) - // bglDepthMask(0); + if (((tspr->cstat&2) || (gltexmayhavealpha(tspr->picnum,tspr->pal))) && (peelcompiling)) + { + curpolygonoffset += 0.01f; + bglEnable(GL_POLYGON_OFFSET_FILL); + bglPolygonOffset(-curpolygonoffset, -curpolygonoffset); + //bglDepthMask(0); + } #endif switch ((globalorientation>>4)&3) @@ -5020,19 +5086,31 @@ static int osdcmd_polymostvars(const osdfuncparm_t *parm) else gltexmiplevel = val; return OSDCMD_OK; } - else if (!Bstrcasecmp(parm->name, "usegoodalpha")) { - if (showval) { OSD_Printf("usegoodalpha is %d\n", usegoodalpha); } - else usegoodalpha = (val != 0); + else if (!Bstrcasecmp(parm->name, "r_depthpeeling")) { + if (showval) { OSD_Printf("r_depthpeeling is %d\n", r_depthpeeling); } + else { + r_depthpeeling = (val != 0); + resetvideomode(); + if (setgamemode(fullscreen,xdim,ydim,bpp)) + OSD_Printf("restartvid: Reset failed...\n"); + } return OSDCMD_OK; } - else if (!Bstrcasecmp(parm->name, "numpeels")) { - if (showval) { OSD_Printf("numpeels is %d\n", numpeels); } - else numpeels = val; + else if (!Bstrcasecmp(parm->name, "r_peelscount")) { + if (showval) { OSD_Printf("r_peelscount is %d\n", r_peelscount); } + else if (val < 1) { OSD_Printf("Value out of range.\n"); } + else { + newpeelscount = val; + resetvideomode(); + if (setgamemode(fullscreen,xdim,ydim,bpp)) + OSD_Printf("restartvid: Reset failed...\n"); + } return OSDCMD_OK; } - else if (!Bstrcasecmp(parm->name, "curpeel")) { - if (showval) { OSD_Printf("curpeel is %d\n", curpeel); } - else curpeel = val; + else if (!Bstrcasecmp(parm->name, "r_curpeel")) { + if (showval) { OSD_Printf("r_curpeel is %d\n", r_curpeel); } + else if ((val < -1) || (val >= r_peelscount)) { OSD_Printf("Value out of range.\n"); } + else r_curpeel = val; return OSDCMD_OK; } else if (!Bstrcasecmp(parm->name, "glpolygonmode")) { @@ -5110,15 +5188,15 @@ void polymost_initosdfuncs(void) OSD_RegisterFunction("gltextureanisotropy", "gltextureanisotropy: changes the OpenGL texture anisotropy setting", gltextureanisotropy); OSD_RegisterFunction("gltexturemaxsize","gltexturemaxsize: changes the maximum OpenGL texture size limit",osdcmd_polymostvars); OSD_RegisterFunction("gltexturemiplevel","gltexturemiplevel: changes the highest OpenGL mipmap level used",osdcmd_polymostvars); - OSD_RegisterFunction("usegoodalpha","usegoodalpha: [OBSOLETE] enable/disable better looking OpenGL alpha hack",osdcmd_polymostvars); - OSD_RegisterFunction("numpeels","numpeels",osdcmd_polymostvars); - OSD_RegisterFunction("curpeel","curpeel: [OBSOLETE] enable/disable better looking OpenGL alpha hack",osdcmd_polymostvars); OSD_RegisterFunction("glpolygonmode","glpolygonmode: debugging feature",osdcmd_polymostvars); //FUK OSD_RegisterFunction("glusetexcache","glusetexcache: enable/disable OpenGL compressed texture cache",osdcmd_polymostvars); OSD_RegisterFunction("glusetexcachecompression","usetexcachecompression: enable/disable compression of files in the OpenGL compressed texture cache",osdcmd_polymostvars); OSD_RegisterFunction("glmultisample","glmultisample: sets the number of samples used for antialiasing (0 = off)",osdcmd_polymostvars); OSD_RegisterFunction("glnvmultisamplehint","glnvmultisamplehint: enable/disable Nvidia multisampling hinting",osdcmd_polymostvars); OSD_RegisterFunction("r_shadescale","r_shadescale: multiplier for lighting",osdcmd_polymostvars); + OSD_RegisterFunction("r_depthpeeling","r_depthpeeling: enable/disable order-independant transparency",osdcmd_polymostvars); + OSD_RegisterFunction("r_peelscount","r_peelscount: sets the number of depth layers for depth peeling",osdcmd_polymostvars); + OSD_RegisterFunction("r_curpeel","r_curpeel: allows to display one depth layer at a time (for development purposes)",osdcmd_polymostvars); #endif OSD_RegisterFunction("usemodels","usemodels: enable/disable model rendering in >8-bit mode",osdcmd_polymostvars); OSD_RegisterFunction("usehightile","usehightile: enable/disable hightile texture rendering in >8-bit mode",osdcmd_polymostvars); diff --git a/polymer/build/src/sdlayer.c b/polymer/build/src/sdlayer.c index 0f6a375cd..f1318695f 100644 --- a/polymer/build/src/sdlayer.c +++ b/polymer/build/src/sdlayer.c @@ -1049,6 +1049,27 @@ int setvideomode(int x, int y, int c, int fs) // supports nvidia's multisample hint extension glinfo.nvmultisamplehint = 1; } + else if (!Bstrcmp((char *)p2, "GL_ARB_fragment_program")) + { + glinfo.arbfp = 1; + } + else if (!Bstrcmp((char *)p2, "GL_ARB_depth_texture")) + { + glinfo.depthtex = 1; + } + else if (!Bstrcmp((char *)p2, "GL_ARB_shadow")) + { + glinfo.shadow = 1; + } + else if (!Bstrcmp((char *)p2, "GL_EXT_framebuffer_object")) + { + glinfo.fbos = 1; + } + else if (!Bstrcmp((char *)p2, "GL_NV_texture_rectangle") || + !Bstrcmp((char *)p2, "GL_EXT_texture_rectangle")) + { + glinfo.rect = 1; + } } Bfree(p); } diff --git a/polymer/build/src/winlayer.c b/polymer/build/src/winlayer.c index 66e94226c..ec8d943f1 100644 --- a/polymer/build/src/winlayer.c +++ b/polymer/build/src/winlayer.c @@ -2882,6 +2882,17 @@ static int SetupOpenGL(int width, int height, int bitspp) nofog = 1; if (!(warnonce&1)) initprintf("3dfx card detected: OpenGL fog disabled\n"); warnonce |= 1; + } else if (!Bstrcmp((char *)p2, "GL_ARB_fragment_program")) { + glinfo.arbfp = 1; + } else if (!Bstrcmp((char *)p2, "GL_ARB_depth_texture")) { + glinfo.depthtex = 1; + } else if (!Bstrcmp((char *)p2, "GL_ARB_shadow")) { + glinfo.shadow = 1; + } else if (!Bstrcmp((char *)p2, "GL_EXT_framebuffer_object")) { + glinfo.fbos = 1; + } else if (!Bstrcmp((char *)p2, "GL_NV_texture_rectangle") || + !Bstrcmp((char *)p2, "GL_EXT_texture_rectangle")) { + glinfo.rect = 1; } } Bfree(p); diff --git a/polymer/eduke32/source/config.c b/polymer/eduke32/source/config.c index a54d8ebca..dd63abf75 100644 --- a/polymer/eduke32/source/config.c +++ b/polymer/eduke32/source/config.c @@ -639,6 +639,9 @@ int32 CONFIG_ReadSetup(void) SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLUseCompressedTextureCache", &glusetexcache); SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLUseTextureCacheCompression", &glusetexcachecompression); + SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLDepthPeeling", &r_depthpeeling); + SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLPeelsCount", &r_peelscount); + dummy = usemodels; SCRIPT_GetNumber(scripthandle, "Screen Setup", "UseModels",&dummy); usemodels = dummy != 0; @@ -784,6 +787,8 @@ void CONFIG_WriteSetup(void) SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLUseTextureCacheCompression", glusetexcachecompression,false,false); SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLUseTextureCompr",glusetexcompr,false,false); SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLWidescreen",glwidescreen,false,false); + SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLDepthPeeling",r_depthpeeling,false,false); + SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLPeelsCount",r_peelscount,false,false); #endif #ifdef RENDERTYPEWIN SCRIPT_PutNumber(scripthandle, "Screen Setup", "MaxRefreshFreq",maxrefreshfreq,false,false);