diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 4e57c638e..57fce23fd 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -126,13 +126,16 @@ void ASkyPicker::PostBeginPlay () else { int boxindex = P_GetSkyboxPortal(box); + // Do not override special portal types, only regular skies. if (0 == (args[1] & 2)) { - Sector->Portals[sector_t::ceiling] = boxindex; + if (Sector->GetPortalType(sector_t::ceiling) == PORTS_SKYVIEWPOINT) + Sector->Portals[sector_t::ceiling] = boxindex; } if (0 == (args[1] & 1)) { - Sector->Portals[sector_t::floor] = boxindex; + if (Sector->GetPortalType(sector_t::floor) == PORTS_SKYVIEWPOINT) + Sector->Portals[sector_t::floor] = boxindex; } } Destroy (); diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index e059a3563..1dac5ac38 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -49,6 +49,7 @@ #include "gl/dynlights/gl_dynlight.h" #include "gl/utility/gl_geometric.h" #include "gl/renderer/gl_renderer.h" +#include "gl/renderer/gl_lightdata.h" #include "gl/system/gl_interface.h" #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderstate.h" @@ -452,7 +453,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, bool gl_SetupLightTexture() { - if (GLRenderer->gllight == NULL) return false; + if (GLRenderer->gllight == nullptr) return false; FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight, false); pat->Bind(CLAMP_XY, 0); return true; @@ -464,6 +465,95 @@ bool gl_SetupLightTexture() // //========================================================================== +bool GLWall::PutWallCompat(int passflag) +{ + static int list_indices[2][2] = + { { GLLDL_WALLS_PLAIN, GLLDL_WALLS_FOG },{ GLLDL_WALLS_MASKED, GLLDL_WALLS_FOGMASKED } }; + + // are lights possible? + if (gl_fixedcolormap != CM_DEFAULT || !gl_lights || seg->sidedef == nullptr || type == RENDERWALL_M2SNF || !gltexture) return false; + + // multipassing these is problematic. + if ((flags&GLWF_SKYHACK && type == RENDERWALL_M2S)) return false; + + // Any lights affecting this wall? + if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) + { + if (seg->sidedef->lighthead == nullptr) return false; + } + else if (sub) + { + if (sub->lighthead != nullptr) return false; + } + + bool foggy = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE); + bool masked = passflag == 2 && gltexture->isMasked(); + + int list = list_indices[masked][foggy]; + if (list == GLLDL_WALLS_PLAIN) + { + if (gltexture->tex->gl_info.Brightmap && gl.glslversion >= 0.f) list = GLLDL_WALLS_BRIGHT; + //if (flags & GLWF_GLOW) list = GLLDL_WALLS_BRIGHT; + } + gl_drawinfo->dldrawlists[list].AddWall(this); + return true; + +} + +//========================================================================== +// +// Fog boundary without any shader support +// +//========================================================================== + +void GLWall::RenderFogBoundaryCompat() +{ + // without shaders some approximation is needed. This won't look as good + // as the shader version but it's an acceptable compromise. + float fogdensity = gl_GetFogDensity(lightlevel, Colormap.FadeColor); + + float dist1 = Dist2(ViewPos.X, ViewPos.Y, glseg.x1, glseg.y1); + float dist2 = Dist2(ViewPos.X, ViewPos.Y, glseg.x2, glseg.y2); + + // these values were determined by trial and error and are scale dependent! + float fogd1 = (0.95f - exp(-fogdensity*dist1 / 62500.f)) * 1.05f; + float fogd2 = (0.95f - exp(-fogdensity*dist2 / 62500.f)) * 1.05f; + + float fc[4] = { Colormap.FadeColor.r / 255.0f,Colormap.FadeColor.g / 255.0f,Colormap.FadeColor.b / 255.0f,fogd2 }; + + gl_RenderState.EnableTexture(false); + gl_RenderState.EnableFog(false); + gl_RenderState.AlphaFunc(GL_GEQUAL, 0); + gl_RenderState.Apply(); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -128.0f); + glDepthFunc(GL_LEQUAL); + glColor4f(fc[0], fc[1], fc[2], fogd1); + glBegin(GL_TRIANGLE_FAN); + glTexCoord2f(lolft.u, lolft.v); + glVertex3f(glseg.x1, zbottom[0], glseg.y1); + glTexCoord2f(uplft.u, uplft.v); + glVertex3f(glseg.x1, ztop[0], glseg.y1); + glColor4f(fc[0], fc[1], fc[2], fogd2); + glTexCoord2f(uprgt.u, uprgt.v); + glVertex3f(glseg.x2, ztop[1], glseg.y2); + glTexCoord2f(lorgt.u, lorgt.v); + glVertex3f(glseg.x2, zbottom[1], glseg.y2); + glEnd(); + glDepthFunc(GL_LESS); + glPolygonOffset(0.0f, 0.0f); + glDisable(GL_POLYGON_OFFSET_FILL); + gl_RenderState.EnableFog(true); + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f); + gl_RenderState.EnableTexture(true); +} + +//========================================================================== +// +// +// +//========================================================================== + void FGLRenderer::RenderMultipassStuff() { return; diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index c56cadcba..b88cc6ca1 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -197,11 +197,12 @@ struct FModelVertex class FModelVertexBuffer : public FVertexBuffer { int mIndexFrame[2]; - unsigned int ibo_id; + FModelVertex *vbo_ptr; + uint32_t ibo_id; public: - FModelVertexBuffer(bool needindex); + FModelVertexBuffer(bool needindex, bool singleframe); ~FModelVertexBuffer(); FModelVertex *LockVertexBuffer(unsigned int size); @@ -210,7 +211,7 @@ public: unsigned int *LockIndexBuffer(unsigned int size); void UnlockIndexBuffer(); - unsigned int SetupFrame(unsigned int frame1, unsigned int frame2); + unsigned int SetupFrame(unsigned int frame1, unsigned int frame2, unsigned int size); void BindVBO(); }; diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index dc937ea40..e2187c59c 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -73,32 +73,17 @@ EXTERN_CVAR(Int, gl_fogmode) extern TDeletingArray Voxels; extern TDeletingArray VoxelDefs; - -class DeletingModelArray : public TArray -{ -public: - -#if 1 - ~DeletingModelArray() - { - for(unsigned i=0;i= 0; i--) { Models[i]->BuildVertexBuffer(); } + */ } void gl_FlushModels() @@ -111,16 +96,22 @@ void gl_FlushModels() //=========================================================================== // +// Uses a hardware buffer if either single frame (i.e. no interpolation needed) +// or shading is available (interpolation is done by the vertex shader) // +// If interpolation has to be done on the CPU side this will fall back +// to CPU-side arrays. // //=========================================================================== -FModelVertexBuffer::FModelVertexBuffer(bool needindex) +FModelVertexBuffer::FModelVertexBuffer(bool needindex, bool singleframe) + : FVertexBuffer(singleframe || gl.glslversion > 0) { + vbo_ptr = nullptr; ibo_id = 0; if (needindex) { - glGenBuffers(1, &ibo_id); + glGenBuffers(1, &ibo_id); // The index buffer can always be a real buffer. } } @@ -161,6 +152,10 @@ FModelVertexBuffer::~FModelVertexBuffer() { glDeleteBuffers(1, &ibo_id); } + if (vbo_ptr != nullptr) + { + delete[] vbo_ptr; + } } //=========================================================================== @@ -171,9 +166,19 @@ FModelVertexBuffer::~FModelVertexBuffer() FModelVertex *FModelVertexBuffer::LockVertexBuffer(unsigned int size) { - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glBufferData(GL_ARRAY_BUFFER, size * sizeof(FModelVertex), NULL, GL_STATIC_DRAW); - return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT); + if (vbo_id > 0) + { + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBufferData(GL_ARRAY_BUFFER, size * sizeof(FModelVertex), nullptr, GL_STATIC_DRAW); + return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + else + { + if (vbo_ptr != nullptr) delete[] vbo_ptr; + vbo_ptr = new FModelVertex[size]; + memset(vbo_ptr, 0, size * sizeof(FModelVertex)); + return vbo_ptr; + } } //=========================================================================== @@ -184,8 +189,11 @@ FModelVertex *FModelVertexBuffer::LockVertexBuffer(unsigned int size) void FModelVertexBuffer::UnlockVertexBuffer() { - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glUnmapBuffer(GL_ARRAY_BUFFER); + if (vbo_id > 0) + { + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glUnmapBuffer(GL_ARRAY_BUFFER); + } } //=========================================================================== @@ -204,7 +212,7 @@ unsigned int *FModelVertexBuffer::LockIndexBuffer(unsigned int size) } else { - return NULL; + return nullptr; } } @@ -216,8 +224,11 @@ unsigned int *FModelVertexBuffer::LockIndexBuffer(unsigned int size) void FModelVertexBuffer::UnlockIndexBuffer() { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + if (ibo_id > 0) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } } @@ -227,21 +238,44 @@ void FModelVertexBuffer::UnlockIndexBuffer() // This must be called after gl_RenderState.Apply! // //=========================================================================== +static TArray iBuffer; -unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int frame2) +unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int frame2, unsigned int size) { glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - if (gl.glslversion > 0) + if (vbo_id > 0) { - glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].x); - glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].u); - glVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame2].x); + if (gl.glslversion > 0) + { + glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].x); + glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame1].u); + glVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame2].x); + } + else + { + // only used for single frame models so there is no vertex2 here, which has no use without a shader. + glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].x); + glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].u); + } + } + else if (frame1 == frame2 || size == 0 || gl_RenderState.GetInterpolationFactor() == 0.f) + { + glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &vbo_ptr[frame1].x); + glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &vbo_ptr[frame1].u); } else { - // only used for single frame models so there is no vertex2 here, which has no use without a shader. - glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].x); - glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].u); + // must interpolate + iBuffer.Resize(size); + glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &iBuffer[0].x); + glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &vbo_ptr[frame1].u); + float frac = gl_RenderState.GetInterpolationFactor(); + for (unsigned i = 0; i < size; i++) + { + iBuffer[i].x = vbo_ptr[frame1 + i].x * (1.f - frac) + vbo_ptr[frame2 + i].x * frac; + iBuffer[i].y = vbo_ptr[frame1 + i].y * (1.f - frac) + vbo_ptr[frame2 + i].y * frac; + iBuffer[i].z = vbo_ptr[frame1 + i].z * (1.f - frac) + vbo_ptr[frame2 + i].z * frac; + } } return frame1; } @@ -254,7 +288,7 @@ unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int fr FModel::~FModel() { - if (mVBuf != NULL) delete mVBuf; + if (mVBuf != nullptr) delete mVBuf; } @@ -266,8 +300,8 @@ static int * SpriteModelHash; static void DeleteModelHash() { - if (SpriteModelHash != NULL) delete [] SpriteModelHash; - SpriteModelHash = NULL; + if (SpriteModelHash != nullptr) delete [] SpriteModelHash; + SpriteModelHash = nullptr; } //=========================================================================== @@ -278,12 +312,15 @@ static void DeleteModelHash() static int FindGFXFile(FString & fn) { + int lump = Wads.CheckNumForFullName(fn); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. + if (lump != -1) return lump; + int best = -1; int dot = fn.LastIndexOf('.'); int slash = fn.LastIndexOf('/'); if (dot > slash) fn.Truncate(dot); - static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", NULL }; + static const char * extensions[] = { ".png", ".jpg", ".tga", ".pcx", nullptr }; for (const char ** extp=extensions; *extp; extp++) { @@ -300,7 +337,7 @@ static int FindGFXFile(FString & fn) // //=========================================================================== -FTexture * LoadSkin(const char * path, const char * fn) +FTextureID LoadSkin(const char * path, const char * fn) { FString buffer; @@ -309,11 +346,11 @@ FTexture * LoadSkin(const char * path, const char * fn) int texlump = FindGFXFile(buffer); if (texlump>=0) { - return TexMan.FindTexture(Wads.GetLumpFullName(texlump), FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny); + return TexMan.CheckForTexture(Wads.GetLumpFullName(texlump), FTexture::TEX_Any, FTextureManager::TEXMAN_TryAny); } else { - return NULL; + return FNullTextureID(); } } @@ -344,9 +381,9 @@ static int ModelFrameHash(FSpriteModelFrame * smf) // //=========================================================================== -static FModel * FindModel(const char * path, const char * modelfile) +static unsigned FindModel(const char * path, const char * modelfile) { - FModel * model = NULL; + FModel * model = nullptr; FString fullname; fullname.Format("%s%s", path, modelfile); @@ -355,12 +392,12 @@ static FModel * FindModel(const char * path, const char * modelfile) if (lump<0) { Printf("FindModel: '%s' not found\n", fullname.GetChars()); - return NULL; + return -1; } - for(int i = 0; i< (int)Models.Size(); i++) + for(unsigned i = 0; i< Models.Size(); i++) { - if (!Models[i]->mFileName.CompareNoCase(fullname)) return Models[i]; + if (!Models[i]->mFileName.CompareNoCase(fullname)) return i; } int len = Wads.LumpLength(lump); @@ -380,32 +417,31 @@ static FModel * FindModel(const char * path, const char * modelfile) model = new FMD3Model; } - if (model != NULL) + if (model != nullptr) { if (!model->Load(path, lump, buffer, len)) { delete model; - return NULL; + return -1; } } else { // try loading as a voxel FVoxel *voxel = R_LoadKVX(lump); - if (voxel != NULL) + if (voxel != nullptr) { model = new FVoxelModel(voxel, true); } else { Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars()); - return NULL; + return -1; } } // The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized model->mFileName = fullname; - Models.Push(model); - return model; + return Models.Push(model); } //=========================================================================== @@ -444,8 +480,9 @@ void gl_InitModels() { FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex]; memset(&smf, 0, sizeof(smf)); - smf.models[0] = md; - smf.skins[0] = md->GetPaletteTexture(); + smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; + smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; + smf.skinIDs[0] = md->GetPaletteTexture(); smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; if (VoxelDefs[i]->PlacedSpin != 0) @@ -474,6 +511,7 @@ void gl_InitModels() } memset(&smf, 0, sizeof(smf)); + smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); @@ -483,10 +521,11 @@ void gl_InitModels() { sc.MustGetString(); memset(&smf, 0, sizeof(smf)); + smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); - if (!smf.type || smf.type->Defaults == NULL) + if (!smf.type || smf.type->Defaults == nullptr) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } @@ -505,15 +544,15 @@ void gl_InitModels() else if (sc.Compare("model")) { sc.MustGetNumber(); - index=sc.Number; - if (index<0 || index>=MAX_MODELS_PER_FRAME) + index = sc.Number; + if (index < 0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); - smf.models[index] = FindModel(path.GetChars(), sc.String); - if (!smf.models[index]) + smf.modelIDs[index] = FindModel(path.GetChars(), sc.String); + if (smf.modelIDs[index] == -1) { Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } @@ -521,11 +560,11 @@ void gl_InitModels() else if (sc.Compare("scale")) { sc.MustGetFloat(); - smf.xscale=sc.Float; + smf.xscale = sc.Float; sc.MustGetFloat(); - smf.yscale=sc.Float; + smf.yscale = sc.Float; sc.MustGetFloat(); - smf.zscale=sc.Float; + smf.zscale = sc.Float; } // [BB] Added zoffset reading. // Now it must be considered deprecated. @@ -631,12 +670,12 @@ void gl_InitModels() FixPathSeperator(sc.String); if (sc.Compare("")) { - smf.skins[index]=NULL; + smf.skinIDs[index]=FNullTextureID(); } else { - smf.skins[index]=LoadSkin(path.GetChars(), sc.String); - if (smf.skins[index] == NULL) + smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String); + if (!smf.skinIDs[index].isValid()) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); @@ -678,9 +717,10 @@ void gl_InitModels() if (isframe) { sc.MustGetString(); - if (smf.models[index]!=NULL) + if (smf.modelIDs[index] != -1) { - smf.modelframes[index] = smf.models[index]->FindFrame(sc.String); + FModel *model = Models[smf.modelIDs[index]]; + smf.modelframes[index] = model->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; @@ -765,7 +805,7 @@ FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, if (frame < sprdef->numframes) { spriteframe_t *sprframe = &SpriteFrames[sprdef->spriteframes + frame]; - if (sprframe->Voxel != NULL) + if (sprframe->Voxel != nullptr) { int index = sprframe->Voxel->VoxeldefIndex; if (dropped && sprframe->Voxel->DroppedSpin !=sprframe->Voxel->PlacedSpin) index++; @@ -773,7 +813,7 @@ FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, } } } - return NULL; + return nullptr; } @@ -792,7 +832,7 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf, { // [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation // and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame. - FSpriteModelFrame * smfNext = NULL; + FSpriteModelFrame * smfNext = nullptr; double inter = 0.; if( gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION) ) { @@ -839,17 +879,17 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf, for(int i=0; imodels[i]; - - if (mdl!=NULL) + if (smf->modelIDs[i] != -1) { + FModel * mdl = Models[smf->modelIDs[i]]; + FTexture *tex = smf->skinIDs[i].isValid()? TexMan(smf->skinIDs[i]) : nullptr; mdl->BuildVertexBuffer(); gl_RenderState.SetVertexBuffer(mdl->mVBuf); if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] ) - mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smfNext->modelframes[i], inter, translation); + mdl->RenderFrame(tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation); else - mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smf->modelframes[i], 0.f, translation); + mdl->RenderFrame(tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation); gl_RenderState.SetVertexBuffer(GLRenderer->mVBO); } @@ -949,12 +989,12 @@ void gl_RenderModel(GLSprite * spr) gl_RenderState.mModelMatrix.rotate(-smf->rolloffset, 1, 0, 0); // consider the pixel stretching. For non-voxels this must be factored out here - float stretch = (smf->models[0] != NULL ? smf->models[0]->getAspectFactor() : 1.f) / glset.pixelstretch; + float stretch = (smf->modelIDs[0] != -1 ? Models[smf->modelIDs[0]]->getAspectFactor() : 1.f) / glset.pixelstretch; gl_RenderState.mModelMatrix.scale(1, stretch, 1); gl_RenderState.EnableModelMatrix(true); - gl_RenderFrameModels( smf, spr->actor->state, spr->actor->tics, spr->actor->GetClass(), NULL, translation ); + gl_RenderFrameModels( smf, spr->actor->state, spr->actor->tics, spr->actor->GetClass(), nullptr, translation ); gl_RenderState.EnableModelMatrix(false); glDepthFunc(GL_LESS); @@ -975,7 +1015,7 @@ void gl_RenderHUDModel(pspdef_t *psp, float ofsX, float ofsY) FSpriteModelFrame *smf = gl_FindModelFrame(playermo->player->ReadyWeapon->GetClass(), psp->state->sprite, psp->state->GetFrame(), false); // [BB] No model found for this sprite, so we can't render anything. - if ( smf == NULL ) + if ( smf == nullptr ) return; glDepthFunc(GL_LEQUAL); @@ -1012,7 +1052,7 @@ void gl_RenderHUDModel(pspdef_t *psp, float ofsX, float ofsY) gl_RenderState.mViewMatrix.rotate(-smf->rolloffset, 1, 0, 0); gl_RenderState.ApplyMatrices(); - gl_RenderFrameModels( smf, psp->state, psp->tics, playermo->player->ReadyWeapon->GetClass(), NULL, 0 ); + gl_RenderFrameModels( smf, psp->state, psp->tics, playermo->player->ReadyWeapon->GetClass(), nullptr, 0 ); glDepthFunc(GL_LESS); if (!( playermo->RenderStyle == LegacyRenderStyles[STYLE_Normal] )) @@ -1027,11 +1067,11 @@ void gl_RenderHUDModel(pspdef_t *psp, float ofsX, float ofsY) bool gl_IsHUDModelForPlayerAvailable (player_t * player) { - if ( (player == NULL) || (player->ReadyWeapon == NULL) || (player->psprites[0].state == NULL) ) + if ( (player == nullptr) || (player->ReadyWeapon == nullptr) || (player->psprites[0].state == nullptr) ) return false; FState* state = player->psprites[0].state; FSpriteModelFrame *smf = gl_FindModelFrame(player->ReadyWeapon->GetClass(), state->sprite, state->GetFrame(), false); - return ( smf != NULL ); + return ( smf != nullptr ); } diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index a99f81322..33fa00736 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -1,6 +1,7 @@ #ifndef __GL_MODELS_H_ #define __GL_MODELS_H_ +#include "tarray.h" #include "gl/utility/gl_geometric.h" #include "gl/data/gl_vertexbuffer.h" #include "p_pspr.h" @@ -16,7 +17,7 @@ enum { VX, VZ, VY }; #define MD3_MAGIC 0x33504449 #define NUMVERTEXNORMALS 162 -FTexture * LoadSkin(const char * path, const char * fn); +FTextureID LoadSkin(const char * path, const char * fn); class FModel @@ -33,6 +34,7 @@ public: virtual int FindFrame(const char * name) = 0; virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0; virtual void BuildVertexBuffer() = 0; + virtual void AddSkins(BYTE *hitlist) = 0; void DestroyVertexBuffer() { delete mVBuf; @@ -124,7 +126,7 @@ protected: int mLumpNum; DMDHeader header; DMDInfo info; - FTexture ** skins; + FTextureID * skins; ModelFrame * frames; bool allowTexComp; // Allow texture compression with this. @@ -154,6 +156,8 @@ public: virtual int FindFrame(const char * name); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); virtual void LoadGeometry(); + virtual void AddSkins(BYTE *hitlist); + void UnloadGeometry(); void BuildVertexBuffer(); @@ -201,7 +205,7 @@ class FMD3Model : public FModel int numTriangles; int numSkins; - FTexture ** skins; + FTextureID * skins; MD3Triangle * tris; MD3TexCoord * texcoords; MD3Vertex * vertices; @@ -259,6 +263,7 @@ public: virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); void LoadGeometry(); void BuildVertexBuffer(); + virtual void AddSkins(BYTE *hitlist); }; struct FVoxelVertexHash @@ -295,7 +300,7 @@ class FVoxelModel : public FModel protected: FVoxel *mVoxel; bool mOwningVoxel; // if created through MODELDEF deleting this object must also delete the voxel object - FTexture *mPalette; + FTextureID mPalette; unsigned int mNumIndices; TArray mVertices; TArray mIndices; @@ -311,7 +316,8 @@ public: void Initialize(); virtual int FindFrame(const char * name); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); - FTexture *GetPaletteTexture() const { return mPalette; } + virtual void AddSkins(BYTE *hitlist); + FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(); float getAspectFactor(); }; @@ -338,8 +344,8 @@ enum struct FSpriteModelFrame { - FModel * models[MAX_MODELS_PER_FRAME]; - FTexture * skins[MAX_MODELS_PER_FRAME]; + int modelIDs[MAX_MODELS_PER_FRAME]; + FTextureID skinIDs[MAX_MODELS_PER_FRAME]; int modelframes[MAX_MODELS_PER_FRAME]; float xscale, yscale, zscale; // [BB] Added zoffset, rotation parameters and flags. @@ -368,4 +374,21 @@ void gl_RenderModel(GLSprite * spr); void gl_RenderHUDModel(pspdef_t *psp, float ofsx, float ofsy); bool gl_IsHUDModelForPlayerAvailable (player_t * player); + +class DeletingModelArray : public TArray +{ +public: + + ~DeletingModelArray() + { + for (unsigned i = 0; iLockVertexBuffer(VertexBufferSize); for (int i = 0; i < info.numFrames; i++) @@ -336,7 +336,22 @@ void FDMDModel::BuildVertexBuffer() } } +//=========================================================================== +// +// for skin precaching +// +//=========================================================================== +void FDMDModel::AddSkins(BYTE *hitlist) +{ + for (int i = 0; i < info.numSkins; i++) + { + if (skins[i].isValid()) + { + hitlist[skins[i].GetIndex()] |= FTexture::TEX_Flat; + } + } +} //=========================================================================== // @@ -364,8 +379,8 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i if (!skin) { - if (info.numSkins == 0) return; - skin = skins[0]; + if (info.numSkins == 0 || !skins[0].isValid()) return; + skin = TexMan(skins[0]); if (!skin) return; } @@ -375,7 +390,7 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetInterpolationFactor((float)inter); gl_RenderState.Apply(); - mVBuf->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex); + mVBuf->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3); glDrawArrays(GL_TRIANGLES, 0, lodInfo[0].numTriangles * 3); gl_RenderState.SetInterpolationFactor(0.f); } @@ -469,7 +484,7 @@ bool FMD2Model::Load(const char * path, int lumpnum, const char * buffer, int le return false; } - skins = new FTexture *[info.numSkins]; + skins = new FTextureID[info.numSkins]; for (i = 0; i < info.numSkins; i++) { diff --git a/src/gl/models/gl_models_md3.cpp b/src/gl/models/gl_models_md3.cpp index 024f8ac81..267e85c91 100644 --- a/src/gl/models/gl_models_md3.cpp +++ b/src/gl/models/gl_models_md3.cpp @@ -179,14 +179,14 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le // copy shaders (skins) md3_shader_t * shader = (md3_shader_t*)(((char*)ss) + LittleLong(ss->Ofs_Shaders)); - s->skins = new FTexture *[s->numSkins]; + s->skins = new FTextureID[s->numSkins]; for (int i = 0; i < s->numSkins; i++) { // [BB] According to the MD3 spec, Name is supposed to include the full path. s->skins[i] = LoadSkin("", shader[i].Name); // [BB] Fall back and check if Name is relative. - if (s->skins[i] == NULL) + if (!s->skins[i].isValid()) s->skins[i] = LoadSkin(path, shader[i].Name); } } @@ -255,7 +255,7 @@ void FMD3Model::LoadGeometry() void FMD3Model::BuildVertexBuffer() { - if (mVBuf == NULL) + if (mVBuf == nullptr) { LoadGeometry(); @@ -269,11 +269,11 @@ void FMD3Model::BuildVertexBuffer() ibufsize += 3 * surf->numTriangles; } - mVBuf = new FModelVertexBuffer(true); + mVBuf = new FModelVertexBuffer(true, numFrames == 1); FModelVertex *vertptr = mVBuf->LockVertexBuffer(vbufsize); unsigned int *indxptr = mVBuf->LockIndexBuffer(ibufsize); - assert(vertptr != NULL && indxptr != NULL); + assert(vertptr != nullptr && indxptr != nullptr); unsigned int vindex = 0, iindex = 0; @@ -309,6 +309,27 @@ void FMD3Model::BuildVertexBuffer() } +//=========================================================================== +// +// for skin precaching +// +//=========================================================================== + +void FMD3Model::AddSkins(BYTE *hitlist) +{ + for (int i = 0; i < numSurfaces; i++) + { + MD3Surface * surf = &surfaces[i]; + for (int j = 0; j < surf->numSkins; j++) + { + if (surf->skins[j].isValid()) + { + hitlist[surf->skins[j].GetIndex()] |= FTexture::TEX_Flat; + } + } + } +} + //=========================================================================== // // @@ -344,8 +365,8 @@ void FMD3Model::RenderFrame(FTexture * skin, int frameno, int frameno2, double i FTexture *surfaceSkin = skin; if (!surfaceSkin) { - if (surf->numSkins==0) return; - surfaceSkin = surf->skins[0]; + if (surf->numSkins==0 || !surf->skins[0].isValid()) return; + surfaceSkin = TexMan(surf->skins[0]); if (!surfaceSkin) return; } @@ -354,7 +375,7 @@ void FMD3Model::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetMaterial(tex, CLAMP_NONE, translation, -1, false); gl_RenderState.Apply(); - mVBuf->SetupFrame(surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices); + mVBuf->SetupFrame(surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices); glDrawElements(GL_TRIANGLES, surf->numTriangles * 3, GL_UNSIGNED_INT, (void*)(intptr_t)(surf->iindex * sizeof(unsigned int))); } gl_RenderState.SetInterpolationFactor(0.f); @@ -370,6 +391,6 @@ FMD3Model::~FMD3Model() { if (frames) delete [] frames; if (surfaces) delete [] surfaces; - frames = NULL; - surfaces = NULL; + frames = nullptr; + surfaces = nullptr; } diff --git a/src/gl/models/gl_voxels.cpp b/src/gl/models/gl_voxels.cpp index 3a34117b9..ec7f0573b 100644 --- a/src/gl/models/gl_voxels.cpp +++ b/src/gl/models/gl_voxels.cpp @@ -213,7 +213,7 @@ FVoxelModel::FVoxelModel(FVoxel *voxel, bool owned) { mVoxel = voxel; mOwningVoxel = owned; - mPalette = new FVoxelTexture(voxel); + mPalette = TexMan.AddTexture(new FVoxelTexture(voxel)); } //=========================================================================== @@ -224,7 +224,6 @@ FVoxelModel::FVoxelModel(FVoxel *voxel, bool owned) FVoxelModel::~FVoxelModel() { - delete mPalette; if (mOwningVoxel) delete mVoxel; } @@ -378,7 +377,7 @@ void FVoxelModel::BuildVertexBuffer() { Initialize(); - mVBuf = new FModelVertexBuffer(true); + mVBuf = new FModelVertexBuffer(true, true); FModelVertex *vertptr = mVBuf->LockVertexBuffer(mVertices.Size()); unsigned int *indxptr = mVBuf->LockIndexBuffer(mIndices.Size()); @@ -398,6 +397,17 @@ void FVoxelModel::BuildVertexBuffer() } +//=========================================================================== +// +// for skin precaching +// +//=========================================================================== + +void FVoxelModel::AddSkins(BYTE *hitlist) +{ + hitlist[mPalette.GetIndex()] |= FTexture::TEX_Flat; +} + //=========================================================================== // // @@ -443,7 +453,7 @@ void FVoxelModel::RenderFrame(FTexture * skin, int frame, int frame2, double int gl_RenderState.SetMaterial(tex, CLAMP_NOFILTER, translation, -1, false); gl_RenderState.Apply(); - mVBuf->SetupFrame(0, 0); + mVBuf->SetupFrame(0, 0, 0); glDrawElements(GL_TRIANGLES, mNumIndices, GL_UNSIGNED_INT, (void*)(intptr_t)0); } diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index cebbb9570..0172488eb 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -439,6 +439,11 @@ public: mInterpolationFactor = fac; } + float GetInterpolationFactor() + { + return mInterpolationFactor; + } + // Backwards compatibility crap follows void ApplyFixedFunction(); void DrawColormapOverlay(); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index a87e522d3..44368775a 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -1019,23 +1019,10 @@ bool FGLInterface::UsesColormap() const void FGLInterface::PrecacheTexture(FTexture *tex, int cache) { - if (tex != NULL) + if (cache & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky)) { - if (cache) - { - if (gl_precache) - { - if (cache & (FTextureManager::HIT_Wall | FTextureManager::HIT_Flat | FTextureManager::HIT_Sky)) - { - FMaterial * gltex = FMaterial::ValidateTexture(tex, false); - if (gltex) gltex->Precache(); - } - } - } - else - { - if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true); - } + FMaterial * gltex = FMaterial::ValidateTexture(tex, false); + if (gltex) gltex->Precache(); } } @@ -1047,15 +1034,8 @@ void FGLInterface::PrecacheTexture(FTexture *tex, int cache) void FGLInterface::PrecacheSprite(FTexture *tex, SpriteHits &hits) { - if (hits.CountUsed() == 0) - { - if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true); - } - else - { - FMaterial * gltex = FMaterial::ValidateTexture(tex, true); - if (gltex) gltex->PrecacheList(hits); - } + FMaterial * gltex = FMaterial::ValidateTexture(tex, true); + if (gltex) gltex->PrecacheList(hits); } //========================================================================== @@ -1070,6 +1050,8 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap &actorhit SpriteHits **spritehitlist = new SpriteHits*[TexMan.NumTextures()]; TMap::Iterator it(actorhitlist); TMap::Pair *pair; + BYTE *modellist = new BYTE[Models.Size()]; + memset(modellist, 0, Models.Size()); memset(spritehitlist, 0, sizeof(SpriteHits**) * TexMan.NumTextures()); // this isn't done by the main code so it needs to be done here first: @@ -1095,6 +1077,9 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap &actorhit } } + // Check all used actors. + // 1. mark all sprites associated with its states + // 2. mark all model data and skins associated with its states while (it.NextPair(pair)) { PClassActor *cls = pair->Key; @@ -1103,11 +1088,29 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap &actorhit for (int i = 0; i < cls->NumOwnedStates; i++) { spritelist[cls->OwnedStates[i].sprite].Insert(gltrans, true); + FSpriteModelFrame * smf = gl_FindModelFrame(cls, cls->OwnedStates[i].sprite, cls->OwnedStates[i].Frame, false); + if (smf != NULL) + { + for (int i = 0; i < MAX_MODELS_PER_FRAME; i++) + { + if (smf->skinIDs[i].isValid()) + { + texhitlist[smf->skinIDs[i].GetIndex()] |= FTexture::TEX_Flat; + } + else if (smf->modelIDs[i] != -1) + { + Models[smf->modelIDs[i]]->AddSkins(texhitlist); + } + if (smf->modelIDs[i] != -1) + { + modellist[smf->modelIDs[i]] = 1; + } + } + } } } - // Precache textures (and sprites). - + // mark all sprite textures belonging to the marked sprites. for (int i = (int)(sprites.Size() - 1); i >= 0; i--) { if (spritelist[i].CountUsed()) @@ -1129,14 +1132,59 @@ void FGLInterface::Precache(BYTE *texhitlist, TMap &actorhit } } + // delete everything unused before creating any new resources to avoid memory usage peaks. + + // delete unused models + for (unsigned i = 0; i < Models.Size(); i++) + { + if (!modellist[i]) Models[i]->DestroyVertexBuffer(); + } + + // delete unused textures int cnt = TexMan.NumTextures(); for (int i = cnt - 1; i >= 0; i--) { - PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]); - if (spritehitlist[i] != nullptr) PrecacheSprite(TexMan.ByIndex(i), *spritehitlist[i]); + FTexture *tex = TexMan.ByIndex(i); + if (tex != nullptr) + { + if (!texhitlist[i]) + { + if (tex->gl_info.Material[0]) tex->gl_info.Material[0]->Clean(true); + } + if (spritehitlist[i] == nullptr || (*spritehitlist[i]).CountUsed() == 0) + { + if (tex->gl_info.Material[1]) tex->gl_info.Material[1]->Clean(true); + } + } } + + if (gl_precache) + { + // cache all used textures + for (int i = cnt - 1; i >= 0; i--) + { + FTexture *tex = TexMan.ByIndex(i); + if (tex != nullptr) + { + PrecacheTexture(tex, texhitlist[i]); + if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0) + { + PrecacheSprite(tex, *spritehitlist[i]); + } + } + } + + // cache all used models + for (unsigned i = 0; i < Models.Size(); i++) + { + if (modellist[i]) + Models[i]->BuildVertexBuffer(); + } + } + delete[] spritehitlist; delete[] spritelist; + delete[] modellist; } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 3f90b251e..c85de8a0d 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -287,8 +287,8 @@ void GLSprite::Draw(int pass) if (drawBillboardFacingCamera) { // [CMB] Rotate relative to camera XY position, not just camera direction, // which is nicer in VR - float xrel = xcenter - GLRenderer->mViewActor->X(); - float yrel = ycenter - GLRenderer->mViewActor->Y(); + float xrel = xcenter - ViewPos.X; + float yrel = ycenter - ViewPos.Y; float absAngleDeg = RAD2DEG(atan2(-yrel, xrel)); float counterRotationDeg = 270. - GLRenderer->mAngles.Yaw.Degrees; // counteracts existing sprite rotation float relAngleDeg = counterRotationDeg + absAngleDeg; diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 0d8096e76..fdf78ee6f 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -171,10 +171,13 @@ public: private: void CheckGlowing(); + bool PutWallCompat(int passflag); void PutWall(bool translucent); void PutPortal(int ptype); void CheckTexturePosition(); + void RenderFogBoundaryCompat(); + void Put3DWall(lightlist_t * lightlist, bool translucent); void SplitWallComplex(sector_t * frontsector, bool translucent, float maplightbottomleft, float maplightbottomright); void SplitWall(sector_t * frontsector, bool translucent); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index ae7cb70c8..906f7f3e1 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -139,6 +139,11 @@ void GLWall::PutWall(bool translucent) } else { + if (gl.lightmethod == LM_SOFTWARE && !translucent) + { + // This is not yet ready. + //if (PutWallCompat(passflag[type])) return; + } bool masked; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 8fe9d948e..9fe120ae2 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -228,16 +228,23 @@ void GLWall::RenderFogBoundary() { if (gl_fogmode && gl_fixedcolormap == 0) { - int rel = rellight + getExtraLight(); - gl_SetFog(lightlevel, rel, &Colormap, false); - gl_RenderState.SetEffect(EFF_FOGBOUNDARY); - gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -128.0f); - RenderWall(RWF_BLANK); - glPolygonOffset(0.0f, 0.0f); - glDisable(GL_POLYGON_OFFSET_FILL); - gl_RenderState.SetEffect(EFF_NONE); + if (gl.glslversion > 0.f) + { + int rel = rellight + getExtraLight(); + gl_SetFog(lightlevel, rel, &Colormap, false); + gl_RenderState.SetEffect(EFF_FOGBOUNDARY); + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -128.0f); + RenderWall(RWF_BLANK); + glPolygonOffset(0.0f, 0.0f); + glDisable(GL_POLYGON_OFFSET_FILL); + gl_RenderState.SetEffect(EFF_NONE); + } + else + { + RenderFogBoundaryCompat(); + } } } @@ -255,12 +262,19 @@ void GLWall::RenderMirrorSurface() Vector v(glseg.y2-glseg.y1, 0 ,-glseg.x2+glseg.x1); v.Normalize(); - // we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is. - lolft.u = lorgt.u = uplft.u = uprgt.u = v.X(); - lolft.v = lorgt.v = uplft.v = uprgt.v = v.Z(); + if (gl.glslversion >= 0.f) + { + // we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is. + lolft.u = lorgt.u = uplft.u = uprgt.u = v.X(); + lolft.v = lorgt.v = uplft.v = uprgt.v = v.Z(); - gl_RenderState.EnableTextureMatrix(true); - gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix); + gl_RenderState.EnableTextureMatrix(true); + gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix); + } + else + { + glNormal3fv(&v[0]); + } // Use sphere mapping for this gl_RenderState.SetEffect(EFF_SPHEREMAP); diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index e6e802e5c..7d091ebb6 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -168,7 +168,7 @@ void gl_LoadExtensions() gl.vendorstring = (char*)glGetString(GL_VENDOR); gl.lightmethod = LM_SOFTWARE; - if (gl.version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) + if ((gl.version >= 3.3f || CheckExtension("GL_ARB_sampler_objects")) && !Args->CheckParm("-nosampler")) { gl.flags |= RFL_SAMPLER_OBJECTS; } diff --git a/src/gl/system/gl_load.c b/src/gl/system/gl_load.c index 9b89f2880..aed4e0ff8 100644 --- a/src/gl/system/gl_load.c +++ b/src/gl/system/gl_load.c @@ -42,6 +42,8 @@ static void* SunGetProcAddress (const GLubyte* name) #if defined(_WIN32) #ifdef _MSC_VER +// disable inlining here because it creates an incredible amount of bloat in this file. +#pragma inline_depth(0) #pragma warning(disable: 4055) #pragma warning(disable: 4054) #pragma warning(disable: 4996) diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index 5207ea00d..6a579b0d5 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -300,7 +300,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla translation = GLTranslationPalette::GetInternalTranslation(translation); } - bool needmipmap = (clampmode <= CLAMP_XY) || !(gl.flags & RFL_SAMPLER_OBJECTS); + bool needmipmap = (clampmode <= CLAMP_XY); FHardwareTexture *hwtex = CreateHwTexture(); @@ -345,9 +345,9 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla } delete[] buffer; } - if (!needmipmap) clampmode = CLAMP_XY_NOMIP; if (tex->bHasCanvas) static_cast(tex)->NeedUpdate(); - if (lastSampler != clampmode || lastTranslation != translation) + if (translation != lastTranslation) lastSampler = 254; + if (lastSampler != clampmode) lastSampler = GLRenderer->mSamplerManager->Bind(texunit, clampmode, lastSampler); lastTranslation = translation; return hwtex; diff --git a/src/gl/textures/gl_samplers.cpp b/src/gl/textures/gl_samplers.cpp index db0193c69..cee2fd894 100644 --- a/src/gl/textures/gl_samplers.cpp +++ b/src/gl/textures/gl_samplers.cpp @@ -86,7 +86,6 @@ void FSamplerManager::UnbindAll() { for (int i = 0; i < FHardwareTexture::MAX_TEXTURES; i++) { - mLastBound[i] = 0; glBindSampler(i, 0); } } @@ -97,12 +96,8 @@ BYTE FSamplerManager::Bind(int texunit, int num, int lastval) if (gl.flags & RFL_SAMPLER_OBJECTS) { unsigned int samp = mSamplers[num]; - //if (samp != mLastBound[texunit]) - { - glBindSampler(texunit, samp); - mLastBound[texunit] = samp; - return 255; - } + glBindSampler(texunit, samp); + return 255; } else { @@ -112,7 +107,7 @@ BYTE FSamplerManager::Bind(int texunit, int num, int lastval) case CLAMP_NONE: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - if (lastval > CLAMP_XY_NOMIP) + if (lastval >= CLAMP_XY_NOMIP) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); @@ -123,7 +118,7 @@ BYTE FSamplerManager::Bind(int texunit, int num, int lastval) case CLAMP_X: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - if (lastval > CLAMP_XY_NOMIP) + if (lastval >= CLAMP_XY_NOMIP) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); @@ -134,7 +129,18 @@ BYTE FSamplerManager::Bind(int texunit, int num, int lastval) case CLAMP_Y: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (lastval > CLAMP_XY_NOMIP) + if (lastval >= CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); + } + break; + + case CLAMP_XY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval >= CLAMP_XY_NOMIP) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); @@ -143,15 +149,11 @@ BYTE FSamplerManager::Bind(int texunit, int num, int lastval) break; case CLAMP_XY_NOMIP: - case CLAMP_XY: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (lastval > CLAMP_XY_NOMIP) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].minfilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_filter_anisotropic); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[gl_texture_filter].magfilter); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); break; case CLAMP_NOFILTER: diff --git a/src/gl/textures/gl_samplers.h b/src/gl/textures/gl_samplers.h index daba65d45..b74d49a33 100644 --- a/src/gl/textures/gl_samplers.h +++ b/src/gl/textures/gl_samplers.h @@ -8,7 +8,6 @@ class FSamplerManager // We need 6 different samplers: 4 for the different clamping modes, // one for 2D-textures and one for voxel textures unsigned int mSamplers[7]; - unsigned int mLastBound[FHardwareTexture::MAX_TEXTURES]; void UnbindAll(); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 003138211..032abbc27 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5567,6 +5567,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) if (argCount >= 2) { const char *a, *b; + // If the string indicies are the same, then they are the same string. + if (args[0] == args[1]) + { + return 0; + } a = FBehavior::StaticLookupString(args[0]); b = FBehavior::StaticLookupString(args[1]); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 1ffeb813f..103ac1264 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1132,7 +1132,7 @@ FUNC(LS_Teleport_Line) static void ThrustThingHelper(AActor *it, DAngle angle, double force, INTBOOL nolimit) { - it->VelFromAngle(angle, force); + it->Thrust(angle, force); if (!nolimit) { it->Vel.X = clamp(it->Vel.X, -MAXMOVE, MAXMOVE);