From 278f2e9b6640d0b148a7c7f37343e8beabd93684 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 30 Aug 2014 14:10:55 +0100 Subject: [PATCH 01/11] Polyobject top/bottom texture + translucency polyobjects do have top/bottom textures, silly. And translucency. --- src/hardware/hw_main.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b9977968e..58aacf022 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1393,11 +1393,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } // check TOP TEXTURE - if (worldhigh < worldtop && texturetranslation[gr_sidedef->toptexture] -#ifdef POLYOBJECTS // polyobjects don't have top textures, silly. - && !gr_curline->polyseg -#endif - ) + if (worldhigh < worldtop && texturetranslation[gr_sidedef->toptexture]) { if (drawtextured) { @@ -1435,11 +1431,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } // check BOTTOM TEXTURE - if (worldlow > worldbottom && texturetranslation[gr_sidedef->bottomtexture] -#ifdef POLYOBJECTS // polyobjects don't have bottom textures, silly. - && !gr_curline->polyseg -#endif - ) //only if VISIBLE!!! + if (worldlow > worldbottom && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!! { if (drawtextured) { @@ -1646,6 +1638,17 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) blendmode = PF_Masked; break; } + +#ifdef POLYOBJECTS + if (gr_curline->polyseg && gr_curline->polyseg->translucency > 0) + { + if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn + return; + + blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf); + } +#endif + if (grTex->mipmap.flags & TF_TRANSPARENT) blendmode = PF_Translucent; From ae27ace7fef6467cfa99b38d026b36818f2fc156 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 30 Aug 2014 14:20:07 +0100 Subject: [PATCH 02/11] Polyobject translucency quick fix. I realise what I did before may cause FOF's in the same sector to not be drawn, if they were before. --- src/hardware/hw_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 58aacf022..93d0e2614 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1643,7 +1643,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (gr_curline->polyseg && gr_curline->polyseg->translucency > 0) { if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn - return; + { + Surf.FlatColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode + blendmode = PF_Masked; + } blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf); } From d96eaa768c02d140d536cda96aafd3b1887a0e34 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 30 Aug 2014 14:36:18 +0100 Subject: [PATCH 03/11] else added less redundancy. --- src/hardware/hw_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 93d0e2614..7e64243a4 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1647,8 +1647,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) Surf.FlatColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode blendmode = PF_Masked; } - - blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf); + else + blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf); } #endif From da2b6f2c01eb6c0085f675de2d97edfccd823297 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Wed, 3 Sep 2014 02:10:47 +0100 Subject: [PATCH 04/11] Fix certain textures with holes in see: CEZ1 skybox in linear filtermodes. --- src/hardware/hw_cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index c97e51616..3899b75b8 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -452,7 +452,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( if (format2bpp[grtex->mipmap.grInfo.format]==4) { - for (i = 3; i < blocksize; i += 4) + for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp { if (block[i] == 0) { From ca0f0bf2fdbd3f958ea90aa616a8c740d36349e2 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Thu, 4 Sep 2014 01:35:29 +0100 Subject: [PATCH 05/11] OpenGL Fade masks I think I've done this all right, someone correct me if I haven't. --- src/f_wipe.c | 14 +-- src/hardware/hw_cache.c | 104 +++++++++++++++++++++ src/hardware/hw_glob.h | 1 + src/hardware/hw_main.c | 37 ++++++-- src/hardware/hw_main.h | 2 +- src/hardware/r_opengl/ogl_win.c | 4 + src/hardware/r_opengl/r_opengl.c | 152 ++++++++++++++++++++++++++++++- src/hardware/r_opengl/r_opengl.h | 8 ++ 8 files changed, 299 insertions(+), 23 deletions(-) diff --git a/src/f_wipe.c b/src/f_wipe.c index 4b4ecd7e3..69e956216 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -172,15 +172,6 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) { */ static void F_DoWipe(fademask_t *fademask) { -#ifdef HWRENDER - /// \todo Mask wipes for OpenGL - if(rendermode != render_soft) - { - HWR_DoScreenWipe(); - return; - } -#endif - // Software mask wipe -- optimized; though it might not look like it! // Okay, to save you wondering *how* this is more optimized than the simpler // version that came before it... @@ -344,6 +335,11 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) I_Sleep(); lastwipetic = nowtime; +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_DoWipe(wipetype, wipeframe-1); // send in the wipe type and wipeframe because we need to cache the graphic + else +#endif F_DoWipe(fmask); I_OsPolling(); I_UpdateNoBlit(); diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 3899b75b8..4b2ff9f22 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1002,4 +1002,108 @@ GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum) return HWR_GetCachedGLPatchPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); } +// Need to do this because they aren't powers of 2 +static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 pblockheight, + lumpnum_t fademasklumpnum, UINT16 fmwidth, UINT16 fmheight) +{ + INT32 i,j; + fixed_t posx, posy, stepx, stepy; + UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock + UINT8 *flat; + UINT8 *dest, *src, texel; + RGBA_t col; + + // Place the flats data into flat + W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum), + PU_HWRCACHE, &flat)); + + stepy = ((INT32)SHORT(fmheight)<>FRACBITS)*SHORT(fmwidth)]; + for (i = 0; i < pblockwidth;i++) + { + // fademask bpp is always 1, and is used just for alpha + texel = src[(posx)>>FRACBITS]; + col = V_GetColor(texel); + *dest = col.s.red; // take the red level of the colour and use it for alpha, as fademasks do + + dest++; + posx += stepx; + } + posy += stepy; + } + + Z_Free(flat); +} + +static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) +{ + size_t size; + UINT16 fmheight = 0, fmwidth = 0; + UINT8 *block; // The fade mask's pixels + + // setup the texture info + grMipmap->grInfo.format = GR_TEXFMT_ALPHA_8; // put the correct alpha levels straight in so I don't need to convert it later + grMipmap->flags = 0; + + size = W_LumpLength(fademasklumpnum); + + switch (size) + { + // None of these are powers of 2, so I'll need to do what is done for textures and make them powers of 2 before they can be used + case 256000: // 640x400 + fmwidth = 640; + fmheight = 400; + break; + case 64000: // 320x200 + fmwidth = 320; + fmheight = 200; + break; + case 16000: // 160x100 + fmwidth = 160; + fmheight = 100; + break; + case 4000: // 80x50 (minimum) + fmwidth = 80; + fmheight = 50; + break; + default: // Bad lump + CONS_Alert(CONS_WARNING, "Fade mask lump of incorrect size, ignored\n"); // I should avoid this by checking the lumpnum in HWR_RunWipe + break; + } + + // Thankfully, this will still work for this scenario + HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo); + + grMipmap->width = blockwidth; + grMipmap->height = blockheight; + + block = MakeBlock(grMipmap); + + HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight); + + // I DO need to convert this because it isn't power of 2 and we need the alpha +} + + +void HWR_GetFadeMask(lumpnum_t fademasklumpnum) +{ + GLMipmap_t *grmip; + + grmip = &HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; + + if (!grmip->downloaded && !grmip->grInfo.data) + HWR_CacheFadeMask(grmip, fademasklumpnum); + + HWD.pfnSetTexture(grmip); + + // The system-memory data can be purged now. + Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); +} + #endif //HWRENDER diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index ee84e8b10..88786bc11 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -106,6 +106,7 @@ GLPatch_t *HWR_GetPic(lumpnum_t lumpnum); void HWR_SetPalette(RGBA_t *palette); GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); +void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7e64243a4..e832457c0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5419,7 +5419,7 @@ void HWR_StartScreenWipe(void) void HWR_EndScreenWipe(void) { - HWRWipeCounter = 1.0f; + HWRWipeCounter = 0.0f; //CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n"); HWD.pfnEndScreenWipe(); } @@ -5429,17 +5429,38 @@ void HWR_DrawIntermissionBG(void) HWD.pfnDrawIntermissionBG(); } -void HWR_DoScreenWipe(void) +void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) { - //CONS_Debug(DBG_RENDER, "In HWR_DoScreenWipe(). Alpha =%f\n", HWRWipeCounter); + static char lumpname[9] = "FADEmmss"; + lumpnum_t lumpnum; + size_t lsize; - HWD.pfnDoScreenWipe(HWRWipeCounter); + if (wipenum > 99 || scrnnum > 99) // not a valid wipe number + return; // shouldn't end up here really, the loop should've stopped running beforehand - // This works for all the cases in vanilla until fade masks get done - HWRWipeCounter -= 0.05f; // Go less opaque after + // puts the numbers into the lumpname + sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum); + lumpnum = W_CheckNumForName(lumpname); - if (HWRWipeCounter < 0) - HWRWipeCounter = 0; + if (lumpnum == LUMPERROR) // again, shouldn't be here really + return; + + lsize = W_LumpLength(lumpnum); + + if (!(lsize == 256000 || lsize == 64000 || lsize == 16000 || lsize == 4000)) + { + CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", lumpname); + return; // again, shouldn't get here if it is a bad size + } + + HWR_GetFadeMask(lumpnum); + + HWD.pfnDoScreenWipe(HWRWipeCounter); // Still send in wipecounter since old stuff might not support multitexturing + + HWRWipeCounter += 0.05f; // increase opacity of end screen + + if (HWRWipeCounter > 1.0f) + HWRWipeCounter = 1.0f; } #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 8d8b69e60..969946442 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -63,8 +63,8 @@ INT32 HWR_GetTextureUsed(void); void HWR_DoPostProcessor(player_t *player); void HWR_StartScreenWipe(void); void HWR_EndScreenWipe(void); -void HWR_DoScreenWipe(void); void HWR_DrawIntermissionBG(void); +void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum); // This stuff is put here so MD2's can use them UINT32 HWR_Lighting(INT32 light, UINT32 color, UINT32 fadecolor, boolean fogblockpoly, boolean plane); diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index daf37fe29..bfdc96d6a 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -366,6 +366,10 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) else maximumAnisotropy = 0; +#ifndef MINI_GL_COMPATIBILITY + SetupGLFunc13(); +#endif + screen_depth = (GLbyte)(lvid->bpp*8); if (screen_depth > 16) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index b853f084e..7590f49f4 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -157,6 +157,10 @@ float byteasfloat(UINT8 fbyte) static I_Error_t I_Error_GL = NULL; +#ifndef MINI_GL_COMPATIBILITY +static boolean gl13 = false; // whether we can use opengl 1.3 functions +#endif + // -----------------+ // DBG_Printf : Output error messages to debug log if DEBUG_TO_FILE is defined, @@ -263,6 +267,11 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...) /* GLU functions */ #define pgluBuild2DMipmaps gluBuild2DMipmaps #endif +#ifndef MINI_GL_COMPATIBILITY +/* 1.3 functions for multitexturing */ +#define pglActiveTexture, glActiveTexture; +#define pglMultiTexCoord2f, glMultiTexCoord2f; +#endif #else //!STATIC_OPENGL /* 1.0 functions */ @@ -387,6 +396,14 @@ static PFNglCopyTexImage2D pglCopyTexImage2D; /* GLU functions */ typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; + +#ifndef MINI_GL_COMPATIBILITY +/* 1.3 functions for multitexturing */ +typedef void (APIENTRY *PFNGLACTIVETEXTUREPROC) (GLenum); +static PFNGLACTIVETEXTUREPROC pglActiveTexture; +typedef void (APIENTRY *PFNGLMULTITEXCOORD2FPROC) (GLenum, GLfloat, GLfloat); +static PFNGLMULTITEXCOORD2FPROC pglMultiTexCoord2f; +#endif #endif #ifndef MINI_GL_COMPATIBILITY @@ -402,6 +419,14 @@ static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; #define GL_TEXTURE_MAX_LOD 0x813B #endif +/* 1.3 GL_TEXTUREi */ +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#endif +#ifndef GL_TEXTURE1 +#define GL_TEXTURE1 0x84C1 +#endif + #endif #ifdef MINI_GL_COMPATIBILITY @@ -492,6 +517,39 @@ boolean SetupGLfunc(void) return true; } +#ifndef MINI_GL_COMPATIBILITY +// This has to be done after the context is created so the version number can be obtained +boolean SetupGLFunc13(void) +{ +#ifndef STATIC_OPENGL +#define GETOPENGLFUNC(func, proc) \ + func = GetGLFunc(#proc); \ + if (!func) \ + { \ + DBG_Printf("failed to get OpenGL function: %s", #proc); \ + } \ + + const char *glversion = (const char *)pglGetString(GL_VERSION); + UINT32 majorversion = 0, minorversion = 0; + + if (glversion != NULL && sscanf((char *)glversion, "%u.%u", &majorversion, &minorversion) == 2) // There is a version number I can identify + { + if (majorversion > 1 || (majorversion == 1 && minorversion >= 3)) // Version of OpenGL is equal to or greater than 1.3 + { + // Get the functions + GETOPENGLFUNC(pglActiveTexture , glActiveTexture) + GETOPENGLFUNC(pglMultiTexCoord2f , glMultiTexCoord2f) + + gl13 = true; // This is now true, so the new fade mask stuff can be done, if OpenGL version is less than 1.3, it still uses the old fade stuff. + } + } +#undef GETOPENGLFUNC + +#endif + return true; +} +#endif + // -----------------+ // SetNoTexture : Disable texture // -----------------+ @@ -1234,6 +1292,23 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i] = (pImgData>>4)<<12; + tex[w*j+i] |= (255>>4)<<8; + tex[w*j+i] |= (255>>4)<<4; + tex[w*j+i] |= (255>>4); + pImgData++; + } + } + } else DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); #else @@ -1299,6 +1374,23 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } else DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); #endif @@ -2109,6 +2201,10 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) INT32 texsize = 2048; float xfix, yfix; +#ifndef MINI_GL_COMPATIBILITY + INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set +#endif + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; @@ -2122,8 +2218,8 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); - // Draw the screen on bottom to fade to - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + // Draw the original screen + pglBindTexture(GL_TEXTURE_2D, startScreenWipe); pglBegin(GL_QUADS); pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -2142,12 +2238,56 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) // Bottom right pglTexCoord2f(xfix, 0.0f); pglVertex3f(1.0f, -1.0f, 1.0f); + pglEnd(); SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); - // Draw the screen on top that fades. - pglBindTexture(GL_TEXTURE_2D, startScreenWipe); +#ifndef MINI_GL_COMPATIBILITY + if (gl13) + { + // Draw the end screen that fades in + pglActiveTexture(GL_TEXTURE0); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, endScreenWipe); + + pglActiveTexture(GL_TEXTURE1); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); + + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + pglBegin(GL_QUADS); + pglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + // Bottom left + pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, 0.0f); + pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 0.0f); + pglVertex3f(-1.0f, -1.0f, 1.0f); + + // Top left + pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, yfix); + pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 1.0f); + pglVertex3f(-1.0f, 1.0f, 1.0f); + + // Top right + pglMultiTexCoord2f(GL_TEXTURE0, xfix, yfix); + pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 1.0f); + pglVertex3f(1.0f, 1.0f, 1.0f); + + // Bottom right + pglMultiTexCoord2f(GL_TEXTURE0, xfix, 0.0f); + pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 0.0f); + pglVertex3f(1.0f, -1.0f, 1.0f); + pglEnd(); + + pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit + pglActiveTexture(GL_TEXTURE0); + } + else + { +#endif + // Draw the end screen that fades in + pglBindTexture(GL_TEXTURE_2D, endScreenWipe); pglBegin(GL_QUADS); pglColor4f(1.0f, 1.0f, 1.0f, alpha); @@ -2166,8 +2306,10 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha) // Bottom right pglTexCoord2f(xfix, 0.0f); pglVertex3f(1.0f, -1.0f, 1.0f); - pglEnd(); +#ifndef MINI_GL_COMPATIBILITY + } +#endif tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now } diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index fd018f4b1..f4d4f77e0 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -35,6 +35,13 @@ #else #include #include + +#ifndef MINI_GL_COMPATIBILITY +#ifdef STATIC_OPENGL // Because of the 1.3 functions, you'll need GLext to compile it if static +#define GL_GLEXT_PROTOTYPES +#include +#endif +#endif #endif #define _CREATE_DLL_ // necessary for Unix AND Windows @@ -66,6 +73,7 @@ boolean LoadGL(void); void *GetGLFunc(const char *proc); boolean SetupGLfunc(void); +boolean SetupGLFunc13(void); void Flush(void); INT32 isExtAvailable(const char *extension, const GLubyte *start); boolean SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepthBits); From bc0b5505a84596d6f4a437042dc57efda5c5957d Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Mon, 8 Sep 2014 00:55:32 +0100 Subject: [PATCH 06/11] OpenGL: Fix sky drawing sky positioning and scaling more correct compared to software. --- src/hardware/hw_main.c | 59 ++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e832457c0..77c56a734 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4355,7 +4355,7 @@ static void HWR_DrawSkyBackground(player_t *player) { FOutVector v[4]; angle_t angle; - float f; + float dimensionmultiply; // 3--2 // | /| @@ -4377,36 +4377,49 @@ static void HWR_DrawSkyBackground(player_t *player) // X - if (textures[skytexture]->width > 256) - angle = (angle_t)((float)(dup_viewangle + gr_xtoviewangle[0]) - /((float)textures[skytexture]->width/256.0f)) - %(ANGLE_90-1); - else - angle = (dup_viewangle + gr_xtoviewangle[0])%(ANGLE_90-1); + // NOTE: This doesn't work right with texture widths greater than 1024 + // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly + // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - f = (float)((textures[skytexture]->width/2) - * FIXED_TO_FLOAT(FINETANGENT((2048 - - ((INT32)angle>>(ANGLETOFINESHIFT + 1))) & FINEMASK))); + angle = (dup_viewangle + gr_xtoviewangle[0]); - v[0].sow = v[3].sow = 0.22f+(f)/(textures[skytexture]->width/2); - v[2].sow = v[1].sow = 0.22f+(f+(127))/(textures[skytexture]->width/2); + dimensionmultiply = ((float)textures[skytexture]->width/256.0f); + v[0].sow = v[3].sow = ((float) angle / ((ANGLE_90-1)*dimensionmultiply)); + v[2].sow = v[1].sow = (-1.0f/dimensionmultiply)+((float) angle / ((ANGLE_90-1)*dimensionmultiply)); // Y + angle = aimingangle; + + float aspectratio = (float)vid.width/(float)vid.height; + dimensionmultiply = ((float)textures[skytexture]->height/(128.0f*aspectratio)); + float angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; - if (textures[skytexture]->height > 256) - angle = (angle_t)((float)(aimingangle) - *(256.0f/(float)textures[skytexture]->height)) - %(ANGLE_90-1); // Just so that looking up and down scales right + // Middle of the sky should always be at angle 0 + // need to keep correct aspect ratio with X + if (atransform.flip) + { + // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously + v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); + v[0].tow = v[1].tow = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply)); + } else - angle = (aimingangle); + { + v[3].tow = v[2].tow = (-1.0f/dimensionmultiply)-(0.5f-(0.5f/dimensionmultiply)); + v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); + } - f = (float)((textures[skytexture]->height/2) - * FIXED_TO_FLOAT(FINETANGENT((2048 - - ((INT32)angle>>(ANGLETOFINESHIFT + 1))) & FINEMASK))); - - v[3].tow = v[2].tow = 0.22f+(f)/(textures[skytexture]->height/2); - v[0].tow = v[1].tow = 0.22f+(f+(127))/(textures[skytexture]->height/2); + if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa + { + angle = InvAngle(angle); + v[3].tow = v[2].tow += ((float) angle / angleturn); + v[0].tow = v[1].tow += ((float) angle / angleturn); + } + else + { + v[3].tow = v[2].tow -= ((float) angle / angleturn); + v[0].tow = v[1].tow -= ((float) angle / angleturn); + } HWD.pfnDrawPolygon(NULL, v, 4, 0); } From b2852ec0f44d22d96869a06cc921f8ab61e2dc95 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Mon, 8 Sep 2014 23:29:05 +0100 Subject: [PATCH 07/11] OpenGL: Sky culling Gets rid of stuff being drawn where the sky should be being drawn. --- src/hardware/hw_main.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 77c56a734..581a8bb71 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1286,6 +1286,25 @@ static void HWR_SplitFog(sector_t *sector, wallVert3D *wallVerts, FSurfaceInfo* HWR_AddTransparentWall(wallVerts, Surf, 0, PF_Translucent|PF_NoTexture, true, lightnum, colormap); } +// HWR_DrawSkyWalls +// Draw walls into the depth buffer so that anything behind is culled properly +static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top) +{ + HWD.pfnSetTexture(NULL); + // no texture + wallVerts[3].t = wallVerts[2].t = 0; + wallVerts[0].t = wallVerts[1].t = 0; + wallVerts[0].s = wallVerts[3].s = 0; + wallVerts[2].s = wallVerts[1].s = 0; + // set top/bottom coords + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall + HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL); + // PF_Invisible so it's not drawn into the colour buffer + // PF_NoTexture for no texture + // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer +} + // // HWR_StoreWallRange // A portion or all of a wall segment will be drawn, from startfrac to endfrac, @@ -1674,6 +1693,57 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) Surf.FlatColor.rgba = 0xffffffff; }*/ } + + // Isn't this just the most lovely mess + if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) + { + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + { + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); + // behind sector is not a thok barrier + else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + } + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + { + if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height + || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height + || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower + || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + } + } + // And now for sky floors! + if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) + { + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + { + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); + // behind sector is not a thok barrier + else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + } + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + { + if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height + || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height + || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher + || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + } + } } else { @@ -1713,6 +1783,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } } + + if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector + HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); + if (gr_frontsector->floorpic == skyflatnum) + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); } From cee8fff7b317a0d9e5191e67fd4e487f9ed27b3f Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Tue, 9 Sep 2014 01:59:19 +0100 Subject: [PATCH 08/11] Quick sky fix Avoid Z-Fighting on the depth wall with the regular walls to stop the possibility of regular walls being made partially invisible. --- src/hardware/hw_main.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 581a8bb71..da9c5f22f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1697,51 +1697,76 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // Isn't this just the most lovely mess if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) { + fixed_t depthwallheight; + + if (!gr_sidedef->toptexture) + depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + else + depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier { if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); + { + if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); + else + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); + } // behind sector is not a thok barrier else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); + // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on } else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not { if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); } else // neither sectors are thok barriers { if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, worldhigh, INT32_MAX); + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); } } // And now for sky floors! if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) { + fixed_t depthwallheight; + + if (!gr_sidedef->bottomtexture) + depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; + else + depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier { if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); + { + if (!gr_sidedef->toptexture) // Only extend up if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); + else + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); + } // behind sector is not a thok barrier else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); } else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not { if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); } else // neither sectors are thok barriers { if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldlow); + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); } } } From 987f9f5c261291dfa0d23587036d27a0426c851b Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Tue, 9 Sep 2014 23:57:12 +0100 Subject: [PATCH 09/11] Quick sky fix 2 walls not extending down when a thok barrier has top textures and both ceilings have sky. --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index da9c5f22f..621ec7237 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1699,7 +1699,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { fixed_t depthwallheight; - if (!gr_sidedef->toptexture) + if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; else depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; From 781dd16fa6c3a5174fe35961d2296e9f509c4205 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Wed, 10 Sep 2014 00:22:39 +0100 Subject: [PATCH 10/11] Fix THOK MD2's not rotating with camera Will also fix any other case that an mobj has a skin and a single frame. --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 0af7455ed..02f505351 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1230,7 +1230,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else p.z = FIXED_TO_FLOAT(spr->mobj->z); - if (spr->mobj->skin) + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) sprdef = &((skin_t *)spr->mobj->skin)->spritedef; else sprdef = &sprites[spr->mobj->sprite]; From 0c0ede6f18387003ca808bcb6d0ddc33a585f36f Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Mon, 27 Oct 2014 20:57:45 +0000 Subject: [PATCH 11/11] OpenGL: Polyobject Planes --- src/hardware/hw_main.c | 487 ++++++++++++++++++++++++++++++++++------- 1 file changed, 413 insertions(+), 74 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 621ec7237..f87af0741 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -66,6 +66,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #ifdef SORTING void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, fixed_t fixedheight, + INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); #else static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector); @@ -1695,78 +1697,81 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } // Isn't this just the most lovely mess - if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) + if (!gr_curline->polyseg) // Don't do it for polyobjects { - fixed_t depthwallheight; - - if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn - depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - else - depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + fixed_t depthwallheight; + + if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn + depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + else + depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier { - if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); - else - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + { + if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); + else + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); + } + // behind sector is not a thok barrier + else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); + // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on } - // behind sector is not a thok barrier - else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height - || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height - || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower - || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - } - // And now for sky floors! - if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->bottomtexture) - depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; - else - depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not { - if (!gr_sidedef->toptexture) // Only extend up if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); - else - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); + if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height + || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height + || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower + || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); } - // behind sector is not a thok barrier - else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + // And now for sky floors! + if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) { - if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height - || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height - || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher - || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + fixed_t depthwallheight; + + if (!gr_sidedef->bottomtexture) + depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; + else + depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; + + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + { + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + { + if (!gr_sidedef->toptexture) // Only extend up if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); + else + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); + } + // behind sector is not a thok barrier + else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + { + if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height + || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height + || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher + || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } } } } @@ -1809,10 +1814,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } - if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector - HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); - if (gr_frontsector->floorpic == skyflatnum) - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); + if (!gr_curline->polyseg) + { + if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector + HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX); + if (gr_frontsector->floorpic == skyflatnum) + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom); + } } @@ -2612,6 +2620,234 @@ static inline void HWR_AddPolyObjectSegs(void) Z_Free(pv1); Z_Free(gr_fakeline); } + +#ifdef POLYOBJECTS_PLANES +static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, fixed_t fixedheight, + FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, + UINT8 alpha, extracolormap_t *planecolormap) +{ + float height; //constant y for all points on the convex flat polygon + FOutVector *v3d; + INT32 i; + float flatxref,flatyref; + float fflatsize; + INT32 flatflag; + size_t len; + float scrollx = 0.0f, scrolly = 0.0f; + angle_t angle = 0; + FSurfaceInfo Surf; + fixed_t tempxsow, tempytow; + size_t nrPlaneVerts; + + static FOutVector *planeVerts = NULL; + static UINT16 numAllocedPlaneVerts = 0; + + nrPlaneVerts = polysector->numVertices; + + height = FIXED_TO_FLOAT(fixedheight); + + if (nrPlaneVerts < 3) //not even a triangle ? + return; + + if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + { + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); + return; + } + + // Allocate plane-vertex buffer if we need to + if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) + { + numAllocedPlaneVerts = (UINT16)nrPlaneVerts; + Z_Free(planeVerts); + Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts); + } + + len = W_LumpLength(lumpnum); + + switch (len) + { + case 4194304: // 2048x2048 lump + fflatsize = 2048.0f; + flatflag = 2047; + break; + case 1048576: // 1024x1024 lump + fflatsize = 1024.0f; + flatflag = 1023; + break; + case 262144:// 512x512 lump + fflatsize = 512.0f; + flatflag = 511; + break; + case 65536: // 256x256 lump + fflatsize = 256.0f; + flatflag = 255; + break; + case 16384: // 128x128 lump + fflatsize = 128.0f; + flatflag = 127; + break; + case 1024: // 32x32 lump + fflatsize = 32.0f; + flatflag = 31; + break; + default: // 64x64 lump + fflatsize = 64.0f; + flatflag = 63; + break; + } + + // reference point for flat texture coord for each vertex around the polygon + flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); + flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); + + // transform + v3d = planeVerts; + + if (FOFsector != NULL) + { + if (fixedheight == FOFsector->floorheight) // it's a floor + { + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; + } + else // it's a ceiling + { + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; + } + } + else if (gr_frontsector) + { + if (fixedheight < dup_viewz) // it's a floor + { + scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; + angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; + } + else // it's a ceiling + { + scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; + scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; + angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; + } + } + + if (angle) // Only needs to be done if there's an altered angle + { + // This needs to be done so that it scrolls in a different direction after rotation like software + tempxsow = FLOAT_TO_FIXED(scrollx); + tempytow = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + + // This needs to be done so everything aligns after rotation + // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does + tempxsow = FLOAT_TO_FIXED(flatxref); + tempytow = FLOAT_TO_FIXED(flatyref); + flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + } + + for (i = 0; i < nrPlaneVerts; i++,v3d++) + { + // Hurdler: add scrolling texture on floor/ceiling + v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations + v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + + // Need to rotate before translate + if (angle) // Only needs to be done if there's an altered angle + { + tempxsow = FLOAT_TO_FIXED(v3d->sow); + tempytow = FLOAT_TO_FIXED(v3d->tow); + v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); + v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); + } + + v3d->x = FIXED_TO_FLOAT(polysector->lines[i]->v1->x); + v3d->y = height; + v3d->z = FIXED_TO_FLOAT(polysector->lines[i]->v1->y); + } + + + if (planecolormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true); + + if (blendmode & PF_Translucent) + { + Surf.FlatColor.s.alpha = (UINT8)alpha; + blendmode |= PF_Modulated|PF_Occlude|PF_Clip; + } + else + blendmode |= PF_Masked|PF_Modulated|PF_Clip; + + HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode); +} + +static void HWR_AddPolyObjectPlanes(void) +{ + size_t i; + sector_t *polyobjsector; + + // Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves + // It should be okay because polyobjects should always be convex anyway + + for (i = 0; i < numpolys; i++) + { + polyobjsector = po_ptrs[i]->lines[0]->backsector; // the in-level polyobject sector + + if (!(po_ptrs[i]->flags & POF_RENDERPLANES)) // Only render planes when you should + continue; + + if (po_ptrs[i]->translucency >= NUMTRANSMAPS) + continue; + + if (polyobjsector->floorheight <= gr_frontsector->ceilingheight + && polyobjsector->floorheight >= gr_frontsector->floorheight + && (viewz < polyobjsector->floorheight)) + { + if (po_ptrs[i]->translucency > 0) + { + FSurfaceInfo Surf; + FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], polyobjsector->floorheight, + polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + } + else + { + HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum); + HWR_RenderPolyObjectPlane(po_ptrs[i], polyobjsector->floorheight, PF_Occlude, + polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector, 255, NULL); + } + } + + if (polyobjsector->ceilingheight >= gr_frontsector->floorheight + && polyobjsector->ceilingheight <= gr_frontsector->ceilingheight + && (viewz > polyobjsector->ceilingheight)) + { + if (po_ptrs[i]->translucency > 0) + { + FSurfaceInfo Surf; + FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); + HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], polyobjsector->ceilingheight, + polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL); + } + else + { + HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum); + HWR_RenderPolyObjectPlane(po_ptrs[i], polyobjsector->ceilingheight, PF_Occlude, + polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, + polyobjsector, 255, NULL); + } + } + } +} +#endif #endif // -----------------+ @@ -2922,8 +3158,13 @@ static void HWR_Subsector(size_t num) // Draw polyobject lines. HWR_AddPolyObjectSegs(); - // Draw polyobject planes - //HWR_AddPolyObjectPlanes(); +#ifdef POLYOBJECTS_PLANES + if (sub->validcount != validcount) // This validcount situation seems to let us know that the floors have already been drawn. + { + // Draw polyobject planes + HWR_AddPolyObjectPlanes(); + } +#endif } #endif @@ -3804,6 +4045,22 @@ typedef struct static size_t numplanes = 0; // a list of transparent floors to be drawn static planeinfo_t *planeinfo = NULL; +typedef struct +{ + polyobj_t *polysector; + fixed_t fixedheight; + INT32 lightlevel; + lumpnum_t lumpnum; + INT32 alpha; + sector_t *FOFSector; + FBITFIELD blend; + extracolormap_t *planecolormap; + INT32 drawcount; +} polyplaneinfo_t; + +static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn +static polyplaneinfo_t *polyplaneinfo = NULL; + #ifndef SORTING size_t numfloors = 0; #else @@ -3813,6 +4070,7 @@ size_t numfloors = 0; typedef struct gr_drawnode_s { planeinfo_t *plane; + polyplaneinfo_t *polyplane; wallinfo_t *wall; gr_vissprite_t *sprite; @@ -3853,6 +4111,35 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, numplanes++; } +// Adding this for now until I can create extrasubsector info for polyobjects +// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane +void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, + fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) +{ + static size_t allocedpolyplanes = 0; + + // Force realloc if buffer has been freed + if (!polyplaneinfo) + allocedpolyplanes = 0; + + if (allocedpolyplanes < numpolyplanes + 1) + { + allocedpolyplanes += MAX_TRANSPARENTFLOOR; + Z_Realloc(polyplaneinfo, allocedpolyplanes * sizeof (*polyplaneinfo), PU_LEVEL, &polyplaneinfo); + } + + polyplaneinfo[numpolyplanes].fixedheight = fixedheight; + polyplaneinfo[numpolyplanes].lightlevel = lightlevel; + polyplaneinfo[numpolyplanes].lumpnum = lumpnum; + polyplaneinfo[numpolyplanes].polysector = polysector; + polyplaneinfo[numpolyplanes].alpha = alpha; + polyplaneinfo[numpolyplanes].FOFSector = FOFSector; + polyplaneinfo[numpolyplanes].blend = blend; + polyplaneinfo[numpolyplanes].planecolormap = planecolormap; + polyplaneinfo[numpolyplanes].drawcount = drawcount++; + numpolyplanes++; +} + // // HWR_CreateDrawNodes // Creates and sorts a list of drawnodes for the scene being rendered. @@ -3865,12 +4152,13 @@ static void HWR_CreateDrawNodes(void) // Could this be optimized into _AddTransparentWall/_AddTransparentPlane? // Hell yes! But sort algorithm must be modified to use a linked list. gr_drawnode_t *sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes) + + (sizeof(polyplaneinfo_t)*numpolyplanes) + (sizeof(wallinfo_t)*numwalls) ,PU_STATIC, NULL); // todo: // However, in reality we shouldn't be re-copying and shifting all this information // that is already lying around. This should all be in some sort of linked list or lists. - size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numwalls), PU_STATIC, NULL); + size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); // If true, swap the draw order. boolean shift = false; @@ -3881,6 +4169,12 @@ static void HWR_CreateDrawNodes(void) sortindex[p] = p; } + for (i = 0; i < numpolyplanes; i++, p++) + { + sortnode[p].polyplane = &polyplaneinfo[i]; + sortindex[p] = p; + } + for (i = 0; i < numwalls; i++, p++) { sortnode[p].wall = &wallinfo[i]; @@ -3916,6 +4210,12 @@ static void HWR_CreateDrawNodes(void) if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz)) shift = true; } + if (sortnode[sortindex[prev]].polyplane) + { + // Plane (i) is further away than polyplane (prev) + if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz)) + shift = true; + } else if (sortnode[sortindex[prev]].wall) { // Plane (i) is further than wall (prev) @@ -3923,6 +4223,28 @@ static void HWR_CreateDrawNodes(void) shift = true; } } + else if (sortnode[sortindex[i]].polyplane) + { + // What are we comparing it with? + if (sortnode[sortindex[prev]].plane) + { + // Plane (i) is further away than plane (prev) + if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz)) + shift = true; + } + if (sortnode[sortindex[prev]].polyplane) + { + // Plane (i) is further away than polyplane (prev) + if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz)) + shift = true; + } + else if (sortnode[sortindex[prev]].wall) + { + // Plane (i) is further than wall (prev) + if (sortnode[sortindex[i]].polyplane->drawcount > sortnode[sortindex[prev]].wall->drawcount) + shift = true; + } + } else if (sortnode[sortindex[i]].wall) { // What are we comparing it with? @@ -3932,6 +4254,12 @@ static void HWR_CreateDrawNodes(void) if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].plane->drawcount) shift = true; } + if (sortnode[sortindex[prev]].polyplane) + { + // Wall (i) is further than polyplane(prev) + if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].polyplane->drawcount) + shift = true; + } else if (sortnode[sortindex[prev]].wall) { // Wall (i) is further than wall (prev) @@ -3968,6 +4296,16 @@ static void HWR_CreateDrawNodes(void) HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap); } + else if (sortnode[sortindex[i]].polyplane) + { + // We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes. + gr_frontsector = NULL; + + if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) + HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum); + HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, + sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + } else if (sortnode[sortindex[i]].wall) { if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture)) @@ -3979,6 +4317,7 @@ static void HWR_CreateDrawNodes(void) numwalls = 0; numplanes = 0; + numpolyplanes = 0; // No mem leaks, please. Z_Free(sortnode); @@ -4768,7 +5107,7 @@ if (0) #endif #ifdef SORTING - if (numplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything + if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } @@ -4998,12 +5337,12 @@ if (0) #endif #ifdef SORTING - if (numplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything + if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything { HWR_CreateDrawNodes(); } #else - if (numfloors || numwalls) + if (numfloors || numpolyplanes || numwalls) { HWD.pfnSetTransform(&atransform); if (numfloors)