diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 0f75ba4676..18d96c9b28 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -588,6 +588,7 @@ bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog) int list = list_indices[masked][foggy]; auto newflat = dldrawlists[list].NewFlat(); *newflat = *flat; + newflat->vboindex = -1; // don't use the vertex buffer with legacy lights to ensure all passes use the same render logic. return true; } diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index 335c7740ca..cd7549aa8a 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -125,6 +125,8 @@ void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count) FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) : FVertexBuffer(!gl.legacyMode), FFlatVertexGenerator(width, height) { + ibo_id = 0; + if (gl.buffermethod != BM_LEGACY) glGenBuffers(1, &ibo_id); switch (gl.buffermethod) { case BM_PERSISTENT: @@ -171,6 +173,11 @@ FFlatVertexBuffer::~FFlatVertexBuffer() glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); } + if (ibo_id != 0) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &ibo_id); + } if (gl.legacyMode) { delete[] map; @@ -189,6 +196,7 @@ void FFlatVertexBuffer::OutputResized(int width, int height) void FFlatVertexBuffer::BindVBO() { glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); if (!gl.legacyMode) { glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FFlatVertex), &VTO->x); @@ -246,4 +254,9 @@ void FFlatVertexBuffer::CreateVBO() Map(); memcpy(map, &vbo_shadowdata[0], vbo_shadowdata.Size() * sizeof(FFlatVertex)); Unmap(); + if (ibo_id > 0) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_data.Size() * sizeof(uint32_t), &ibo_data[0], GL_STATIC_DRAW); + } } diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index de741b2511..7c54b1916e 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -95,6 +95,7 @@ public: class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator { + unsigned int ibo_id; FFlatVertex *map; unsigned int mIndex; std::atomic mCurIndex; @@ -177,6 +178,11 @@ public: #endif + uint32_t *GetIndexPointer() const + { + return ibo_id == 0 ? &ibo_data[0] : nullptr; + } + void Reset() { mCurIndex = mIndex; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 305a5177cc..a0a1c5cc81 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -62,7 +62,7 @@ static void matrixToGL(const VSMatrix &mat, int loc) void FRenderState::Reset() { mTextureEnabled = true; - mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; + mClipLineShouldBeActive = mClipLineEnabled = 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; diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 1db6602a57..8aa4d00938 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -81,6 +81,7 @@ class FRenderState bool mGlowEnabled; bool mSplitEnabled; bool mClipLineEnabled; + bool mClipLineShouldBeActive; bool mBrightmapEnabled; bool mColorMask[4]; bool currentColorMask[4]; @@ -201,6 +202,11 @@ public: return mClipLineEnabled; } + bool GetClipLineShouldBeActive() + { + return mClipLineShouldBeActive; + } + void SetClipHeight(float height, float direction); void SetNormal(FVector3 norm) @@ -326,6 +332,11 @@ public: glDisable(GL_CLIP_DISTANCE0); } } + else + { + // this needs to be flagged because in this case per-sector plane rendering needs to be disabled if a clip plane is active. + mClipLineShouldBeActive = on; + } } void EnableBrightmap(bool on) diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 4ab217babb..8da945e6c6 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -121,6 +121,7 @@ struct FDrawInfo : public HWDrawInfo void ProcessLights(GLFlat *flat, bool istrans); void DrawSubsector(GLFlat *flat, subsector_t * sub); void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli); + void SetupSectorLights(GLFlat *flat, int pass, int *dli); // Sprite drawer void DrawSprite(GLSprite *sprite, int pass); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 380271989c..0aa9c88fc4 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -48,6 +48,8 @@ #include "gl/scene/gl_scenedrawer.h" #include "gl/renderer/gl_quaddrawer.h" +CVAR(Bool, gl_render_subsectors, false, 0) + //========================================================================== // // Flats @@ -62,7 +64,35 @@ void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, (*dli)++; return; } - if (flat->SetupSubsectorLights(pass, sub, lightdata)) + if (flat->SetupSectorLights(pass, flat->sector, lightdata)) + { + int d = GLRenderer->mLights->UploadLights(lightdata); + if (pass == GLPASS_LIGHTSONLY) + { + GLRenderer->mLights->StoreIndex(d); + } + else + { + gl_RenderState.ApplyLightIndex(d); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FDrawInfo::SetupSectorLights(GLFlat *flat, int pass, int *dli) +{ + if (dli != NULL && *dli != -1) + { + gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); + (*dli)++; + return; + } + if (flat->SetupSectorLights(pass, flat->sector, lightdata)) { int d = GLRenderer->mLights->UploadLights(lightdata); if (pass == GLPASS_LIGHTSONLY) @@ -137,15 +167,22 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans) { flat->dynlightindex = GLRenderer->mLights->GetIndexPtr(); + if (flat->sector->ibocount > 0 && !gl_render_subsectors && !gl_RenderState.GetClipLineShouldBeActive()) + { + SetupSectorLights(flat, GLPASS_LIGHTSONLY, nullptr); + } + else + { // Draw the subsectors belonging to this sector - for (int i=0; i< flat->sector->subsectorcount; i++) + for (int i = 0; i < flat->sector->subsectorcount; i++) { subsector_t * sub = flat->sector->subsectors[i]; - if (ss_renderflags[sub->Index()]& flat->renderflags || istrans) + if (ss_renderflags[sub->Index()] & flat->renderflags || istrans) { SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr); } } + } // Draw the subsectors assigned to it due to missing textures if (!(flat->renderflags&SSRF_RENDER3DPLANES)) @@ -175,29 +212,40 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool gl_RenderState.Apply(); if (gl.legacyMode) processlights = false; - if (flat->vboindex >= 0) + + auto vcount = flat->sector->ibocount; + if (vcount > 0 && !gl_render_subsectors && !gl_RenderState.GetClipLineShouldBeActive()) + { + if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli); + drawcalls.Clock(); + glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->vboindex); + drawcalls.Unclock(); + flatvertices += vcount; + flatprimitives++; + } + else if (flat->vboindex >= 0) { int index = flat->vboindex; for (int i=0; isector->subsectorcount; i++) { subsector_t * sub = flat->sector->subsectors[i]; + if (sub->numlines <= 2) continue; if (ss_renderflags[sub->Index()]& flat->renderflags || istrans) { if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli); drawcalls.Clock(); - glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines); + glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index); drawcalls.Unclock(); flatvertices += sub->numlines; flatprimitives++; } - index += sub->numlines; + index += (sub->numlines - 2) * 3; } } else { // Draw the subsectors belonging to this sector - // (can this case even happen?) for (int i=0; isector->subsectorcount; i++) { subsector_t * sub = flat->sector->subsectors[i]; diff --git a/src/hwrenderer/data/flatvertices.cpp b/src/hwrenderer/data/flatvertices.cpp index f069a7989e..5771012bc4 100644 --- a/src/hwrenderer/data/flatvertices.cpp +++ b/src/hwrenderer/data/flatvertices.cpp @@ -118,13 +118,22 @@ static F3DFloor *Find3DFloor(sector_t *target, sector_t *model) // //========================================================================== -int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor) +int FFlatVertexGenerator::CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FFlatVertexGenerator::FIndexGenerationInfo &gen) { - int idx = vbo_shadowdata.Reserve(sub->numlines); - for(unsigned int k=0; knumlines; k++, idx++) + if (sub->numlines < 3) return -1; + + int idx = ibo_data.Reserve((sub->numlines - 2) * 3); + int idxc = idx; + int firstndx = gen.GetIndex(sub->firstline[0].v1); + int secondndx = gen.GetIndex(sub->firstline[1].v1); + for (unsigned int k = 2; knumlines; k++) { - vbo_shadowdata[idx].SetFlatVertex(sub->firstline[k].v1, plane); - if (sub->sector->transdoor && floor) vbo_shadowdata[idx].z -= 1.f; + auto ndx = gen.GetIndex(sub->firstline[k].v1); + + ibo_data[idx++] = vi + firstndx; + ibo_data[idx++] = vi + secondndx; + ibo_data[idx++] = vi + ndx; + secondndx = ndx; } return idx; } @@ -135,15 +144,28 @@ int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secpla // //========================================================================== -int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor) +int FFlatVertexGenerator::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FFlatVertexGenerator::FIndexGenerationInfo &gen) { - int rt = vbo_shadowdata.Size(); - // First calculate the vertices for the sector itself - for(int j=0; jsubsectorcount; j++) + int rt = ibo_data.Size(); + int vi = vbo_shadowdata.Reserve(gen.vertices.Size()); + float diff; + + // Create the actual vertices. + if (sec->transdoor && floor) diff = -1.f; + else diff = 0.f; + for (unsigned i = 0; i < gen.vertices.Size(); i++) + { + vbo_shadowdata[vi + i].SetFlatVertex(gen.vertices[i], plane); + vbo_shadowdata[vi + i].z += diff; + } + + // Create the indices for the subsectors + for (int j = 0; jsubsectorcount; j++) { subsector_t *sub = sec->subsectors[j]; - CreateSubsectorVertices(sub, plane, floor); + CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen); } + sec->ibocount = ibo_data.Size() - rt; return rt; } @@ -153,23 +175,23 @@ int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t & // //========================================================================== -int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor) +int FFlatVertexGenerator::CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray &gen) { // First calculate the vertices for the sector itself sec->vboheight[h] = sec->GetPlaneTexZ(h); - sec->vboindex[h] = CreateSectorVertices(sec, plane, floor); + sec->vboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, gen[sec->Index()]); // Next are all sectors using this one as heightsec TArray &fakes = sec->e->FakeFloor.Sectors; - for (unsigned g=0; gvboindex[2+h] = CreateSectorVertices(fsec, plane, false); + fsec->vboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]); } // and finally all attached 3D floors TArray &xf = sec->e->XFloor.attached; - for (unsigned g=0; gtop.vindex = vbo_shadowdata.Size(); - if (dobottom) ffloor->bottom.vindex = vbo_shadowdata.Size(); - - CreateSectorVertices(fsec, plane, false); + auto ndx = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]); + if (dotop) ffloor->top.vindex = ndx; + if (dobottom) ffloor->bottom.vindex = ndx; } } } @@ -199,13 +220,28 @@ int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t // //========================================================================== -void FFlatVertexGenerator::CreateFlatVertices() +void FFlatVertexGenerator::CreateIndexedFlatVertices() { + TArray gen; + gen.Resize(level.sectors.Size()); + // This must be generated up front so that the following code knows how many vertices a sector contains. + for (unsigned i = 0; i < level.sectors.Size(); i++) + { + for (int j = 0; j < level.sectors[i].subsectorcount; j++) + { + auto sub = level.sectors[i].subsectors[j]; + for (unsigned k = 0; k < sub->numlines; k++) + { + auto vert = sub->firstline[k].v1; + gen[i].AddVertex(vert); + } + } + } for (int h = sector_t::floor; h <= sector_t::ceiling; h++) { - for(auto &sec : level.sectors) + for (auto &sec : level.sectors) { - CreateVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor); + CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, gen); } } @@ -213,7 +249,7 @@ void FFlatVertexGenerator::CreateFlatVertices() // No new vertices are needed here. The planes come from the actual sector for (auto &sec : level.sectors) { - for(auto ff : sec.e->XFloor.ffloors) + for (auto ff : sec.e->XFloor.ffloors) { if (ff->top.model == &sec) { @@ -257,7 +293,7 @@ void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane) void FFlatVertexGenerator::CreateVertices() { vbo_shadowdata.Resize(NUM_RESERVED); - CreateFlatVertices(); + CreateIndexedFlatVertices(); } //========================================================================== diff --git a/src/hwrenderer/data/flatvertices.h b/src/hwrenderer/data/flatvertices.h index ee390218f8..3025a6820d 100644 --- a/src/hwrenderer/data/flatvertices.h +++ b/src/hwrenderer/data/flatvertices.h @@ -45,8 +45,32 @@ class FFlatVertexGenerator { protected: TArray vbo_shadowdata; + TArray ibo_data; FFlatVertex *mMap; + // Temporary data for creating an indexed buffer + struct FIndexGenerationInfo + { + TArray vertices; + TMap vertexmap; + + uint32_t AddVertex(vertex_t *vert) + { + auto check = vertexmap.CheckKey(vert); + if (check != nullptr) return *check; + auto index = vertices.Push(vert); + vertexmap[vert] = index; + return index; + } + + uint32_t GetIndex(vertex_t *vert) + { + auto check = vertexmap.CheckKey(vert); + if (check != nullptr) return *check; + return ~0; + } + }; + public: enum @@ -65,10 +89,11 @@ public: void OutputResized(int width, int height); private: - int CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor); - int CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor); - int CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor); - void CreateFlatVertices(); + int CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FIndexGenerationInfo &gen); + int CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FIndexGenerationInfo &gen); + int CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray &gen); + void CreateIndexedFlatVertices(); + void UpdatePlaneVertices(sector_t *sec, int plane); protected: void CreateVertices(); diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 7aa7e0b7df..56c74a8f79 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -311,7 +311,9 @@ public: int dynlightindex; + bool SetupLights(int pass, FLightNode *head, FDynLightData &lightdata, int portalgroup); bool SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata); + bool SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata); void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index dabee535d6..fa1ff287a7 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -92,14 +92,13 @@ bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte // //========================================================================== -bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata) +bool GLFlat::SetupLights(int pass, FLightNode * node, FDynLightData &lightdata, int portalgroup) { Plane p; if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces. lightdata.Clear(); - FLightNode * node = sub->lighthead; while (node) { ADynamicLight * light = node->lightsource; @@ -121,13 +120,23 @@ bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &li } p.Set(plane.plane.Normal(), plane.plane.fD()); - lightdata.GetLight(sub->sector->PortalGroup, p, light, false); + lightdata.GetLight(portalgroup, p, light, false); node = node->nextLight; } return true; } +bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata) +{ + return SetupLights(pass, sub->lighthead, lightdata, sub->sector->PortalGroup); +} + +bool GLFlat::SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata) +{ + return SetupLights(pass, sec->lighthead, lightdata, sec->PortalGroup); +} + //========================================================================== // // GLFlat::PutFlat diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index d92951aa9a..57fef57e00 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -1090,6 +1090,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) { subsector_t *sub = HandledSubsectors[j]; ss_renderflags[sub->Index()] &= ~SSRF_RENDERCEILING; + sub->sector->ibocount = -1; // cannot render this sector in one go. if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL) { @@ -1135,6 +1136,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) { subsector_t *sub = HandledSubsectors[j]; ss_renderflags[sub->Index()] &= ~SSRF_RENDERFLOOR; + sub->sector->ibocount = -1; // cannot render this sector in one go. if (sub->portalcoverage[sector_t::floor].subsectors == NULL) { diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 4254c92d49..5c6096f842 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -120,6 +120,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag ffloor->top.copied = ffloor->bottom.copied = false; ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2; ffloor->target = sec; + ffloor->top.vindex = ffloor->bottom.vindex = -1; if (!(flags&FF_THINFLOOR)) { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 56850f6a01..dba5a109e3 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1510,6 +1510,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->friction = ORIG_FRICTION; ss->movefactor = ORIG_FRICTION_FACTOR; ss->sectornum = i; + ss->ibocount = -1; } delete[] msp; } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 283fac0004..6acf9e37c5 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1383,6 +1383,7 @@ public: sec->sectornum = index; sec->damageinterval = 32; sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1; + sec->ibocount = -1; memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors)); if (floordrop) sec->Flags = SECF_FLOORDROP; // killough 3/7/98: end changes diff --git a/src/r_defs.h b/src/r_defs.h index d5b104624d..17fcc5cad0 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1087,9 +1087,10 @@ public: vbo_fakeceiling = ceiling+2, }; - int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering + int vboindex[4]; // VBO/IBO indices of the 4 planes this sector uses during rendering double vboheight[2]; // Last calculated height for the 2 planes of this actual sector - int vbocount[2]; // Total count of vertices belonging to this sector's planes + int vbocount[2]; // Total count of vertices belonging to this sector's planes. This is used when a sector height changes and also contains all attached planes. + int ibocount; // number of indices per plane (identical for all planes.) If this is -1 the index buffer is not in use. float GetReflect(int pos) { return gl_plane_reflection_i? reflect[pos] : 0; } bool VBOHeightcheck(int pos) const { return vboheight[pos] == GetPlaneTexZ(pos); } diff --git a/src/win32/win32gliface.cpp b/src/win32/win32gliface.cpp index bd4600bb0f..cb6da5ff9b 100644 --- a/src/win32/win32gliface.cpp +++ b/src/win32/win32gliface.cpp @@ -1159,10 +1159,15 @@ bool SystemFrameBuffer::IsFullscreen() // // //========================================================================== +EXTERN_CVAR(Bool, vid_vsync); +CUSTOM_CVAR(Bool, gl_control_tear, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + vid_vsync.Callback(); +} void SystemFrameBuffer::SetVSync (bool vsync) { - if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? SwapInterval : 0); + if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? (gl_control_tear? SwapInterval : 1) : 0); } void SystemFrameBuffer::SwapBuffers() diff --git a/wadsrc/static/shaders/glsl/material_normal.fp b/wadsrc/static/shaders/glsl/material_normal.fp index b048f45597..6b65de6a3b 100644 --- a/wadsrc/static/shaders/glsl/material_normal.fp +++ b/wadsrc/static/shaders/glsl/material_normal.fp @@ -9,6 +9,10 @@ vec3 lightContribution(int i, vec3 normal) float lightdistance = distance(lightpos.xyz, pixelpos.xyz); if (lightpos.w < lightdistance) return vec3(0.0); // Early out lights touching surface but not this fragment + + vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz); + float dotprod = dot(normal, lightdir); + if (dotprod < 0.0) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0); @@ -17,8 +21,7 @@ vec3 lightContribution(int i, vec3 normal) if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag { - vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz); - attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0); + attenuation *= clamp(dotprod, 0.0, 1.0); } if (attenuation > 0.0) // Skip shadow map test if possible diff --git a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt index efc6bedc8b..96f0063208 100644 --- a/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt +++ b/wadsrc/static/zscript/statusbar/sbarinfowrapper.txt @@ -12,7 +12,7 @@ struct SBarInfo native ui } -// The sole purpose of this wrapper is to elimintate the native dependencies of the status bar object +// The sole purpose of this wrapper is to eliminate the native dependencies of the status bar object // because those would seriously impede the script conversion of the base class. class SBarInfoWrapper : BaseStatusBar