diff --git a/CMakeLists.txt b/CMakeLists.txt index f1002cbc7..2b04eeb3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,7 +192,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) option(FORCE_INTERNAL_ZLIB "Use internal zlib") option(FORCE_INTERNAL_JPEG "Use internal jpeg") option(FORCE_INTERNAL_BZIP2 "Use internal bzip2") -option(FORCE_INTERNAL_GME "Use internal gme" ON) +option(FORCE_INTERNAL_GME "Use internal gme") # Fast math flags, required by some subprojects set( ZD_FASTMATH_FLAG "" ) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 1dac5ac38..2224dd9f4 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -54,6 +54,7 @@ #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderstate.h" #include "gl/scene/gl_drawinfo.h" +#include "gl/data/gl_vertexbuffer.h" //========================================================================== @@ -67,8 +68,7 @@ void gl_PatchMenu() { if (gl.glslversion == 0) { - // Radial fog and Doom lighting are not available in SM < 4 cards - // The way they are implemented does not work well on older hardware. + // Radial fog and Doom lighting are not available without full shader support. FOptionValues **opt = OptionValues.CheckKey("LightingModes"); if (opt != NULL) @@ -376,8 +376,9 @@ void FRenderState::DrawColormapOverlay() // Sets up the parameters to render one dynamic light onto one plane // //========================================================================== + bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right, - float & scale, int desaturation, bool checkside, bool forceadditive) + float & scale, int desaturation, bool checkside, bool additive) { Vector fn, pos; @@ -392,7 +393,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, { return false; } - if (light->owned && light->target != NULL && !light->target->IsVisibleToPlayer()) + if (!light->visibletoplayer) { return false; } @@ -414,7 +415,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, #endif float cs = 1.0f - (dist / radius); - if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive) cs *= 0.2f; // otherwise the light gets too strong. + if (additive) cs *= 0.2f; // otherwise the light gets too strong. float r = light->GetRed() / 255.0f * cs * gl_lights_intensity; float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity; float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity; @@ -441,7 +442,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, g = (g*(32 - desaturation) + gray*desaturation) / 32; b = (b*(32 - desaturation) + gray*desaturation) / 32; } - glColor3f(r, g, b); + gl_RenderState.SetColor(r, g, b); return true; } @@ -455,7 +456,7 @@ bool gl_SetupLightTexture() { if (GLRenderer->gllight == nullptr) return false; FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight, false); - pat->Bind(CLAMP_XY, 0); + pat->Bind(CLAMP_XY_NOMIP, 0); return true; } @@ -486,7 +487,7 @@ bool GLWall::PutWallCompat(int passflag) if (sub->lighthead != nullptr) return false; } - bool foggy = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE); + bool foggy = !gl_isBlack(Colormap.FadeColor) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; bool masked = passflag == 2 && gltexture->isMasked(); int list = list_indices[masked][foggy]; @@ -500,6 +501,34 @@ bool GLWall::PutWallCompat(int passflag) } +//========================================================================== +// +// +// +//========================================================================== + +bool GLFlat::PutFlatCompat(bool fog) +{ + // are lights possible? + if (gl_fixedcolormap != CM_DEFAULT || !gl_lights || !gltexture || renderstyle != STYLE_Translucent || alpha < 1.f - FLT_EPSILON || sector->lighthead == NULL) return false; + + static int list_indices[2][2] = + { { GLLDL_FLATS_PLAIN, GLLDL_FLATS_FOG },{ GLLDL_FLATS_MASKED, GLLDL_FLATS_FOGMASKED } }; + + bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack); + bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; + + + int list = list_indices[masked][foggy]; + if (list == GLLDL_FLATS_PLAIN) + { + if (gltexture->tex->gl_info.Brightmap && gl.glslversion >= 0.f) list = GLLDL_FLATS_BRIGHT; + } + gl_drawinfo->dldrawlists[list].AddFlat(this); + return true; +} + + //========================================================================== // // Fog boundary without any shader support @@ -530,14 +559,14 @@ void GLWall::RenderFogBoundaryCompat() glDepthFunc(GL_LEQUAL); glColor4f(fc[0], fc[1], fc[2], fogd1); glBegin(GL_TRIANGLE_FAN); - glTexCoord2f(lolft.u, lolft.v); + glTexCoord2f(tcs[LOLFT].u, tcs[LOLFT].v); glVertex3f(glseg.x1, zbottom[0], glseg.y1); - glTexCoord2f(uplft.u, uplft.v); + glTexCoord2f(tcs[UPLFT].u, tcs[UPLFT].v); glVertex3f(glseg.x1, ztop[0], glseg.y1); glColor4f(fc[0], fc[1], fc[2], fogd2); - glTexCoord2f(uprgt.u, uprgt.v); + glTexCoord2f(tcs[UPRGT].u, tcs[UPRGT].v); glVertex3f(glseg.x2, ztop[1], glseg.y2); - glTexCoord2f(lorgt.u, lorgt.v); + glTexCoord2f(tcs[LORGT].u, tcs[LORGT].v); glVertex3f(glseg.x2, zbottom[1], glseg.y2); glEnd(); glDepthFunc(GL_LESS); @@ -548,6 +577,211 @@ void GLWall::RenderFogBoundaryCompat() gl_RenderState.EnableTexture(true); } +//========================================================================== +// +// Flats +// +//========================================================================== + +void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) +{ + Plane p; + Vector nearPt, up, right, t1; + float scale; + + FLightNode * node = sub->lighthead; + while (node) + { + ADynamicLight * light = node->lightsource; + + if (light->flags2&MF2_DORMANT || + (pass == GLPASS_LIGHTTEX && light->IsAdditive()) || + (pass == GLPASS_LIGHTTEX_ADDITIVE && !light->IsAdditive())) + { + node = node->nextLight; + continue; + } + + // we must do the side check here because gl_SetupLight needs the correct plane orientation + // which we don't have for Legacy-style 3D-floors + double planeh = plane.plane.ZatPoint(light); + if (gl_lights_checkside && ((planehZ() && ceiling) || (planeh>light->Z() && !ceiling))) + { + node = node->nextLight; + continue; + } + + p.Set(plane.plane); + if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, false, pass != GLPASS_LIGHTTEX)) + { + node = node->nextLight; + continue; + } + gl_RenderState.Apply(); + + FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); + for (unsigned int k = 0; k < sub->numlines; k++) + { + vertex_t *vt = sub->firstline[k].v1; + ptr->x = vt->fX(); + ptr->z = plane.plane.ZatPoint(vt) + dz; + ptr->y = vt->fY(); + t1.Set(ptr->x, ptr->z, ptr->y); + Vector nearToVert = t1 - nearPt; + + ptr->u = (nearToVert.Dot(right) * scale) + 0.5f; + ptr->v = (nearToVert.Dot(up) * scale) + 0.5f; + ptr++; + } + GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); + node = node->nextLight; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void GLFlat::DrawLightsCompat(int pass) +{ + gl_RenderState.Apply(); + if (sub) + { + // This represents a single subsector + DrawSubsectorLights(sub, pass); + } + else + { + // Draw the subsectors belonging to this sector + for (int i = 0; isubsectorcount; i++) + { + subsector_t * sub = sector->subsectors[i]; + if (gl_drawinfo->ss_renderflags[sub - subsectors] & renderflags) + { + DrawSubsectorLights(sub, pass); + } + } + + // Draw the subsectors assigned to it due to missing textures + if (!(renderflags&SSRF_RENDER3DPLANES)) + { + gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR) ? + gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) : + gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum); + + while (node) + { + DrawSubsectorLights(sub, pass); + node = node->next; + } + } + } +} + + +//========================================================================== +// +// Sets up the texture coordinates for one light to be rendered +// +//========================================================================== +bool GLWall::PrepareLight(ADynamicLight * light, int pass) +{ + float vtx[] = { glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2 }; + Plane p; + Vector nearPt, up, right; + float scale; + + p.Init(vtx, 4); + + if (!p.ValidNormal()) + { + return false; + } + + if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, true, pass != GLPASS_LIGHTTEX)) + { + return false; + } + + if (tcs != NULL) + { + Vector t1; + int outcnt[4] = { 0,0,0,0 }; + + for (int i = 0; i<4; i++) + { + t1.Set(&vtx[i * 3]); + Vector nearToVert = t1 - nearPt; + tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f; + tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f; + + // quick check whether the light touches this polygon + if (tcs[i].u<0) outcnt[0]++; + if (tcs[i].u>1) outcnt[1]++; + if (tcs[i].v<0) outcnt[2]++; + if (tcs[i].v>1) outcnt[3]++; + + } + // The light doesn't touch this polygon + if (outcnt[0] == 4 || outcnt[1] == 4 || outcnt[2] == 4 || outcnt[3] == 4) return false; + } + + draw_dlight++; + return true; +} + + +void GLWall::RenderLightsCompat(int pass) +{ + FLightNode * node; + + // black fog is diminishing light and should affect lights less than the rest! + if (pass == GLPASS_LIGHTTEX) gl_SetFog((255 + lightlevel) >> 1, 0, NULL, false); + else gl_SetFog(lightlevel, 0, &Colormap, true); + + if (seg->sidedef == NULL) + { + return; + } + else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) + { + // Iterate through all dynamic lights which touch this wall and render them + node = seg->sidedef->lighthead; + } + else if (sub) + { + // To avoid constant rechecking for polyobjects use the subsector's lightlist instead + node = sub->lighthead; + } + else + { + return; + } + + texcoord save[4]; + memcpy(save, tcs, sizeof(tcs)); + while (node) + { + ADynamicLight * light = node->lightsource; + + if (light->flags2&MF2_DORMANT || + (pass == GLPASS_LIGHTTEX && light->IsAdditive()) || + (pass == GLPASS_LIGHTTEX_ADDITIVE && !light->IsAdditive())) + { + node = node->nextLight; + continue; + } + if (PrepareLight(light, pass)) + { + RenderWall(RWF_TEXTURED, NULL); + } + node = node->nextLight; + } + memcpy(tcs, save, sizeof(tcs)); +} + //========================================================================== // // @@ -556,7 +790,6 @@ void GLWall::RenderFogBoundaryCompat() void FGLRenderer::RenderMultipassStuff() { - return; // First pass: empty background with sector light only // Part 1: solid geometry. This is set up so that there are no transparent parts @@ -565,25 +798,28 @@ void FGLRenderer::RenderMultipassStuff() gl_RenderState.EnableTexture(false); gl_RenderState.EnableBrightmap(false); gl_RenderState.Apply(); - gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_BASE); - gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_BASE); + gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_PLAIN); + gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_PLAIN); // Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show // This creates a blank surface that only fills the nontransparent parts of the texture gl_RenderState.EnableTexture(true); gl_RenderState.SetTextureMode(TM_MASK); gl_RenderState.EnableBrightmap(true); - gl_drawinfo->dldrawlists[GLLDL_WALLS_BRIGHT].DrawWalls(GLPASS_BASE_MASKED); - gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_BASE_MASKED); - gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_BASE_MASKED); - gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_BASE_MASKED); + gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + gl_drawinfo->dldrawlists[GLLDL_WALLS_BRIGHT].DrawWalls(GLPASS_PLAIN); + gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_PLAIN); + gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_PLAIN); + gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_PLAIN); // Part 3: The base of fogged surfaces, including the texture gl_RenderState.EnableBrightmap(false); gl_RenderState.SetTextureMode(TM_MODULATE); + gl_RenderState.AlphaFunc(GL_GEQUAL, 0); gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_PLAIN); - gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN); gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_PLAIN); + gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN); gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_PLAIN); // second pass: draw lights @@ -632,11 +868,18 @@ void FGLRenderer::RenderMultipassStuff() gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); - gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE); - gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE); - gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); - gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); + gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_FOGGY); + gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_FOGGY); + gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_FOGGY); + gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_FOGGY); } else gl_lights = false; + + glDepthFunc(GL_LESS); + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + gl_RenderState.EnableFog(true); + gl_RenderState.BlendFunc(GL_ONE, GL_ZERO); + glDepthMask(true); + } diff --git a/src/gl/dynlights/a_dynlight.cpp b/src/gl/dynlights/a_dynlight.cpp index 36382ce36..5458f0479 100644 --- a/src/gl/dynlights/a_dynlight.cpp +++ b/src/gl/dynlights/a_dynlight.cpp @@ -160,6 +160,7 @@ void ADynamicLight::BeginPlay() m_Radius[0] = args[LIGHT_INTENSITY]; m_Radius[1] = args[LIGHT_SECONDARY_INTENSITY]; + visibletoplayer = true; } //========================================================================== @@ -237,6 +238,7 @@ void ADynamicLight::Tick() return; } if (target->flags & MF_UNMORPHED) return; + visibletoplayer = target->IsVisibleToPlayer(); // cache this value for the renderer to speed up calculations. } // Don't bother if the light won't be shown diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index 5759d4cb8..513245be5 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -116,6 +116,7 @@ public: bool owned; bool halo; BYTE color2[3]; + bool visibletoplayer; int bufferindex; // intermediate texture coordinate data diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index e2187c59c..c87cb52c2 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -170,7 +170,10 @@ FModelVertex *FModelVertexBuffer::LockVertexBuffer(unsigned int size) { 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); + if (gl.version >= 3.0) + return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + else + return (FModelVertex*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); } else { @@ -208,7 +211,10 @@ unsigned int *FModelVertexBuffer::LockIndexBuffer(unsigned int size) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size * sizeof(unsigned int), NULL, GL_STATIC_DRAW); - return (unsigned int*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, size * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (gl.version >= 3.0) + return (unsigned int*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, size * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + else + return (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); } else { @@ -519,6 +525,7 @@ void gl_InitModels() { if (sc.Compare("model")) { + path = ""; sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; @@ -529,7 +536,6 @@ void gl_InitModels() { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } - GetDefaultByType(smf.type)->hasmodel=true; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -743,6 +749,7 @@ void gl_InitModels() if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); + GetDefaultByType(smf.type)->hasmodel = true; map[c]=1; } } @@ -933,16 +940,19 @@ void gl_RenderModel(GLSprite * spr) const double x = spr->actor->Vel.X; const double y = spr->actor->Vel.Y; const double z = spr->actor->Vel.Z; - - // [BB] Calculate the pitch using spherical coordinates. - if(z || x || y) pitch = float(atan( z/sqrt(x*x+y*y) ) / M_PI * 180); - - // Correcting pitch if model is moving backwards - if(x || y) + + if (spr->actor->Vel.LengthSquared() > EQUAL_EPSILON) { - if((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1; + // [BB] Calculate the pitch using spherical coordinates. + if (z || x || y) pitch = float(atan(z / sqrt(x*x + y*y)) / M_PI * 180); + + // Correcting pitch if model is moving backwards + if (fabs(x) > EQUAL_EPSILON || fabs(y) > EQUAL_EPSILON) + { + if ((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1; + } + else pitch = fabs(pitch); } - else pitch = fabs(pitch); } if( smf->flags & MDL_ROTATING ) @@ -964,7 +974,7 @@ void gl_RenderModel(GLSprite * spr) // Applying model transformations: // 1) Applying actor angle, pitch and roll to the model gl_RenderState.mModelMatrix.rotate(-angle, 0, 1, 0); - gl_RenderState.mModelMatrix.rotate(pitch, 0, 0, 1); + gl_RenderState.mModelMatrix.rotate(-pitch, 0, 0, 1); gl_RenderState.mModelMatrix.rotate(-roll, 1, 0, 0); // 2) Applying Doomsday like rotation of the weapon pickup models diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index d638feaf3..0a0049426 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -95,7 +95,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mSkyVBO = NULL; gl_spriteindex = 0; mShaderManager = NULL; - glpart2 = glpart = mirrortexture = NULL; + gllight = glpart2 = glpart = mirrortexture = NULL; mLights = NULL; } @@ -112,6 +112,7 @@ void FGLRenderer::Initialize() } else mVAOID = 0; + gllight = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/gllight.png"), FTexture::TEX_MiscPatch); glpart2 = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart2.png"), FTexture::TEX_MiscPatch); glpart = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart.png"), FTexture::TEX_MiscPatch); mirrortexture = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/mirror.png"), FTexture::TEX_MiscPatch); @@ -350,7 +351,7 @@ void FGLRenderer::DrawTexture(FTexture *img, DrawParms &parms) if (pal) translation = -pal->GetIndex(); } } - gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, 0, !!(parms.style.Flags & STYLEF_RedIsAlpha)); + gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, -1, !!(parms.style.Flags & STYLEF_RedIsAlpha)); u1 = gltex->GetUL(); v1 = gltex->GetVT(); diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index a444dbe62..0dc8efd84 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -326,7 +326,7 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) GLWall * ws1; ws1=&walls[walls.Size()-1]; ws=&walls[drawitems[sort->itemindex].index]; // may have been reallocated! - float newtexv = ws->uplft.v + ((ws->lolft.v - ws->uplft.v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]); + float newtexv = ws->tcs[GLWall::UPLFT].v + ((ws->tcs[GLWall::LOLFT].v - ws->tcs[GLWall::UPLFT].v) / (ws->zbottom[0] - ws->ztop[0])) * (fh->z - ws->ztop[0]); // I make the very big assumption here that translucent walls in sloped sectors // and 3D-floors never coexist in the same level. If that were the case this @@ -334,12 +334,12 @@ void GLDrawList::SortWallIntoPlane(SortNode * head,SortNode * sort) if (!ceiling) { ws->ztop[1] = ws1->zbottom[1] = ws->ztop[0] = ws1->zbottom[0] = fh->z; - ws->uprgt.v = ws1->lorgt.v = ws->uplft.v = ws1->lolft.v = newtexv; + ws->tcs[GLWall::UPRGT].v = ws1->tcs[GLWall::LORGT].v = ws->tcs[GLWall::UPLFT].v = ws1->tcs[GLWall::LOLFT].v = newtexv; } else { ws1->ztop[1] = ws->zbottom[1] = ws1->ztop[0] = ws->zbottom[0] = fh->z; - ws1->uplft.v = ws->lolft.v = ws1->uprgt.v = ws->lorgt.v=newtexv; + ws1->tcs[GLWall::UPLFT].v = ws->tcs[GLWall::LOLFT].v = ws1->tcs[GLWall::UPRGT].v = ws->tcs[GLWall::LORGT].v=newtexv; } } @@ -462,7 +462,7 @@ void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) float ix=(float)(ws->glseg.x1+r*(ws->glseg.x2-ws->glseg.x1)); float iy=(float)(ws->glseg.y1+r*(ws->glseg.y2-ws->glseg.y1)); - float iu=(float)(ws->uplft.u + r * (ws->uprgt.u - ws->uplft.u)); + float iu=(float)(ws->tcs[GLWall::UPLFT].u + r * (ws->tcs[GLWall::UPRGT].u - ws->tcs[GLWall::UPLFT].u)); float izt=(float)(ws->ztop[0]+r*(ws->ztop[1]-ws->ztop[0])); float izb=(float)(ws->zbottom[0]+r*(ws->zbottom[1]-ws->zbottom[0])); @@ -475,7 +475,7 @@ void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort) ws1->glseg.y1=ws->glseg.y2=iy; ws1->ztop[0]=ws->ztop[1]=izt; ws1->zbottom[0]=ws->zbottom[1]=izb; - ws1->lolft.u = ws1->uplft.u = ws->lorgt.u = ws->uprgt.u = iu; + ws1->tcs[GLWall::LOLFT].u = ws1->tcs[GLWall::UPLFT].u = ws->tcs[GLWall::LORGT].u = ws->tcs[GLWall::UPRGT].u = iu; SortNode * sort2=SortNodes.GetNew(); memset(sort2,0,sizeof(SortNode)); diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 744ffeef4..124440eee 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -61,6 +61,7 @@ enum Drawpasses GLPASS_LIGHTTEX, // lighttexture pass GLPASS_TEXONLY, // finishing texture pass GLPASS_LIGHTTEX_ADDITIVE, // lighttexture pass (additive) + GLPASS_LIGHTTEX_FOGGY, // lighttexture pass on foggy surfaces (forces all lights to be additive) }; diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 7406bb20e..850a93615 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -443,6 +443,11 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG } if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; + + case GLPASS_LIGHTTEX: + case GLPASS_LIGHTTEX_ADDITIVE: + DrawLightsCompat(pass); + break; } } @@ -463,6 +468,10 @@ inline void GLFlat::PutFlat(bool fog) { Colormap.Clear(); } + if (gl.lightmethod == LM_SOFTWARE) + { + if (PutFlatCompat(fog)) return; + } if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog || gltexture == NULL) { // translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list. diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index c85de8a0d..97e041497 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -596,8 +596,12 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) { if (!(thing->flags7 & MF7_FLYCHEAT) && thing->target == GLRenderer->mViewActor && GLRenderer->mViewActor != NULL) { - double clipdist = clamp(thing->Speed, thing->target->radius, thing->target->radius * 2); - if ((thingpos - ViewPos).LengthSquared() < clipdist * clipdist) return; + double speed = thing->Vel.Length(); + if (speed >= thing->target->radius / 2) + { + double clipdist = clamp(thing->Speed, thing->target->radius, thing->target->radius * 2); + if ((thingpos - ViewPos).LengthSquared() < clipdist * clipdist) return; + } } thing->flags7 |= MF7_FLYCHEAT; // do this only once for the very first frame, but not if it gets into range again. } diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index dfc3a6294..b25fc30f0 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -75,57 +75,52 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * while (node) { light=node->lightsource; - //if (!light->owned || light->target == NULL || light->target->IsVisibleToPlayer()) + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self)) { - if (!(light->flags2&MF2_DORMANT) && - (!(light->flags4&MF4_DONTLIGHTSELF) || light->target != self)) + float dist; + + // This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not. + // This will do the calculations explicitly rather than calling one of AActor's utility functions. + if (Displacements.size > 0) { - float dist; + int fromgroup = light->Sector->PortalGroup; + int togroup = subsec->sector->PortalGroup; + if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; - // This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not. - // This will do the calculations explicitly rather than calling one of AActor's utility functions. - if (Displacements.size > 0) + DVector2 offset = Displacements.getOffset(fromgroup, togroup); + dist = FVector3(x - light->X() - offset.X, y - light->Y() - offset.Y, z - light->Z()).LengthSquared(); + } + else + { + direct: + dist = FVector3(x - light->X(), y - light->Y(), z - light->Z()).LengthSquared(); + } + + radius = light->GetRadius() * gl_lights_size; + + if (dist < radius * radius) + { + dist = sqrtf(dist); // only calculate the square root if we really need it. + + frac = 1.0f - (dist / radius); + + if (frac > 0) { - int fromgroup = light->Sector->PortalGroup; - int togroup = subsec->sector->PortalGroup; - if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct; - - DVector2 offset = Displacements.getOffset(fromgroup, togroup); - dist = FVector3(x - light->X() - offset.X, y - light->Y() - offset.Y, z - light->Z()).LengthSquared(); - } - else - { - direct: - dist = FVector3(x - light->X(), y - light->Y(), z - light->Z()).LengthSquared(); - } - // This is to avoid calling the software-implemented sqrt function which gets used by FVector3::Length(). - // With fast math on in this module this call will be mapped to a machine instruction on most platforms. - dist = sqrtf(dist); - - radius = light->GetRadius() * gl_lights_size; - - if (dist < radius) - { - frac = 1.0f - (dist / radius); - - if (frac > 0) + lr = light->GetRed() / 255.0f * gl_lights_intensity; + lg = light->GetGreen() / 255.0f * gl_lights_intensity; + lb = light->GetBlue() / 255.0f * gl_lights_intensity; + if (light->IsSubtractive()) { - lr = light->GetRed() / 255.0f * gl_lights_intensity; - lg = light->GetGreen() / 255.0f * gl_lights_intensity; - lb = light->GetBlue() / 255.0f * gl_lights_intensity; - if (light->IsSubtractive()) - { - float bright = FVector3(lr, lg, lb).Length(); - FVector3 lightColor(lr, lg, lb); - lr = (bright - lr) * -1; - lg = (bright - lg) * -1; - lb = (bright - lb) * -1; - } - - out[0] += lr * frac; - out[1] += lg * frac; - out[2] += lb * frac; + float bright = FVector3(lr, lg, lb).Length(); + FVector3 lightColor(lr, lg, lb); + lr = (bright - lr) * -1; + lg = (bright - lg) * -1; + lb = (bright - lb) * -1; } + + out[0] += lr * frac; + out[1] += lg * frac; + out[2] += lb * frac; } } } diff --git a/src/gl/scene/gl_vertex.cpp b/src/gl/scene/gl_vertex.cpp index 3c41f52bd..27ad8e059 100644 --- a/src/gl/scene/gl_vertex.cpp +++ b/src/gl/scene/gl_vertex.cpp @@ -61,14 +61,14 @@ EXTERN_CVAR(Bool, gl_seamless) // //========================================================================== -void GLWall::SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr) +void GLWall::SplitUpperEdge(FFlatVertex *&ptr) { if (seg == NULL || seg->sidedef == NULL || (seg->sidedef->Flags & WALLF_POLYOBJ) || seg->sidedef->numsegs == 1) return; side_t *sidedef = seg->sidedef; float polyw = glseg.fracright - glseg.fracleft; - float facu = (tcs[2].u - tcs[1].u) / polyw; - float facv = (tcs[2].v - tcs[1].v) / polyw; + float facu = (tcs[UPRGT].u - tcs[UPLFT].u) / polyw; + float facv = (tcs[UPRGT].v - tcs[UPLFT].v) / polyw; float fact = (ztop[1] - ztop[0]) / polyw; float facc = (zceil[1] - zceil[0]) / polyw; float facf = (zfloor[1] - zfloor[0]) / polyw; @@ -85,8 +85,8 @@ void GLWall::SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr) ptr->x = cseg->v2->fX(); ptr->y = cseg->v2->fY(); ptr->z = ztop[0] + fact * fracfac; - ptr->u = tcs[1].u + facu * fracfac; - ptr->v = tcs[1].v + facv * fracfac; + ptr->u = tcs[UPLFT].u + facu * fracfac; + ptr->v = tcs[UPLFT].v + facv * fracfac; ptr++; } } @@ -97,14 +97,14 @@ void GLWall::SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr) // //========================================================================== -void GLWall::SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr) +void GLWall::SplitLowerEdge(FFlatVertex *&ptr) { if (seg == NULL || seg->sidedef == NULL || (seg->sidedef->Flags & WALLF_POLYOBJ) || seg->sidedef->numsegs == 1) return; side_t *sidedef = seg->sidedef; float polyw = glseg.fracright - glseg.fracleft; - float facu = (tcs[3].u - tcs[0].u) / polyw; - float facv = (tcs[3].v - tcs[0].v) / polyw; + float facu = (tcs[LORGT].u - tcs[LOLFT].u) / polyw; + float facv = (tcs[LORGT].v - tcs[LOLFT].v) / polyw; float facb = (zbottom[1] - zbottom[0]) / polyw; float facc = (zceil[1] - zceil[0]) / polyw; float facf = (zfloor[1] - zfloor[0]) / polyw; @@ -121,8 +121,8 @@ void GLWall::SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr) ptr->x = cseg->v2->fX(); ptr->y = cseg->v2->fY(); ptr->z = zbottom[0] + facb * fracfac; - ptr->u = tcs[0].u + facu * fracfac; - ptr->v = tcs[0].v + facv * fracfac; + ptr->u = tcs[LOLFT].u + facu * fracfac; + ptr->v = tcs[LOLFT].v + facv * fracfac; ptr++; } } @@ -133,7 +133,7 @@ void GLWall::SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr) // //========================================================================== -void GLWall::SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr) +void GLWall::SplitLeftEdge(FFlatVertex *&ptr) { if (vertexes[0] == NULL) return; @@ -144,8 +144,8 @@ void GLWall::SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr) int i = 0; float polyh1 = ztop[0] - zbottom[0]; - float factv1 = polyh1 ? (tcs[1].v - tcs[0].v) / polyh1 : 0; - float factu1 = polyh1 ? (tcs[1].u - tcs[0].u) / polyh1 : 0; + float factv1 = polyh1 ? (tcs[UPLFT].v - tcs[LOLFT].v) / polyh1 : 0; + float factu1 = polyh1 ? (tcs[UPLFT].u - tcs[LOLFT].u) / polyh1 : 0; while (inumheights && vi->heightlist[i] <= zbottom[0]) i++; while (inumheights && vi->heightlist[i] < ztop[0]) @@ -153,8 +153,8 @@ void GLWall::SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr) ptr->x = glseg.x1; ptr->y = glseg.y1; ptr->z = vi->heightlist[i]; - ptr->u = factu1*(vi->heightlist[i] - ztop[0]) + tcs[1].u; - ptr->v = factv1*(vi->heightlist[i] - ztop[0]) + tcs[1].v; + ptr->u = factu1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].u; + ptr->v = factv1*(vi->heightlist[i] - ztop[0]) + tcs[UPLFT].v; ptr++; i++; } @@ -167,7 +167,7 @@ void GLWall::SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr) // //========================================================================== -void GLWall::SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr) +void GLWall::SplitRightEdge(FFlatVertex *&ptr) { if (vertexes[1] == NULL) return; @@ -178,8 +178,8 @@ void GLWall::SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr) int i = vi->numheights - 1; float polyh2 = ztop[1] - zbottom[1]; - float factv2 = polyh2 ? (tcs[2].v - tcs[3].v) / polyh2 : 0; - float factu2 = polyh2 ? (tcs[2].u - tcs[3].u) / polyh2 : 0; + float factv2 = polyh2 ? (tcs[UPRGT].v - tcs[LORGT].v) / polyh2 : 0; + float factu2 = polyh2 ? (tcs[UPRGT].u - tcs[LORGT].u) / polyh2 : 0; while (i>0 && vi->heightlist[i] >= ztop[1]) i--; while (i>0 && vi->heightlist[i] > zbottom[1]) @@ -187,8 +187,8 @@ void GLWall::SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr) ptr->x = glseg.x2; ptr->y = glseg.y2; ptr->z = vi->heightlist[i]; - ptr->u = factu2*(vi->heightlist[i] - ztop[1]) + tcs[2].u; - ptr->v = factv2*(vi->heightlist[i] - ztop[1]) + tcs[2].v; + ptr->u = factu2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].u; + ptr->v = factv2*(vi->heightlist[i] - ztop[1]) + tcs[UPRGT].v; ptr++; i--; } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index fdf78ee6f..fdeb99ed0 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -119,6 +119,13 @@ public: RWF_NORENDER = 8, }; + enum + { + LOLFT, + UPLFT, + UPRGT, + LORGT, + }; friend struct GLDrawList; friend class GLPortal; @@ -126,7 +133,7 @@ public: GLSeg glseg; vertex_t * vertexes[2]; // required for polygon splitting float ztop[2],zbottom[2]; - texcoord uplft, uprgt, lolft, lorgt; + texcoord tcs[4]; float alpha; FMaterial *gltexture; @@ -177,13 +184,14 @@ private: void CheckTexturePosition(); void RenderFogBoundaryCompat(); + void RenderLightsCompat(int pass); 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); void SetupLights(); - bool PrepareLight(texcoord * tcs, ADynamicLight * light); + bool PrepareLight(ADynamicLight * light, int pass); void RenderWall(int textured, unsigned int *store = NULL); void RenderTextured(int rflags); @@ -236,10 +244,10 @@ private: void RenderMirrorSurface(); void RenderTranslucentWall(); - void SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr); - void SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr); - void SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr); - void SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr); + void SplitLeftEdge (FFlatVertex *&ptr); + void SplitRightEdge(FFlatVertex *&ptr); + void SplitUpperEdge(FFlatVertex *&ptr); + void SplitLowerEdge(FFlatVertex *&ptr); public: @@ -288,7 +296,6 @@ public: GLSectorPlane plane; int lightlevel; bool stack; - bool foggy; bool ceiling; BYTE renderflags; int vboindex; @@ -296,9 +303,13 @@ public: int dynlightindex; + // compatibility fallback stuff. + void DrawSubsectorLights(subsector_t * sub, int pass); + void DrawLightsCompat(int pass); + bool PutFlatCompat(bool fog); + void SetupSubsectorLights(int pass, subsector_t * sub, int *dli = NULL); void DrawSubsector(subsector_t * sub); - void DrawSubsectorLights(subsector_t * sub, int pass); void DrawSkyboxSector(int pass, bool processlights); void DrawSubsectors(int pass, bool processlights, bool istrans); void ProcessLights(bool istrans); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 906f7f3e1..edd85e1df 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -142,7 +142,7 @@ void GLWall::PutWall(bool translucent) if (gl.lightmethod == LM_SOFTWARE && !translucent) { // This is not yet ready. - //if (PutWallCompat(passflag[type])) return; + if (PutWallCompat(passflag[type])) return; } bool masked; @@ -297,10 +297,10 @@ void GLWall::SplitWallComplex(sector_t * frontsector, bool translucent, float ma 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); + copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u); + copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v); + copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u); + copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v); copyWall1.SplitWall(frontsector, translucent); copyWall2.SplitWall(frontsector, translucent); @@ -338,10 +338,10 @@ void GLWall::SplitWallComplex(sector_t * frontsector, bool translucent, float ma 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); + copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u); + copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v); + copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u); + copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v); copyWall1.SplitWall(frontsector, translucent); copyWall2.SplitWall(frontsector, translucent); @@ -432,10 +432,10 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent) 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]); + tcs[UPLFT].v=copyWall1.tcs[LOLFT].v=copyWall1.tcs[UPLFT].v+ + (maplightbottomleft-copyWall1.ztop[0])*(copyWall1.tcs[LOLFT].v-copyWall1.tcs[UPLFT].v)/(zbottom[0]-copyWall1.ztop[0]); + tcs[UPRGT].v=copyWall1.tcs[LORGT].v=copyWall1.tcs[UPRGT].v+ + (maplightbottomright-copyWall1.ztop[1])*(copyWall1.tcs[LORGT].v-copyWall1.tcs[UPRGT].v)/(zbottom[1]-copyWall1.ztop[1]); copyWall1.Put3DWall(&lightlist[i], translucent); } if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1]) @@ -574,8 +574,8 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto if (tci) { - uplft.v = tci->FloatToTexV(-ztop[0] + texturetop); - lolft.v = tci->FloatToTexV(-zbottom[0] + texturetop); + tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop); + tcs[LOLFT].v = tci->FloatToTexV(-zbottom[0] + texturetop); } } else @@ -595,7 +595,7 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto if (tci) { - lolft.v = uplft.v = tci->FloatToTexV(-ztop[0] + texturetop); + tcs[LOLFT].v = tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop); } } @@ -612,8 +612,8 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto if (tci) { - uprgt.v = tci->FloatToTexV(-ztop[1] + texturetop); - lorgt.v = tci->FloatToTexV(-zbottom[1] + texturetop); + tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); + tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop); } } else @@ -632,12 +632,12 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto zbottom[1] = ztop[1] = inter_y; if (tci) { - lorgt.v = uprgt.v = tci->FloatToTexV(-ztop[1] + texturetop); + tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop); } } - uplft.u = lolft.u = l_ul + texlength * glseg.fracleft; - uprgt.u = lorgt.u = l_ul + texlength * glseg.fracright; + tcs[UPLFT].u = tcs[LOLFT].u = l_ul + texlength * glseg.fracleft; + tcs[UPRGT].u = tcs[LORGT].u = l_ul + texlength * glseg.fracright; if (gltexture != NULL) { @@ -646,15 +646,15 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto else if (flags & GLT_CLAMPY) { // for negative scales we can get negative coordinates here. - normalize = (uplft.v > lolft.v || uprgt.v > lorgt.v); + normalize = (tcs[UPLFT].v > tcs[LOLFT].v || tcs[UPRGT].v > tcs[LORGT].v); } if (normalize) { // we have to shift the y-coordinate from [-1..0] to [0..1] when using texture clamping with a negative scale - uplft.v += 1.f; - uprgt.v += 1.f; - lolft.v += 1.f; - lorgt.v += 1.f; + tcs[UPLFT].v += 1.f; + tcs[UPRGT].v += 1.f; + tcs[LOLFT].v += 1.f; + tcs[LORGT].v += 1.f; } } @@ -675,21 +675,21 @@ void GLWall::CheckTexturePosition() // clamp texture coordinates to a reasonable range. // Extremely large values can cause visual problems - if (uplft.v < uprgt.v) + if (tcs[UPLFT].v < tcs[UPRGT].v) { - sub = float(xs_FloorToInt(uplft.v)); + sub = float(xs_FloorToInt(tcs[UPLFT].v)); } else { - sub = float(xs_FloorToInt(uprgt.v)); + sub = float(xs_FloorToInt(tcs[UPRGT].v)); } - uplft.v -= sub; - uprgt.v -= sub; - lolft.v -= sub; - lorgt.v -= sub; + tcs[UPLFT].v -= sub; + tcs[UPRGT].v -= sub; + tcs[LOLFT].v -= sub; + tcs[LORGT].v -= sub; - if ((uplft.v == 0.f && uprgt.v == 0.f && lolft.v <= 1.f && lorgt.v <= 1.f) || - (uplft.v >= 0.f && uprgt.v >= 0.f && lolft.v == 1.f && lorgt.v == 1.f)) + if ((tcs[UPLFT].v == 0.f && tcs[UPRGT].v == 0.f && tcs[LOLFT].v <= 1.f && tcs[LORGT].v <= 1.f) || + (tcs[UPLFT].v >= 0.f && tcs[UPRGT].v >= 0.f && tcs[LOLFT].v == 1.f && tcs[LORGT].v == 1.f)) { flags |= GLT_CLAMPY; } @@ -698,13 +698,13 @@ void GLWall::CheckTexturePosition() // This intentionally only tests the seg's frontsector. if (seg->frontsector->special == GLSector_Skybox) { - sub = (float)xs_FloorToInt(uplft.u); - uplft.u -= sub; - uprgt.u -= sub; - lolft.u -= sub; - lorgt.u -= sub; - if ((uplft.u == 0.f && lolft.u == 0.f && uprgt.u <= 1.f && lorgt.u <= 1.f) || - (uplft.u >= 0.f && lolft.u >= 0.f && uprgt.u == 1.f && lorgt.u == 1.f)) + sub = (float)xs_FloorToInt(tcs[UPLFT].u); + tcs[UPLFT].u -= sub; + tcs[UPRGT].u -= sub; + tcs[LOLFT].u -= sub; + tcs[LORGT].u -= sub; + if ((tcs[UPLFT].u == 0.f && tcs[LOLFT].u == 0.f && tcs[UPRGT].u <= 1.f && tcs[LORGT].u <= 1.f) || + (tcs[UPLFT].u >= 0.f && tcs[LOLFT].u >= 0.f && tcs[UPRGT].u == 1.f && tcs[LORGT].u == 1.f)) { flags |= GLT_CLAMPX; } @@ -1039,10 +1039,10 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // split the poly! GLWall split; int i,t=0; - float v_factor=(zbottom[0]-ztop[0])/(lolft.v-uplft.v); + float v_factor=(zbottom[0]-ztop[0])/(tcs[LOLFT].v-tcs[UPLFT].v); // only split the vertical area of the polygon that does not contain slopes. - float splittopv = MAX(uplft.v, uprgt.v); - float splitbotv = MIN(lolft.v, lorgt.v); + float splittopv = MAX(tcs[UPLFT].v, tcs[UPRGT].v); + float splitbotv = MIN(tcs[LOLFT].v, tcs[LORGT].v); // this is split vertically into sections. for(i=0;isplittopv) { - split.ztop[0]=split.ztop[1]= ztop[0]+v_factor*(splitrect[i].top-uplft.v); - split.uplft.v=split.uprgt.v=splitrect[i].top; + split.ztop[0]=split.ztop[1]= ztop[0]+v_factor*(splitrect[i].top-tcs[UPLFT].v); + split.tcs[UPLFT].v=split.tcs[UPRGT].v=splitrect[i].top; } // the bottom line of the current segment is inside the splittable area // use the splitrect's bottom as bottom of this segment // if not use the bottom of the remaining polygon if (splitbot<=splitbotv) { - split.zbottom[0]=split.zbottom[1]=ztop[0]+v_factor*(splitbot-uplft.v); - split.lolft.v=split.lorgt.v=splitbot; + split.zbottom[0]=split.zbottom[1]=ztop[0]+v_factor*(splitbot-tcs[UPLFT].v); + split.tcs[LOLFT].v=split.tcs[LORGT].v=splitbot; } // // @@ -1166,8 +1166,8 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, texlength = tci.FloatToTexU(seg->sidedef->TexelLength); - uplft.u = lolft.u = ul + texlength * glseg.fracleft; - uprgt.u = lorgt.u = ul + texlength * glseg.fracright; + tcs[UPLFT].u = tcs[LOLFT].u = ul + texlength * glseg.fracleft; + tcs[UPRGT].u = tcs[LORGT].u = ul + texlength * glseg.fracright; float rowoffset = tci.RowOffset(seg->sidedef->GetTextureYOffset(side_t::mid)); to = (rover->flags&(FF_UPPERTEXTURE | FF_LOWERTEXTURE)) ? @@ -1175,10 +1175,10 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, to += rowoffset + rover->top.model->GetPlaneTexZ(rover->top.isceiling); - uplft.v = tci.FloatToTexV(to - ff_topleft); - uprgt.v = tci.FloatToTexV(to - ff_topright); - lolft.v = tci.FloatToTexV(to - ff_bottomleft); - lorgt.v = tci.FloatToTexV(to - ff_bottomright); + tcs[UPLFT].v = tci.FloatToTexV(to - ff_topleft); + tcs[UPRGT].v = tci.FloatToTexV(to - ff_topright); + tcs[LOLFT].v = tci.FloatToTexV(to - ff_bottomleft); + tcs[LORGT].v = tci.FloatToTexV(to - ff_bottomright); type = RENDERWALL_FFBLOCK; CheckTexturePosition(); } diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 9fe120ae2..4fd586388 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -175,14 +175,8 @@ void GLWall::SetupLights() void GLWall::RenderWall(int textured, unsigned int *store) { - static texcoord tcs[4]; // making this variable static saves us a relatively costly stack integrity check. bool split = (gl_seamless && !(textured&RWF_NOSPLIT) && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT)); - tcs[0]=lolft; - tcs[1]=uplft; - tcs[2]=uprgt; - tcs[3]=lorgt; - if (!(textured & RWF_NORENDER)) { gl_RenderState.Apply(); @@ -193,18 +187,18 @@ void GLWall::RenderWall(int textured, unsigned int *store) FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); unsigned int count, offset; - ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[0].u, tcs[0].v); + ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); ptr++; - if (split && glseg.fracleft == 0) SplitLeftEdge(tcs, ptr); - ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[1].u, tcs[1].v); + if (split && glseg.fracleft == 0) SplitLeftEdge(ptr); + ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v); ptr++; - if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs, ptr); - ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[2].u, tcs[2].v); + if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(ptr); + ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v); ptr++; - if (split && glseg.fracright == 1) SplitRightEdge(tcs, ptr); - ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[3].u, tcs[3].v); + if (split && glseg.fracright == 1) SplitRightEdge(ptr); + ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); ptr++; - if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs, ptr); + if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(ptr); count = GLRenderer->mVBO->GetCount(ptr, &offset); if (!(textured & RWF_NORENDER)) { @@ -265,8 +259,8 @@ void GLWall::RenderMirrorSurface() 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(); + tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X(); + tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z(); gl_RenderState.EnableTextureMatrix(true); gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix); @@ -448,5 +442,10 @@ void GLWall::Draw(int pass) RenderTranslucentWall(); break; } + + case GLPASS_LIGHTTEX: + case GLPASS_LIGHTTEX_ADDITIVE: + RenderLightsCompat(pass); + break; } } diff --git a/src/p_lights.cpp b/src/p_lights.cpp index 181ef1a19..564e010a3 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -302,9 +302,9 @@ void DFlicker::Tick () DFlicker::DFlicker (sector_t *sector, int upper, int lower) : DLighting (sector) { - m_MaxLight = upper; - m_MinLight = lower; - sector->lightlevel = upper; + m_MaxLight = sector_t::ClampLight(upper); + m_MinLight = sector_t::ClampLight(lower); + sector->lightlevel = m_MaxLight; m_Count = (pr_flicker()&64)+1; } diff --git a/src/sound/oalload.h b/src/sound/oalload.h index 986131b2c..3cee30d58 100644 --- a/src/sound/oalload.h +++ b/src/sound/oalload.h @@ -22,7 +22,7 @@ static oalloadentry oalfuncs[] = { { NULL, 0 } }; - +#ifndef IN_IDE_PARSER #define alEnable p_alEnable #define alDisable p_alDisable #define alIsEnabled p_alIsEnabled @@ -116,6 +116,7 @@ static oalloadentry oalfuncs[] = { #define alcCaptureStart p_alcCaptureStart #define alcCaptureStop p_alcCaptureStop #define alcCaptureSamples p_alcCaptureSamples +#endif #endif -#endif \ No newline at end of file +#endif diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 56dfb4a4c..95fa4d39a 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -40,6 +40,9 @@ #include #endif +#include +#include + #include "except.h" #include "doomstat.h" #include "templates.h" @@ -69,7 +72,7 @@ static void* hmodOpenAL; #ifdef __APPLE__ #define OPENALLIB "OpenAL.framework/OpenAL" #else -#define OPENALLIB "libopenal.so" +#define OPENALLIB "libopenal.so.1" #endif #define LoadLibrary(x) dlopen((x), RTLD_LAZY) #define GetProcAddress(a,b) dlsym((a),(b)) @@ -273,6 +276,8 @@ class OpenALSoundStream : public SoundStream alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL); alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); } + if(Renderer->AL.EXT_SOURCE_RADIUS) + alSourcef(Source, AL_SOURCE_RADIUS, 0.f); alGenBuffers(BufferCount, Buffers); return (getALError() == AL_NO_ERROR); @@ -626,12 +631,21 @@ public: extern ReverbContainer *ForcedEnvironment; -#define AREA_SOUND_RADIUS (128.f) +#define AREA_SOUND_RADIUS (32.f) #define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */ #define PITCH(pitch) (snd_pitched ? (pitch)/128.f : 1.f) +static size_t GetChannelCount(ChannelConfig chans) +{ + switch(chans) + { + case ChannelConfig_Mono: return 1; + case ChannelConfig_Stereo: return 2; + } + return 0; +} static float GetRolloff(const FRolloffInfo *rolloff, float distance) { @@ -686,7 +700,12 @@ template static void LoadALFunc(const char *name, T *x) { *x = reinterpret_cast(alGetProcAddress(name)); } +template +static void LoadALCFunc(ALCdevice *device, const char *name, T *x) +{ *x = reinterpret_cast(alcGetProcAddress(device, name)); } + #define LOAD_FUNC(x) (LoadALFunc(#x, &x)) +#define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x)) OpenALSoundRenderer::OpenALSoundRenderer() : Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0) { @@ -744,8 +763,10 @@ OpenALSoundRenderer::OpenALSoundRenderer() DPrintf(" Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS)); ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX"); - ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");; + ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect"); + ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device"); AL.EXT_source_distance_model = !!alIsExtensionPresent("AL_EXT_source_distance_model"); + AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS"); AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates"); AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points"); @@ -766,6 +787,12 @@ OpenALSoundRenderer::OpenALSoundRenderer() alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT; } + if(ALC.SOFT_pause_device) + { + LOAD_DEV_FUNC(Device, alcDevicePauseSOFT); + LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT); + } + ALenum err = getALError(); if(err != AL_NO_ERROR) { @@ -905,6 +932,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() if(EnvSlot) Printf(" EFX enabled\n"); } +#undef LOAD_DEV_FUNC #undef LOAD_FUNC OpenALSoundRenderer::~OpenALSoundRenderer() @@ -1042,7 +1070,7 @@ std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int { int sum = 0; for(int c = 0;c < channels;c++) - sum = ((short*)sfxdata)[i*channels + c]; + sum += ((short*)sfxdata)[i*channels + c]; ((short*)sfxdata)[i] = sum / channels; } } @@ -1052,7 +1080,7 @@ std::pair OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int { int sum = 0; for(int c = 0;c < channels;c++) - sum = sfxdata[i*channels + c] - 128; + sum += sfxdata[i*channels + c] - 128; sfxdata[i] = (sum / channels) + 128; } } @@ -1124,7 +1152,7 @@ std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le SampleType type; int srate; - SoundDecoder *decoder = CreateDecoder(&reader); + std::unique_ptr decoder(CreateDecoder(&reader)); if(!decoder) return std::make_pair(retval, true); decoder->getInfo(&srate, &chans, &type); @@ -1143,46 +1171,53 @@ std::pair OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le { Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans), GetSampleTypeName(type)); - delete decoder; return std::make_pair(retval, true); } TArray data = decoder->readAll(); if(chans != ChannelConfig_Mono && monoize) { - // TODO: Handle this better if ChannelConfig ever gets more channel configurations. - size_t frames = data.Size() / 2 / (type == SampleType_Int16 ? 2 : 1); + size_t chancount = GetChannelCount(chans); + size_t frames = data.Size() / chancount / + (type == SampleType_Int16 ? 2 : 1); if(type == SampleType_Int16) { short *sfxdata = (short*)&data[0]; for(size_t i = 0;i < frames;i++) - sfxdata[i] = (sfxdata[i*2 + 0]-0 + sfxdata[i*2 + 1]-0)/2; + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c]; + sfxdata[i] = sum / chancount; + } } else if(type == SampleType_UInt8) { BYTE *sfxdata = (BYTE*)&data[0]; for(size_t i = 0;i < frames;i++) - sfxdata[i] = (sfxdata[i*2 + 0]-128 + sfxdata[i*2 + 1]-128)/2 + 128; + { + int sum = 0; + for(size_t c = 0;c < chancount;c++) + sum += sfxdata[i*chancount + c] - 128; + sfxdata[i] = (sum / chancount) + 128; + } } - data.Resize(data.Size()/2); + data.Resize(data.Size()/chancount); } + ALenum err; ALuint buffer = 0; alGenBuffers(1, &buffer); alBufferData(buffer, format, &data[0], data.Size(), srate); - - ALenum err; if((err=getALError()) != AL_NO_ERROR) { Printf("Failed to buffer data: %s\n", alGetString(err)); alDeleteBuffers(1, &buffer); getALError(); - delete decoder; return std::make_pair(retval, true); } retval.data = MAKE_PTRID(buffer); - delete decoder; return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize)); } @@ -1262,6 +1297,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_ROLLOFF_FACTOR, 0.f); alSourcef(source, AL_MAX_GAIN, SfxVolume); alSourcef(source, AL_GAIN, SfxVolume*vol); + if(AL.EXT_SOURCE_RADIUS) + alSourcef(source, AL_SOURCE_RADIUS, 0.f); if(EnvSlot) { @@ -1282,7 +1319,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int else alSourcef(source, AL_PITCH, PITCH(pitch)); - if(!reuse_chan) + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) alSourcef(source, AL_SEC_OFFSET, 0.f); else { @@ -1290,8 +1327,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); else { - // FIXME: set offset based on the current time and the StartTime - alSourcef(source, AL_SEC_OFFSET, 0.f); + float offset = std::chrono::duration_cast>( + std::chrono::steady_clock::now().time_since_epoch() - + std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) + ).count(); + if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); } } if(getALError() != AL_NO_ERROR) @@ -1321,7 +1361,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int chan->Rolloff.RolloffType = ROLLOFF_Log; chan->Rolloff.RolloffFactor = 0.f; chan->Rolloff.MinDistance = 1.f; - chan->DistanceScale = 1.f; chan->DistanceSqr = 0.f; chan->ManualRolloff = false; @@ -1404,7 +1443,16 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale); dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); } - if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + if(AL.EXT_SOURCE_RADIUS) + { + /* Since the OpenAL distance is decoupled from the sound's distance, get the OpenAL + * distance that corresponds to the area radius. */ + alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? + // Clamp in case the max distance is <= the area radius + 1.f/MAX(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f + ); + } + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) { FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; @@ -1414,20 +1462,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } - else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + else { - FVector3 dir = pos - listener->position; + FVector3 dir = pos; + if(AL.EXT_SOURCE_RADIUS) + alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f); + else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + { + dir -= listener->position; - float mindist = rolloff->MinDistance/distscale; - FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); - float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; - dir = amb + (dir-amb)*a; + float mindist = rolloff->MinDistance/distscale; + FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); + float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS; + dir = amb + (dir-amb)*a; - dir += listener->position; + dir += listener->position; + } alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); } - else - alSource3f(source, AL_POSITION, pos[0], pos[1], -pos[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f); @@ -1456,7 +1508,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else alSourcef(source, AL_PITCH, PITCH(pitch)); - if(!reuse_chan) + if(!reuse_chan || reuse_chan->StartTime.AsOne == 0) alSourcef(source, AL_SEC_OFFSET, 0.f); else { @@ -1464,8 +1516,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f); else { - // FIXME: set offset based on the current time and the StartTime - alSourcef(source, AL_SAMPLE_OFFSET, 0.f); + float offset = std::chrono::duration_cast>( + std::chrono::steady_clock::now().time_since_epoch() - + std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne) + ).count(); + if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset); } } if(getALError() != AL_NO_ERROR) @@ -1493,7 +1548,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff = *rolloff; - chan->DistanceScale = distscale; chan->DistanceSqr = dist_sqr; chan->ManualRolloff = manualRolloff; @@ -1579,10 +1633,20 @@ void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state) { case SoundRenderer::INACTIVE_Active: alListenerf(AL_GAIN, 1.0f); + if(ALC.SOFT_pause_device) + { + alcDeviceResumeSOFT(Device); + getALCError(Device); + } break; - /* FIXME: This doesn't stop anything. */ case SoundRenderer::INACTIVE_Complete: + if(ALC.SOFT_pause_device) + { + alcDevicePauseSOFT(Device); + getALCError(Device); + } + /* fall-through */ case SoundRenderer::INACTIVE_Mute: alListenerf(AL_GAIN, 0.0f); break; @@ -1631,26 +1695,26 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh if(chan == NULL || chan->SysChannel == NULL) return; - alDeferUpdatesSOFT(); - FVector3 dir = pos - listener->position; chan->DistanceSqr = (float)dir.LengthSquared(); if(chan->ManualRolloff) { - if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) - { - float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale); - dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); - } - if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + if(!AL.EXT_SOURCE_RADIUS && areasound && + chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) { FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f); float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS; dir = amb + (dir-amb)*a; } + if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f))) + { + float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale); + dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f); + } } - else if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) + else if(!AL.EXT_SOURCE_RADIUS && areasound && + chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) { float mindist = chan->Rolloff.MinDistance / chan->DistanceScale; FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f); @@ -1659,6 +1723,8 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh } dir += listener->position; + alDeferUpdatesSOFT(); + ALuint source = GET_PTRID(chan->SysChannel); alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]); alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]); @@ -1802,7 +1868,7 @@ void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan) { // FIXME: Get current time (preferably from the audio clock, but the system // time will have to do) - chan->StartTime.AsOne = 0; + chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count(); } float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 2644b171a..88dcbc238 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -58,6 +58,11 @@ #define AL_FORMAT_71CHN32 0x1212 #endif +#ifndef AL_EXT_SOURCE_RADIUS +#define AL_EXT_SOURCE_RADIUS 1 +#define AL_SOURCE_RADIUS 0x1031 +#endif + #include "efx.h" @@ -124,9 +129,11 @@ private: struct { bool EXT_EFX; bool EXT_disconnect; + bool SOFT_pause_device; } ALC; struct { bool EXT_source_distance_model; + bool EXT_SOURCE_RADIUS; bool SOFT_deferred_updates; bool SOFT_loop_points; } AL; @@ -174,6 +181,9 @@ private: ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void); ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void); + void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device); + void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device); + void LoadReverb(const ReverbContainer *env); void PurgeStoppedSources(); static FSoundChan *FindLowestChannel(); diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 2d9663dbc..a8a2ddb9e 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -45,6 +45,7 @@ FWarpTexture::FWarpTexture (FTexture *source, int warptype) : GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f) { CopyInfo(source); + if (warptype == 2) SetupMultipliers(256, 128); SetupMultipliers(128, 128); // [mxd] bWarped = warptype; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 34a9cf02c..e5d080095 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2433,12 +2433,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItem) ACTION_RETURN_BOOL(true); } - if (distance == 0) - { - // use the minimum distance that does not result in an overlap - distance = (self->radius + GetDefaultByType(missile)->radius); - } - if (ACTION_CALL_FROM_WEAPON()) { // Used from a weapon, so use some ammo diff --git a/wadsrc/static/shaders/glsl/func_warp2.fp b/wadsrc/static/shaders/glsl/func_warp2.fp index 7cc5e7ebb..ee712593d 100644 --- a/wadsrc/static/shaders/glsl/func_warp2.fp +++ b/wadsrc/static/shaders/glsl/func_warp2.fp @@ -7,11 +7,10 @@ vec4 ProcessTexel() const float pi = 3.14159265358979323846; vec2 offset = vec2(0.0,0.0); - float siny = sin(pi * 2.0 * (texCoord.y * 2.2 + timer * 0.75)) * 0.03; - offset.y = siny + sin(pi * 2.0 * (texCoord.x * 0.75 + timer * 0.75)) * 0.03; - offset.x = siny + sin(pi * 2.0 * (texCoord.x * 1.1 + timer * 0.45)) * 0.02; + offset.y = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.61 + 900.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.36 + 300.0/8192.0)); + offset.x = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.49 + 700.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.49 + 1200.0/8192.0)); - texCoord += offset; + texCoord += offset * 0.025; return getTexel(texCoord); } diff --git a/wadsrc/static/shaders/glsl/func_warp3.fp b/wadsrc/static/shaders/glsl/func_warp3.fp new file mode 100644 index 000000000..a81969ca6 --- /dev/null +++ b/wadsrc/static/shaders/glsl/func_warp3.fp @@ -0,0 +1,18 @@ +uniform float timer; + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + + const float pi = 3.14159265358979323846; + vec2 offset = vec2(0.0,0.0); + + float siny = sin(pi * 2.0 * (texCoord.y * 2.0 + timer * 0.75)) * 0.03; + offset.y = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.75)) * 0.03; + offset.x = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.45)) * 0.02; + + texCoord += offset; + + return getTexel(texCoord); +} + diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index af5b30a03..0afcb9813 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -134,7 +134,7 @@ float R_DoomLightingEquation(float light, float dist) /* L in the range 0 to 63 */ float L = light * 63.0/31.0; - float min_L = clamp(36.0/31.0 - L, 0.0, 1.0); + float min_L = clamp(36.0/31.0 - L, 0.03, 1.0); // Fix objects getting totally black when close. if (dist < 0.0001)