diff --git a/src/gl/data/gl_setup.cpp b/src/gl/data/gl_setup.cpp index 5e6e0767b..c42a2c19c 100644 --- a/src/gl/data/gl_setup.cpp +++ b/src/gl/data/gl_setup.cpp @@ -413,7 +413,6 @@ static void InitVertexData() TArray * vt_sectorlists; int i,j,k; - unsigned int l; vt_sectorlists = new TArray[numvertexes]; @@ -436,15 +435,6 @@ static void InitVertexData() AddToVertex(sec, vt_sectorlists[v-vertexes]); if (sec->heightsec) AddToVertex(sec->heightsec, vt_sectorlists[v-vertexes]); - - for(l=0;lflags & FF_EXISTS)) continue; - if (rover->flags&FF_NOSHADE) continue; // FF_NOSHADE doesn't create any wall splits - - AddToVertex(rover->model, vt_sectorlists[v-vertexes]); - } } } } diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 15aa56da9..d7f46e07e 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -69,7 +69,7 @@ TArray gl_MatrixStack; void FRenderState::Reset() { mTextureEnabled = true; - mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; + mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true; currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true; mFogColor.d = -1; @@ -104,6 +104,7 @@ void FRenderState::Reset() bool FRenderState::ApplyShader() { + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; if (mSpecialEffect > EFF_NONE) { activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect); @@ -157,7 +158,6 @@ bool FRenderState::ApplyShader() else if (activeShader->currentglowstate) { // if glowing is on, disable it. - static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; activeShader->muGlowTopColor.Set(nulvec); activeShader->muGlowBottomColor.Set(nulvec); activeShader->muGlowTopPlane.Set(nulvec); @@ -165,6 +165,18 @@ bool FRenderState::ApplyShader() activeShader->currentglowstate = 0; } + if (mSplitEnabled) + { + activeShader->muSplitTopPlane.Set(mSplitTopPlane.vec); + activeShader->muSplitBottomPlane.Set(mSplitBottomPlane.vec); + activeShader->currentsplitstate = 1; + } + else + { + activeShader->muSplitTopPlane.Set(nulvec); + activeShader->muSplitBottomPlane.Set(nulvec); + } + if (mColormapState != activeShader->currentfixedcolormap) { float r, g, b; diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index aa24072c2..d46bb4996 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -46,6 +46,7 @@ class FRenderState bool mTextureEnabled; bool mFogEnabled; bool mGlowEnabled; + bool mSplitEnabled; bool mBrightmapEnabled; bool mColorMask[4]; bool currentColorMask[4]; @@ -72,6 +73,7 @@ class FRenderState FStateVec4 mCameraPos; FStateVec4 mGlowTop, mGlowBottom; FStateVec4 mGlowTopPlane, mGlowBottomPlane; + FStateVec4 mSplitTopPlane, mSplitBottomPlane; PalEntry mFogColor; PalEntry mObjectColor; FStateVec4 mDynColor; @@ -229,6 +231,11 @@ public: mGlowEnabled = on; } + void EnableSplit(bool on) + { + mSplitEnabled = on; + } + void SetLightIndex(int n) { mLightIndex = n; @@ -272,6 +279,12 @@ public: mGlowBottomPlane.Set(FIXED2FLOAT(bottom.a), FIXED2FLOAT(bottom.b), FIXED2FLOAT(bottom.ic), FIXED2FLOAT(bottom.d)); } + void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom) + { + mSplitTopPlane.Set(FIXED2FLOAT(top.a), FIXED2FLOAT(top.b), FIXED2FLOAT(top.ic), FIXED2FLOAT(top.d)); + mSplitBottomPlane.Set(FIXED2FLOAT(bottom.a), FIXED2FLOAT(bottom.b), FIXED2FLOAT(bottom.ic), FIXED2FLOAT(bottom.d)); + } + void SetDynLight(float r, float g, float b) { mDynColor.Set(r, g, b, 0); diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp index 7eeda5f3d..c020ab276 100644 --- a/src/gl/scene/gl_sky.cpp +++ b/src/gl/scene/gl_sky.cpp @@ -137,11 +137,12 @@ void GLSkyInfo::init(int sky1, PalEntry FadeColor) void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) { + int ptype = -1; FPortal *portal = sector->portals[plane]; if (portal != NULL) { if (GLPortal::instack[1 - plane]) return; - type = RENDERWALL_SECTORSTACK; + ptype = PORTALTYPE_SECTORSTACK; this->portal = portal; } else @@ -156,13 +157,13 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) { - type = RENDERWALL_SKYBOX; + ptype = PORTALTYPE_SKYBOX; skybox = skyboxx; } else { skyinfo.init(sector->sky, Colormap.FadeColor); - type = RENDERWALL_SKY; + ptype = PORTALTYPE_SKY; sky = UniqueSkies.Get(&skyinfo); } } @@ -170,12 +171,14 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) { if ((plane == sector_t::ceiling && viewz > sector->ceilingplane.d) || (plane == sector_t::floor && viewz < -sector->floorplane.d)) return; - type = RENDERWALL_PLANEMIRROR; + ptype = PORTALTYPE_PLANEMIRROR; planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->floorplane; } - else return; } - PutWall(0); + if (ptype != -1) + { + PutPortal(ptype); + } } @@ -189,22 +192,23 @@ void GLWall::SkyLine(line_t *line) { ASkyViewpoint * skyboxx = line->skybox; GLSkyInfo skyinfo; + int ptype; // JUSTHIT is used as an indicator that a skybox is in use. // This is to avoid recursion if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) { - type = RENDERWALL_SKYBOX; + ptype = PORTALTYPE_SKYBOX; skybox = skyboxx; } else { skyinfo.init(line->frontsector->sky, Colormap.FadeColor); - type = RENDERWALL_SKY; + ptype = PORTALTYPE_SKY; sky = UniqueSkies.Get(&skyinfo); } - PutWall(0); + PutPortal(ptype); } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 5b27d9435..d9ef91232 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -30,13 +30,7 @@ enum WallTypes RENDERWALL_M1S, RENDERWALL_M2S, RENDERWALL_BOTTOM, - RENDERWALL_SKY, RENDERWALL_FOGBOUNDARY, - RENDERWALL_HORIZON, - RENDERWALL_SKYBOX, - RENDERWALL_SECTORSTACK, - RENDERWALL_PLANEMIRROR, - RENDERWALL_MIRROR, RENDERWALL_MIRRORSURFACE, RENDERWALL_M2SNF, RENDERWALL_COLOR, @@ -44,6 +38,16 @@ enum WallTypes // Insert new types at the end! }; +enum PortalTypes +{ + PORTALTYPE_SKY, + PORTALTYPE_HORIZON, + PORTALTYPE_SKYBOX, + PORTALTYPE_SECTORSTACK, + PORTALTYPE_PLANEMIRROR, + PORTALTYPE_MIRROR, +}; + struct GLSeg { float x1,x2; @@ -85,7 +89,6 @@ struct GLSectorPlane }; - class GLWall { public: @@ -105,7 +108,6 @@ public: { RWF_BLANK = 0, RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here - RWF_GLOW = 2, RWF_NOSPLIT = 4, RWF_NORENDER = 8, }; @@ -126,6 +128,7 @@ public: fixed_t viewdistance; + TArray *lightlist; int lightlevel; BYTE type; BYTE flags; @@ -160,12 +163,14 @@ public: private: void CheckGlowing(); - void PutWall(bool translucent); + void PutWall(sector_t *sec, bool translucent); + void PutPortal(int ptype); void CheckTexturePosition(); void SetupLights(); bool PrepareLight(texcoord * tcs, ADynamicLight * light); void RenderWall(int textured, unsigned int *store = NULL); + void RenderTextured(int rflags); void FloodPlane(int pass); @@ -175,8 +180,6 @@ private: void SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); void SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - void Put3DWall(lightlist_t * lightlist, bool translucent); - void SplitWall(sector_t * frontsector, bool translucent); void LightPass(); void SetHorizon(vertex_t * ul, vertex_t * ur, vertex_t * ll, vertex_t * lr); bool DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index bbe36b71f..c8808e79b 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -96,57 +96,54 @@ void GLWall::CheckGlowing() // // //========================================================================== -void GLWall::PutWall(bool translucent) +void GLWall::PutWall(sector_t *sec, bool translucent) { - GLPortal * portal; int list; - static char passflag[]={ + static char passflag[] = { 0, //RENDERWALL_NONE, 1, //RENDERWALL_TOP, // unmasked 1, //RENDERWALL_M1S, // unmasked 2, //RENDERWALL_M2S, // depends on render and texture settings 1, //RENDERWALL_BOTTOM, // unmasked - 4, //RENDERWALL_SKYDOME, // special 3, //RENDERWALL_FOGBOUNDARY, // translucent - 4, //RENDERWALL_HORIZON, // special - 4, //RENDERWALL_SKYBOX, // special - 4, //RENDERWALL_SECTORSTACK, // special - 4, //RENDERWALL_PLANEMIRROR, // special - 4, //RENDERWALL_MIRROR, // special - 1, //RENDERWALL_MIRRORSURFACE, // only created here from RENDERWALL_MIRROR + 1, //RENDERWALL_MIRRORSURFACE, // only created from PORTALTYPE_MIRROR 2, //RENDERWALL_M2SNF, // depends on render and texture settings, no fog, used on mid texture lines with a fog boundary. 3, //RENDERWALL_COLOR, // translucent 2, //RENDERWALL_FFBLOCK // depends on render and texture settings }; - + + if (gltexture && gltexture->GetTransparent() && passflag[type] == 2) { translucent = true; } - if (gl_fixedcolormap) + if (gl_fixedcolormap) { // light planes don't get drawn with fullbright rendering - if (!gltexture && passflag[type]!=4) return; - + if (gltexture == NULL) return; Colormap.Clear(); } + else if (sec->e->XFloor.lightlist.Size() > 0 && gltexture != NULL) + { + lightlist = &sec->e->XFloor.lightlist; + } CheckGlowing(); if (translucent) // translucent walls { - viewdistance = P_AproxDistance( ((seg->linedef->v1->x+seg->linedef->v2->x)>>1) - viewx, - ((seg->linedef->v1->y+seg->linedef->v2->y)>>1) - viewy); + viewdistance = P_AproxDistance(((seg->linedef->v1->x + seg->linedef->v2->x) >> 1) - viewx, + ((seg->linedef->v1->y + seg->linedef->v2->y) >> 1) - viewy); gl_drawinfo->drawlists[GLDL_TRANSLUCENT].AddWall(this); } - else if (passflag[type]!=4) // non-translucent walls + else { bool masked; - masked = passflag[type]==1? false : (gltexture && gltexture->isMasked()); + masked = passflag[type] == 1 ? false : (gltexture && gltexture->isMasked()); if ((flags&GLWF_SKYHACK && type == RENDERWALL_M2S)) { @@ -159,18 +156,25 @@ void GLWall::PutWall(bool translucent) gl_drawinfo->drawlists[list].AddWall(this); } - else switch (type) + lightlist = NULL; +} + +void GLWall::PutPortal(int ptype) +{ + GLPortal * portal; + + switch (ptype) { // portals don't go into the draw list. // Instead they are added to the portal manager - case RENDERWALL_HORIZON: + case PORTALTYPE_HORIZON: horizon=UniqueHorizons.Get(horizon); portal=GLPortal::FindPortal(horizon); if (!portal) portal=new GLHorizonPortal(horizon); portal->AddLine(this); break; - case RENDERWALL_SKYBOX: + case PORTALTYPE_SKYBOX: portal = GLPortal::FindPortal(skybox); if (!portal) { @@ -181,12 +185,12 @@ void GLWall::PutWall(bool translucent) portal->AddLine(this); break; - case RENDERWALL_SECTORSTACK: + case PORTALTYPE_SECTORSTACK: portal = this->portal->GetGLPortal(); portal->AddLine(this); break; - case RENDERWALL_PLANEMIRROR: + case PORTALTYPE_PLANEMIRROR: if (GLPortal::PlaneMirrorMode * planemirror->c <=0) { //@sync-portal @@ -197,7 +201,7 @@ void GLWall::PutWall(bool translucent) } break; - case RENDERWALL_MIRROR: + case PORTALTYPE_MIRROR: portal=GLPortal::FindPortal(seg->linedef); if (!portal) portal=new GLMirrorPortal(seg->linedef); portal->AddLine(this); @@ -209,7 +213,7 @@ void GLWall::PutWall(bool translucent) } break; - case RENDERWALL_SKY: + case PORTALTYPE_SKY: portal=GLPortal::FindPortal(sky); if (!portal) portal=new GLSkyPortal(sky); portal->AddLine(this); @@ -217,222 +221,6 @@ void GLWall::PutWall(bool translucent) } } -//========================================================================== -// -// Sets 3D-floor lighting info -// -//========================================================================== - -void GLWall::Put3DWall(lightlist_t * lightlist, bool translucent) -{ - // only modify the light level if it doesn't originate from the seg's frontsector. This is to account for light transferring effects - if (lightlist->p_lightlevel != &seg->sidedef->sector->lightlevel) - { - lightlevel = gl_ClampLight(*lightlist->p_lightlevel); - } - // relative light won't get changed here. It is constant across the entire wall. - - Colormap.CopyFrom3DLight(lightlist); - PutWall(translucent); -} - -//========================================================================== -// -// Splits a wall vertically if a 3D-floor -// creates different lighting across the wall -// -//========================================================================== - -void GLWall::SplitWall(sector_t * frontsector, bool translucent) -{ - GLWall copyWall1,copyWall2; - float maplightbottomleft; - float maplightbottomright; - unsigned int i; - int origlight = lightlevel; - TArray & lightlist=frontsector->e->XFloor.lightlist; - - if (glseg.x1==glseg.x2 && glseg.y1==glseg.y2) - { - return; - } - ::SplitWall.Clock(); - -#ifdef _DEBUG - if (seg->linedef-lines==1) - { - int a = 0; - } -#endif - - if (lightlist.Size()>1) - { - for(i=0;i=ztop[0] && maplightbottomright>=ztop[1]) - { - continue; - } - - // check for an intersection with the upper plane - if ((maplightbottomleftztop[1]) || - (maplightbottomleft>ztop[0] && maplightbottomright(fabsf(glseg.x2-glseg.x1), fabsf(glseg.y2-glseg.y2)); - - float dch=ztop[1]-ztop[0]; - float dfh=maplightbottomright-maplightbottomleft; - float coeff= (ztop[0]-maplightbottomleft)/(dfh-dch); - - // check for inaccuracies - let's be a little generous here! - if (coeff*clen<.1f) - { - maplightbottomleft=ztop[0]; - } - else if (coeff*clen>clen-.1f) - { - maplightbottomright=ztop[1]; - } - else - { - // split the wall in 2 at the intersection and recursively split both halves - copyWall1=copyWall2=*this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2-glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2-glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1]-ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1]-zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright-glseg.fracleft); - copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u-uplft.u); - copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v-uplft.v); - copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u-lolft.u); - copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v-lolft.v); - - ::SplitWall.Unclock(); - - copyWall1.SplitWall(frontsector, translucent); - copyWall2.SplitWall(frontsector, translucent); - return; - } - } - - // check for an intersection with the lower plane - if ((maplightbottomleftzbottom[1]) || - (maplightbottomleft>zbottom[0] && maplightbottomright(fabsf(glseg.x2-glseg.x1), fabsf(glseg.y2-glseg.y2)); - - float dch=zbottom[1]-zbottom[0]; - float dfh=maplightbottomright-maplightbottomleft; - float coeff= (zbottom[0]-maplightbottomleft)/(dfh-dch); - - // check for inaccuracies - let's be a little generous here because there's - // some conversions between floats and fixed_t's involved - if (coeff*clen<.1f) - { - maplightbottomleft=zbottom[0]; - } - else if (coeff*clen>clen-.1f) - { - maplightbottomright=zbottom[1]; - } - else - { - // split the wall in 2 at the intersection and recursively split both halves - copyWall1=copyWall2=*this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2-glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2-glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1]-ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1]-zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright-glseg.fracleft); - copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u-uplft.u); - copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v-uplft.v); - copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u-lolft.u); - copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v-lolft.v); - - ::SplitWall.Unclock(); - - copyWall1.SplitWall(frontsector, translucent); - copyWall2.SplitWall(frontsector, translucent); - return; - } - } - - // 3D floor is completely within this light - if (maplightbottomleft<=zbottom[0] && maplightbottomright<=zbottom[1]) - { - // These values must not be destroyed! - int ll=lightlevel; - FColormap lc=Colormap; - - Put3DWall(&lightlist[i], translucent); - - lightlevel=ll; - Colormap=lc; - - ::SplitWall.Unclock(); - - return; - } - - if (maplightbottomleft<=ztop[0] && maplightbottomright<=ztop[1] && - (maplightbottomleft!=ztop[0] || maplightbottomright!=ztop[1])) - { - copyWall1=*this; - - copyWall1.flags |= GLWF_NOSPLITLOWER; - flags |= GLWF_NOSPLITUPPER; - ztop[0]=copyWall1.zbottom[0]=maplightbottomleft; - ztop[1]=copyWall1.zbottom[1]=maplightbottomright; - uplft.v=copyWall1.lolft.v=copyWall1.uplft.v+ - (maplightbottomleft-copyWall1.ztop[0])*(copyWall1.lolft.v-copyWall1.uplft.v)/(zbottom[0]-copyWall1.ztop[0]); - uprgt.v=copyWall1.lorgt.v=copyWall1.uprgt.v+ - (maplightbottomright-copyWall1.ztop[1])*(copyWall1.lorgt.v-copyWall1.uprgt.v)/(zbottom[1]-copyWall1.ztop[1]); - copyWall1.Put3DWall(&lightlist[i], translucent); - } - if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1]) - { - ::SplitWall.Unclock(); - return; - } - } - } - - // These values must not be destroyed! - int ll=lightlevel; - FColormap lc=Colormap; - - Put3DWall(&lightlist[lightlist.Size()-1], translucent); - - lightlevel=ll; - Colormap=lc; - flags &= ~GLWF_NOSPLITUPPER; - ::SplitWall.Unclock(); -} - - //========================================================================== // // @@ -458,7 +246,6 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) } else { - type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, true); hi.lightlevel = gl_ClampLight(fs->GetCeilingLight()); hi.colormap = fs->ColorMap; @@ -473,7 +260,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) if (gl_fixedcolormap) hi.colormap.Clear(); horizon = &hi; - PutWall(0); + PutPortal(PORTALTYPE_HORIZON); } ztop[1] = ztop[0] = zbottom[0]; } @@ -487,7 +274,6 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) } else { - type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, false); hi.lightlevel = gl_ClampLight(fs->GetFloorLight()); hi.colormap = fs->ColorMap; @@ -502,7 +288,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) if (gl_fixedcolormap) hi.colormap.Clear(); horizon = &hi; - PutWall(0); + PutPortal(PORTALTYPE_HORIZON); } } return true; @@ -712,7 +498,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, gltexture->GetTexCoordInfo(&tci, seg->sidedef->GetTextureXScale(texpos), seg->sidedef->GetTextureYScale(texpos)); - type = (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) ? RENDERWALL_MIRROR : _type; + type = _type; float floatceilingref = FIXED2FLOAT(ceilingrefheight + tci.RowOffset(seg->sidedef->GetTextureYOffset(texpos))); if (peg) floatceilingref += tci.mRenderHeight - FIXED2FLOAT(lh + v_offset); @@ -720,13 +506,16 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, if (!SetWallCoordinates(seg, &tci, floatceilingref, topleft, topright, bottomleft, bottomright, seg->sidedef->GetTextureXOffset(texpos))) return; - CheckTexturePosition(); - - // Add this wall to the render list - sector_t * sec = sub? sub->sector : seg->frontsector; - - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(false); - else SplitWall(sec, false); + if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) + { + PutPortal(PORTALTYPE_MIRROR); + } + else + { + CheckTexturePosition(); + // Add this wall to the render list + PutWall(sub ? sub->sector : seg->frontsector, false); + } glseg=glsave; flags&=~GLT_CLAMPY; @@ -924,12 +713,15 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, { flags |= GLWF_NOSPLITUPPER|GLWF_NOSPLITLOWER; type=RENDERWALL_FOGBOUNDARY; - PutWall(true); - if (!gltexture) + FMaterial *savetex = gltexture; + gltexture = NULL; + PutWall(seg->frontsector, true); + if (!savetex) { flags &= ~(GLWF_NOSPLITUPPER|GLWF_NOSPLITLOWER); return; } + gltexture = savetex; type=RENDERWALL_M2SNF; } else type=RENDERWALL_M2S; @@ -1014,8 +806,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // Draw the stuff // // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) split.PutWall(translucent); - else split.SplitWall(realfront, translucent); + split.PutWall(realfront, translucent); t=1; } @@ -1023,13 +814,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, } else { - // - // - // Draw the stuff without splitting - // - // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(translucent); - else SplitWall(realfront, translucent); + PutWall(realfront, translucent); } alpha=1.0f; } @@ -1137,11 +922,8 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, RenderStyle=STYLE_Normal; translucent=false; } - - sector_t * sec = sub? sub->sector : seg->frontsector; - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(translucent); - else SplitWall(sec, translucent); + PutWall(sub? sub->sector : seg->frontsector, translucent); alpha=1.0f; lightlevel = savelight; @@ -1476,6 +1258,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) Colormap = frontsector->ColorMap; flags = 0; dynlightindex = UINT_MAX; + lightlist = NULL; int rel = 0; int orglightlevel = gl_ClampLight(frontsector->lightlevel); @@ -1768,7 +1551,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * type = RENDERWALL_BOTTOM; gltexture->GetTexCoordInfo(&tci, FRACUNIT, FRACUNIT); SetWallCoordinates(seg, &tci, FIXED2FLOAT(bfh), bfh, bfh, ffh, ffh, 0); - PutWall(false); + PutWall(seg->frontsector, false); } } } diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index ce14e16d3..cd404f4c9 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -182,11 +182,6 @@ void GLWall::RenderWall(int textured, unsigned int *store) tcs[1]=uplft; tcs[2]=uprgt; tcs[3]=lorgt; - if ((flags&GLWF_GLOW) && (textured & RWF_GLOW)) - { - gl_RenderState.SetGlowPlanes(topplane, bottomplane); - gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); - } if (!(textured & RWF_NORENDER)) { @@ -306,6 +301,66 @@ void GLWall::RenderMirrorSurface() } } +//========================================================================== +// +// +// +//========================================================================== + +void GLWall::RenderTextured(int rflags) +{ + int tmode = gl_RenderState.GetTextureMode(); + int rel = getExtraLight(); + + if (flags & GLWF_GLOW) + { + gl_RenderState.EnableGlow(true); + gl_RenderState.SetGlowPlanes(topplane, bottomplane); + gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); + } + gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); + + if (type == RENDERWALL_M2SNF) + { + if (flags & GLT_CLAMPY) + { + if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); + } + gl_SetFog(255, 0, NULL, false); + } + + float absalpha = fabsf(alpha); + if (lightlist == NULL) + { + gl_SetColor(lightlevel, rel, Colormap, absalpha); + if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); + RenderWall(rflags); + } + else + { + gl_RenderState.EnableSplit(true); + glEnable(GL_CLIP_DISTANCE3); + glEnable(GL_CLIP_DISTANCE4); + + for (unsigned i = 0; i < lightlist->Size(); i++) + { + int thisll = (*lightlist)[i].caster != NULL? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + FColormap thiscm; + thiscm.FadeColor = Colormap.FadeColor; + thiscm.CopyFrom3DLight(&(*lightlist)[i]); + gl_SetColor(thisll, rel, thiscm, absalpha); + if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add); + gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane); + RenderWall(rflags); + } + + glDisable(GL_CLIP_DISTANCE3); + glDisable(GL_CLIP_DISTANCE4); + gl_RenderState.EnableSplit(false); + } + gl_RenderState.SetTextureMode(tmode); + gl_RenderState.EnableGlow(false); +} //========================================================================== // @@ -315,57 +370,27 @@ void GLWall::RenderMirrorSurface() void GLWall::RenderTranslucentWall() { - bool transparent = gltexture? gltexture->GetTransparent() : false; - - // currently the only modes possible are solid, additive or translucent - // and until that changes I won't fix this code for the new blending modes! - bool isadditive = RenderStyle == STYLE_Add; - - if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) + if (gltexture) { - SetupLights(); + if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) + { + SetupLights(); + } + if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); + RenderTextured(RWF_TEXTURED | RWF_NOSPLIT); + if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - - if (!transparent) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); - else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); - - int extra; - if (gltexture) - { - gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); - gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); - extra = getExtraLight(); - } - else - { - gl_RenderState.EnableTexture(false); - extra = 0; - } - int tmode = gl_RenderState.GetTextureMode(); - - gl_SetColor(lightlevel, extra, Colormap, fabsf(alpha)); - if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, extra, &Colormap, isadditive); else { - if (flags & GLT_CLAMPY) - { - if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); - } - gl_SetFog(255, 0, NULL, false); - } - - RenderWall(RWF_TEXTURED|RWF_NOSPLIT); - - // restore default settings - if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - if (!gltexture) - { + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + gl_SetColor(lightlevel, 0, Colormap, fabsf(alpha)); + gl_SetFog(lightlevel, 0, &Colormap, RenderStyle == STYLE_Add); + gl_RenderState.EnableTexture(false); + RenderWall(RWF_NOSPLIT); gl_RenderState.EnableTexture(true); } - gl_RenderState.EnableGlow(false); - gl_RenderState.SetTextureMode(tmode); } //========================================================================== @@ -375,17 +400,6 @@ void GLWall::RenderTranslucentWall() //========================================================================== void GLWall::Draw(int pass) { - int rel; - int tmode; - -#ifdef _DEBUG - if (seg->linedef-lines==879) - { - int a = 0; - } -#endif - - switch (pass) { case GLPASS_LIGHTSONLY: @@ -396,28 +410,11 @@ void GLWall::Draw(int pass) SetupLights(); // fall through case GLPASS_PLAIN: - rel = rellight + getExtraLight(); - gl_SetColor(lightlevel, rel, Colormap,1.0f); - tmode = gl_RenderState.GetTextureMode(); - if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false); - else - { - if (flags & GLT_CLAMPY) - { - if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); - } - gl_SetFog(255, 0, NULL, false); - } - gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); - gl_RenderState.SetMaterial(gltexture, flags & 3, false, -1, false); - RenderWall(RWF_TEXTURED|RWF_GLOW); - gl_RenderState.EnableGlow(false); - gl_RenderState.SetTextureMode(tmode); + RenderTextured(RWF_TEXTURED); break; case GLPASS_TRANSLUCENT: - switch (type) { case RENDERWALL_MIRRORSURFACE: diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 2955cf7c8..aa8dfac2b 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -216,6 +216,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muGlowTopColor.Init(hShader, "uGlowTopColor"); muGlowBottomPlane.Init(hShader, "uGlowBottomPlane"); muGlowTopPlane.Init(hShader, "uGlowTopPlane"); + muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); + muSplitTopPlane.Init(hShader, "uSplitTopPlane"); muFixedColormap.Init(hShader, "uFixedColormap"); muInterpolationFactor.Init(hShader, "uInterpolationFactor"); muClipHeightTop.Init(hShader, "uClipHeightTop"); diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index c5baceceb..cf6480d9b 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -218,6 +218,8 @@ class FShader FUniform4f muGlowTopColor; FUniform4f muGlowBottomPlane; FUniform4f muGlowTopPlane; + FUniform4f muSplitBottomPlane; + FUniform4f muSplitTopPlane; FBufferedUniform1f muInterpolationFactor; FBufferedUniform1f muClipHeightTop; FBufferedUniform1f muClipHeightBottom; @@ -233,6 +235,7 @@ public: int fakevb_index; private: int currentglowstate; + int currentsplitstate; int currentfixedcolormap; bool currentTextureMatrixState; bool currentModelMatrixState; @@ -243,6 +246,7 @@ public: { hShader = hVertProg = hFragProg = 0; currentglowstate = 0; + currentsplitstate = 0; currentfixedcolormap = 0; currentTextureMatrixState = true; // by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. currentModelMatrixState = true; diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 2e7d0f1e0..3fd718ff7 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -174,7 +174,7 @@ void gl_LoadExtensions() void gl_PrintStartupLog() { int v = 0; - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &v); + if (gl.version >= 3.2) glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &v); Printf ("GL_VENDOR: %s\n", glGetString(GL_VENDOR)); Printf ("GL_RENDERER: %s\n", glGetString(GL_RENDERER)); diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 48c21dde2..545607ea1 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -16,7 +16,7 @@ #include "gl/utility/gl_convert.h" -glcycle_t RenderWall,SetupWall,ClipWall,SplitWall; +glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; glcycle_t RenderSprite,SetupSprite; glcycle_t All, Finish, PortalAll, Bsp; @@ -91,7 +91,6 @@ void ResetProfilingData() ProcessAll.Reset(); RenderWall.Reset(); SetupWall.Reset(); - SplitWall.Reset(); ClipWall.Reset(); RenderFlat.Reset(); SetupFlat.Reset(); @@ -111,15 +110,15 @@ void ResetProfilingData() static void AppendRenderTimes(FString &str) { - double setupwall = SetupWall.TimeMS() - SplitWall.TimeMS(); + double setupwall = SetupWall.TimeMS(); double clipwall = ClipWall.TimeMS() - SetupWall.TimeMS(); double bsp = Bsp.TimeMS() - ClipWall.TimeMS() - SetupFlat.TimeMS() - SetupSprite.TimeMS(); - str.AppendFormat("W: Render=%2.3f, Split = %2.3f, Setup=%2.3f, Clip=%2.3f\n" + str.AppendFormat("W: Render=%2.3f, Setup=%2.3f, Clip=%2.3f\n" "F: Render=%2.3f, Setup=%2.3f\n" "S: Render=%2.3f, Setup=%2.3f\n" "All=%2.3f, Render=%2.3f, Setup=%2.3f, BSP = %2.3f, Portal=%2.3f, Drawcalls=%2.3f, Finish=%2.3f\n", - RenderWall.TimeMS(), SplitWall.TimeMS(), setupwall, clipwall, RenderFlat.TimeMS(), SetupFlat.TimeMS(), + RenderWall.TimeMS(), setupwall, clipwall, RenderFlat.TimeMS(), SetupFlat.TimeMS(), RenderSprite.TimeMS(), SetupSprite.TimeMS(), All.TimeMS() + Finish.TimeMS(), RenderAll.TimeMS(), ProcessAll.TimeMS(), bsp, PortalAll.TimeMS(), drawcalls.TimeMS(), Finish.TimeMS()); } diff --git a/src/gl/utility/gl_clock.h b/src/gl/utility/gl_clock.h index 46a01d1e4..4d5163d86 100644 --- a/src/gl/utility/gl_clock.h +++ b/src/gl/utility/gl_clock.h @@ -102,7 +102,7 @@ private: #endif // __APPLE__ -extern glcycle_t RenderWall,SetupWall,ClipWall,SplitWall; +extern glcycle_t RenderWall,SetupWall,ClipWall; extern glcycle_t RenderFlat,SetupFlat; extern glcycle_t RenderSprite,SetupSprite; extern glcycle_t All, Finish, PortalAll, Bsp; diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 827644eea..1c6aebe47 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -29,6 +29,12 @@ void main() glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y; glowdist.y = worldcoord.y + ((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z); + + if (uSplitBottomPlane.z != 0) + { + gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; + gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); + } #endif #ifdef SPHEREMAP @@ -56,4 +62,5 @@ void main() gl_ClipDistance[1] = worldcoord.y - uClipSplit.x; gl_ClipDistance[2] = uClipSplit.y - worldcoord.y; + }