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
This commit is contained in:
Plagman 2007-01-06 01:29:45 +00:00
parent 8a3ca3dbc4
commit 5a7cceb19d
11 changed files with 302 additions and 323 deletions

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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<spritesortcnt-gap;i++)
@ -6059,11 +6065,6 @@ if (!usegoodalpha)
}
}
if (usegoodalpha)
{
bglNewList(1, GL_COMPILE);
peelcompiling = 1;
}
begindrawing(); //{{{
/*for(i=spritesortcnt-1;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<spritesortcnt;i++)
{
if (!tspriteptr[i]) continue;
tspriteptr[j] = tspriteptr[i];
spritesx[j] = spritesx[i];
spritesy[j] = spritesy[i]; j++;
}
spritesortcnt = j;
for (i=maskwallcnt-1;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<maskwallcnt;i++)
{
if (maskwall[i] < 0) continue;
maskwall[j++] = maskwall[i];
}
maskwallcnt = j;
}
#endif
while ((spritesortcnt > 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;i<spritesortcnt;i++)
if (tspriteptr[i]->owner >= 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();

View file

@ -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;

View file

@ -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();

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);