From ab8a64743320413e70b85a40b098814fc18fc598 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 11:33:18 +0200 Subject: [PATCH 01/33] - fixed the disabled visibility rules check for dynamic lights by doing the actual check in the light's Tick() method and letting the renderer only use the result. --- src/gl/compatibility/gl_20.cpp | 2 +- src/gl/dynlights/a_dynlight.cpp | 2 + src/gl/dynlights/gl_dynlight.h | 1 + src/gl/scene/gl_spritelight.cpp | 85 ++++++++++++++++----------------- 4 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 1dac5ac38..025ae3038 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -392,7 +392,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; } 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/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; } } } From fd8a59bd249f936a702765a0025b4869e3bfc172 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 12:23:40 +0200 Subject: [PATCH 02/33] - fixed: INHERITACTORPITCH was inverted. - changed PITCHFORMOMENTUM to do nothing for very small velocities. --- src/gl/models/gl_models.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index e2187c59c..22a4913a7 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -933,16 +933,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 +967,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 From 54571beacad6974597c581e1f446f4e1561aace6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 12:28:35 +0200 Subject: [PATCH 03/33] - reset the path to "" before a model definition is parsed. --- src/gl/models/gl_models.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 22a4913a7..22cc7479f 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -519,6 +519,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; From 2c888165777235fbc3d4e5f830c7a5aa89d4b4ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 13:25:26 +0200 Subject: [PATCH 04/33] - fixed parameters for warp type 2. --- src/textures/warptexture.cpp | 1 + 1 file changed, 1 insertion(+) 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; } From 9f91fa8f4377a55b5837584f64f2f9820992851b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 13:47:40 +0200 Subject: [PATCH 05/33] - make the warp2 shader's formula match the software renderer's. This fixes some jerkiness with vertical scrollers due to a bad sine period and makes the overall appearance of the effect what it was originally supposed to be. The old warp2 shader was not created by replicating the formula but by trial and error until it looked close enough. A version of the old warp2 shader with a fixed sine period is still available as a custom hardware shader. --- wadsrc/static/shaders/glsl/func_warp2.fp | 7 +++---- wadsrc/static/shaders/glsl/func_warp3.fp | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 wadsrc/static/shaders/glsl/func_warp3.fp 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); +} + From 5f095082c0bdc5390ef31224577f0880930cbca3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 14:10:06 +0200 Subject: [PATCH 06/33] - fixed: The 2D drawing code incorrectly set the shader override to disable all special effects. --- src/gl/renderer/gl_renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index d638feaf3..7002e6b10 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -350,7 +350,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(); From bdb7594e60812155d89d6887ca426198bec98750 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 14:25:58 +0200 Subject: [PATCH 07/33] - fixed: Incomplete model definitions flagged the actor as having a model, which could cause a crash. --- src/gl/models/gl_models.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 22cc7479f..bcf1d4f6a 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -530,7 +530,6 @@ void gl_InitModels() { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } - GetDefaultByType(smf.type)->hasmodel=true; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -744,6 +743,7 @@ void gl_InitModels() if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); + GetDefaultByType(smf.type)->hasmodel = true; map[c]=1; } } From 3334b28a02da663b904280de951b3a158c75aace Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 14:30:10 +0200 Subject: [PATCH 08/33] - don't let the light go completely black with software-emulated lighting. --- wadsrc/static/shaders/glsl/main.fp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 0b833be06e10f7f6a7c7b122f3b63774289cff99 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 14:37:52 +0200 Subject: [PATCH 09/33] - removed accidentally added GZDoom specials. --- src/p_lnspec.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 103ac1264..c7d801cbb 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -75,9 +75,6 @@ */ static const BYTE ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 }; -int LS_Sector_SetPlaneReflection(line_t *ln, AActor *it, bool backSide, int arg0, int arg1, int arg2, int arg3, int arg4); -int LS_SetGlobalFogParameter(line_t *ln, AActor *it, bool backSide, int arg0, int arg1, int arg2, int arg3, int arg4); - #define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \ int arg0, int arg1, int arg2, int arg3, int arg4) @@ -3444,9 +3441,9 @@ static lnSpecFunc LineSpecials[] = /* 154 */ LS_Teleport_NoStop, /* 155 */ LS_NOP, /* 156 */ LS_NOP, - /* 157 */ LS_SetGlobalFogParameter, + /* 157 */ LS_NOP, // SetGlobalFogParameter /* 158 */ LS_FS_Execute, - /* 159 */ LS_Sector_SetPlaneReflection, + /* 159 */ LS_NOP, // Sector_SetPlaneReflection /* 160 */ LS_NOP, // Sector_Set3DFloor /* 161 */ LS_NOP, // Sector_SetContents /* 162 */ LS_NOP, // Reserved Doom64 branch From 317730584fafd63edac3b765d014741f33b1534f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 14:39:31 +0200 Subject: [PATCH 10/33] - GZDoom still needs this. --- src/p_lnspec.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index c7d801cbb..103ac1264 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -75,6 +75,9 @@ */ static const BYTE ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 }; +int LS_Sector_SetPlaneReflection(line_t *ln, AActor *it, bool backSide, int arg0, int arg1, int arg2, int arg3, int arg4); +int LS_SetGlobalFogParameter(line_t *ln, AActor *it, bool backSide, int arg0, int arg1, int arg2, int arg3, int arg4); + #define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \ int arg0, int arg1, int arg2, int arg3, int arg4) @@ -3441,9 +3444,9 @@ static lnSpecFunc LineSpecials[] = /* 154 */ LS_Teleport_NoStop, /* 155 */ LS_NOP, /* 156 */ LS_NOP, - /* 157 */ LS_NOP, // SetGlobalFogParameter + /* 157 */ LS_SetGlobalFogParameter, /* 158 */ LS_FS_Execute, - /* 159 */ LS_NOP, // Sector_SetPlaneReflection + /* 159 */ LS_Sector_SetPlaneReflection, /* 160 */ LS_NOP, // Sector_Set3DFloor /* 161 */ LS_NOP, // Sector_SetContents /* 162 */ LS_NOP, // Reserved Doom64 branch From 7b65e6d424f67551c976ef6d6e5d8e24a5954f7b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 19:16:07 +0200 Subject: [PATCH 11/33] - use glMapBuffer instead of glMapBufferRange on older hardware. --- src/gl/models/gl_models.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index bcf1d4f6a..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 { From 8817f891923a9d675e9fa964710083770b827396 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 20:31:21 +0200 Subject: [PATCH 12/33] - do not clip the first frame of very slow projectiles. --- src/gl/scene/gl_sprite.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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. } From ec7b4b1ba4bf8ac54ec50ff22752b23d82d4dc71 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 22:14:39 +0200 Subject: [PATCH 13/33] - initial work on textured dynamic light processing. --- src/gl/compatibility/gl_20.cpp | 25 +++++++++++++++++-------- src/gl/renderer/gl_renderer.cpp | 3 ++- src/gl/scene/gl_walls.cpp | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 025ae3038..15d52c48a 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -556,7 +556,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 +564,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 @@ -638,5 +640,12 @@ void FGLRenderer::RenderMultipassStuff() gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE); } 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/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 7002e6b10..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); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 906f7f3e1..237c037d6 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; From 4412f99b385151c6ce5edf7f8cfbca7e1780c836 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 4 May 2016 23:07:16 +0200 Subject: [PATCH 14/33] - added the flat dispatcher for textured lighting. --- src/gl/compatibility/gl_20.cpp | 27 +++++++++++++++++++++++++++ src/gl/scene/gl_flats.cpp | 4 ++++ src/gl/scene/gl_wall.h | 1 + 3 files changed, 32 insertions(+) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 15d52c48a..ecbc32831 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -500,6 +500,33 @@ 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; + + + 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); +} + + //========================================================================== // // Fog boundary without any shader support diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 7406bb20e..6b6f0e4a9 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -463,6 +463,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_wall.h b/src/gl/scene/gl_wall.h index fdf78ee6f..cb443cd2a 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -304,6 +304,7 @@ public: void ProcessLights(bool istrans); void PutFlat(bool fog = false); + bool PutFlatCompat(bool fog); void Process(sector_t * model, int whichplane, bool notexture); void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); void ProcessSector(sector_t * frontsector); From c9d4c6803960b7ddd7905a3066d941a78e961673 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 00:24:47 +0200 Subject: [PATCH 15/33] - added dynamic light drawer for flats. --- src/gl/compatibility/gl_20.cpp | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index ecbc32831..e69ce961e 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" //========================================================================== @@ -376,6 +377,7 @@ 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) { @@ -575,6 +577,95 @@ void GLWall::RenderFogBoundaryCompat() gl_RenderState.EnableTexture(true); } +//========================================================================== +// +// Flats +// +//========================================================================== +enum +{ + LIGHTPASS_MULT, + LIGHTPASS_ADD, + LIGHTPASS_FOG +}; + +void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) +{ + Plane p; + Vector nearPt, up, right, t1; + float scale; + unsigned int k; + seg_t *v; + + FLightNode * node = sub->lighthead; + gl_RenderState.Apply(); + while (node) + { + ADynamicLight * light = node->lightsource; + + if (light->flags2&MF2_DORMANT) + { + node = node->nextLight; + continue; + } + switch (pass) + { + case LIGHTPASS_MULT: + if (light->IsAdditive()) + { + node = node->nextLight; + continue; + } + break; + + case LIGHTPASS_ADD: + if (!light->IsAdditive()) + { + node = node->nextLight; + continue; + } + break; + + default: + break; + } + + + // 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, foggy)) + { + node = node->nextLight; + continue; + } + + 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; + } +} + //========================================================================== // // From 0b2821d696dba4cd12a518d7469a4bb216b7511f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 10:28:21 +0200 Subject: [PATCH 16/33] - added dynamic light rendering with textures on flats --- src/gl/compatibility/gl_20.cpp | 77 ++++++++++++++++++++-------------- src/gl/scene/gl_flats.cpp | 5 +++ src/gl/scene/gl_wall.h | 7 +++- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index e69ce961e..5c7c983d3 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -582,20 +582,12 @@ void GLWall::RenderFogBoundaryCompat() // Flats // //========================================================================== -enum -{ - LIGHTPASS_MULT, - LIGHTPASS_ADD, - LIGHTPASS_FOG -}; void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) { Plane p; Vector nearPt, up, right, t1; float scale; - unsigned int k; - seg_t *v; FLightNode * node = sub->lighthead; gl_RenderState.Apply(); @@ -603,33 +595,13 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) { ADynamicLight * light = node->lightsource; - if (light->flags2&MF2_DORMANT) + if (light->flags2&MF2_DORMANT || + (pass == GLPASS_LIGHTTEX && light->IsAdditive()) || + (pass == GLPASS_LIGHTTEX_ADDITIVE && !light->IsAdditive())) { node = node->nextLight; continue; } - switch (pass) - { - case LIGHTPASS_MULT: - if (light->IsAdditive()) - { - node = node->nextLight; - continue; - } - break; - - case LIGHTPASS_ADD: - if (!light->IsAdditive()) - { - node = node->nextLight; - continue; - } - break; - - default: - break; - } - // 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 @@ -666,6 +638,49 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) } } +//========================================================================== +// +// +// +//========================================================================== + +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; + } + } + } +} + + //========================================================================== // // diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 6b6f0e4a9..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; } } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index cb443cd2a..3bdcbd6ce 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -296,15 +296,18 @@ 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); void PutFlat(bool fog = false); - bool PutFlatCompat(bool fog); void Process(sector_t * model, int whichplane, bool notexture); void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); void ProcessSector(sector_t * frontsector); From 51baa7d137486bf07c40017e471aa4340c2857e1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 11:32:21 +0200 Subject: [PATCH 17/33] - added code to calculate light texture coordinates on walls. --- src/gl/compatibility/gl_20.cpp | 58 ++++++++++++++++++++++++++++++++-- src/gl/scene/gl_wall.h | 3 +- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 5c7c983d3..96cd88fd8 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -379,7 +379,7 @@ void FRenderState::DrawColormapOverlay() //========================================================================== 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; @@ -416,7 +416,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; @@ -613,7 +613,7 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) } p.Set(plane.plane); - if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, false, foggy)) + if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, false, pass == GLPASS_LIGHTTEX_ADDITIVE)) { node = node->nextLight; continue; @@ -681,6 +681,58 @@ void GLFlat::DrawLightsCompat(int pass) } +//========================================================================== +// +// Sets up the texture coordinates for one light to be rendered +// +//========================================================================== +bool GLWall::PrepareLight(texcoord * tcs, 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_ADDITIVE)) + { + 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; +} + + //========================================================================== // // diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 3bdcbd6ce..cfd8ae361 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -183,7 +183,7 @@ private: void SplitWall(sector_t * frontsector, bool translucent); void SetupLights(); - bool PrepareLight(texcoord * tcs, ADynamicLight * light); + bool PrepareLight(texcoord * tcs, ADynamicLight * light, int pass); void RenderWall(int textured, unsigned int *store = NULL); void RenderTextured(int rflags); @@ -288,7 +288,6 @@ public: GLSectorPlane plane; int lightlevel; bool stack; - bool foggy; bool ceiling; BYTE renderflags; int vboindex; From 2b92048a5b1185cfe73d97f444284100cf0ec1fa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 11:48:39 +0200 Subject: [PATCH 18/33] - renamed the texture coord variables in GLWall. It makes no sense having them organized differently in this struct than what the rendering code needs. This saves one redundant copy operation and a function-local static variable. --- src/gl/compatibility/gl_20.cpp | 9 +-- src/gl/scene/gl_drawinfo.cpp | 10 +-- src/gl/scene/gl_vertex.cpp | 40 ++++++------ src/gl/scene/gl_wall.h | 17 ++++-- src/gl/scene/gl_walls.cpp | 108 ++++++++++++++++----------------- src/gl/scene/gl_walls_draw.cpp | 26 +++----- 6 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 96cd88fd8..6df940b77 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -526,6 +526,7 @@ bool GLFlat::PutFlatCompat(bool fog) if (gltexture->tex->gl_info.Brightmap && gl.glslversion >= 0.f) list = GLLDL_FLATS_BRIGHT; } gl_drawinfo->dldrawlists[list].AddFlat(this); + return true; } @@ -559,14 +560,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); 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_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 cfd8ae361..97c8217b7 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; @@ -236,10 +243,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: diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 237c037d6..edd85e1df 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -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..319330342 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); From d61ec05c0f744d4eb68742b4a451b0648ea8fcbf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 12:18:09 +0200 Subject: [PATCH 19/33] - draw texture based dynamic lights on walls. --- src/gl/compatibility/gl_20.cpp | 76 +++++++++++++++++++++++++++------- src/gl/scene/gl_drawinfo.h | 1 + src/gl/scene/gl_wall.h | 3 +- src/gl/scene/gl_walls_draw.cpp | 5 +++ 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 6df940b77..2224dd9f4 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -68,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) @@ -443,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; } @@ -457,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; } @@ -488,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]; @@ -517,7 +516,7 @@ bool GLFlat::PutFlatCompat(bool fog) { { 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; + bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive; int list = list_indices[masked][foggy]; @@ -591,7 +590,6 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) float scale; FLightNode * node = sub->lighthead; - gl_RenderState.Apply(); while (node) { ADynamicLight * light = node->lightsource; @@ -614,11 +612,12 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass) } p.Set(plane.plane); - if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, false, pass == GLPASS_LIGHTTEX_ADDITIVE)) + 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++) @@ -687,7 +686,7 @@ void GLFlat::DrawLightsCompat(int pass) // Sets up the texture coordinates for one light to be rendered // //========================================================================== -bool GLWall::PrepareLight(texcoord * tcs, ADynamicLight * light, int pass) +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; @@ -701,7 +700,7 @@ bool GLWall::PrepareLight(texcoord * tcs, ADynamicLight * light, int pass) return false; } - if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, true, pass == GLPASS_LIGHTTEX_ADDITIVE)) + if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, true, pass != GLPASS_LIGHTTEX)) { return false; } @@ -734,6 +733,55 @@ bool GLWall::PrepareLight(texcoord * tcs, ADynamicLight * light, int pass) } +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)); +} + //========================================================================== // // @@ -820,10 +868,10 @@ 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; 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_wall.h b/src/gl/scene/gl_wall.h index 97c8217b7..fdeb99ed0 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -184,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, int pass); + bool PrepareLight(ADynamicLight * light, int pass); void RenderWall(int textured, unsigned int *store = NULL); void RenderTextured(int rflags); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 319330342..4fd586388 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -442,5 +442,10 @@ void GLWall::Draw(int pass) RenderTranslucentWall(); break; } + + case GLPASS_LIGHTTEX: + case GLPASS_LIGHTTEX_ADDITIVE: + RenderLightsCompat(pass); + break; } } From c193bb77994b4b80f851a5c71915f8b5e1a0d5ac Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 May 2016 20:12:26 +0200 Subject: [PATCH 20/33] - removed the special case 0 in A_SpawnItem, meaning 'in front of the player'. As it turned out this has been broken for many, many years, so one can assume that most content using this function depends on this special case not working. I could track it down to at least 2008. --- src/thingdef/thingdef_codeptr.cpp | 6 ------ 1 file changed, 6 deletions(-) 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 From 52995f8fc2973e1bd1fdd3361b920d7eb2695439 Mon Sep 17 00:00:00 2001 From: Edoardo Prezioso Date: Wed, 4 May 2016 20:33:17 +0200 Subject: [PATCH 21/33] - Fixed missing sector light clamp in DFlicker. For some reason, this code didn't care about the sector light limits. Found by code inspection. --- src/p_lights.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_lights.cpp b/src/p_lights.cpp index 10bf9edf4..90d1da869 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -301,9 +301,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; } From 55294c58065ae5b0724068f2f7549088e5c08ade Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 1 May 2016 21:07:41 -0700 Subject: [PATCH 22/33] Use the correct OpenAL lib name on Linux --- src/sound/oalsound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 56dfb4a4c..3e3b70fb4 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -69,7 +69,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)) From bf5ac9b4764f57eb355bf7e904f615809a218519 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 May 2016 01:56:12 -0700 Subject: [PATCH 23/33] Use AL_EXT_SOURCE_RADIUS for area sounds --- src/sound/oalsound.cpp | 59 ++++++++++++++++++++++++++++-------------- src/sound/oalsound.h | 6 +++++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 3e3b70fb4..48c2b53f8 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -273,6 +273,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,7 +628,7 @@ 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 */ @@ -746,6 +748,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX"); ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");; 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"); @@ -1262,6 +1265,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) { @@ -1404,7 +1409,15 @@ 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) ? + 1.f / GetRolloff(rolloff, AREA_SOUND_RADIUS) : 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 +1427,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); @@ -1631,26 +1648,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 +1676,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]); diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 2644b171a..c9ebc70ea 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" @@ -127,6 +132,7 @@ private: } ALC; struct { bool EXT_source_distance_model; + bool EXT_SOURCE_RADIUS; bool SOFT_deferred_updates; bool SOFT_loop_points; } AL; From 12c9281a7e484daee75e935297c84457d76e3b27 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 May 2016 02:46:01 -0700 Subject: [PATCH 24/33] Avoid redundantly setting DistanceScale --- src/sound/oalsound.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 48c2b53f8..b9421221b 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1326,7 +1326,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; @@ -1510,7 +1509,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; From c3cef91a4f1a0953676fe3271f77750de34b9b18 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 May 2016 05:07:23 -0700 Subject: [PATCH 25/33] Properly sum the channels being downmixed to mono --- src/sound/oalsound.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index b9421221b..c13787c7b 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1045,7 +1045,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; } } @@ -1055,7 +1055,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; } } From e1c8890c5e9d46981150d2cea2deae474722aafc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 May 2016 13:34:46 -0700 Subject: [PATCH 26/33] Set the appropriate start offset for restarted sounds --- src/sound/oalsound.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index c13787c7b..2e351fa0e 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -40,6 +40,8 @@ #include #endif +#include + #include "except.h" #include "doomstat.h" #include "templates.h" @@ -1472,7 +1474,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 { @@ -1480,8 +1482,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) @@ -1819,7 +1824,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) From 26a8a8a1ba583aed21949109afdf8ec28fe1cc68 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 May 2016 14:23:07 -0700 Subject: [PATCH 27/33] Pause OpenAL processing using ALC_SOFT_pause_device when inactive --- src/sound/oalsound.cpp | 21 +++++++++++++++++++-- src/sound/oalsound.h | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 2e351fa0e..c9ba16f2b 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -690,7 +690,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) { @@ -748,7 +753,8 @@ 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"); @@ -771,6 +777,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) { @@ -910,6 +922,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() if(EnvSlot) Printf(" EFX enabled\n"); } +#undef LOAD_DEV_FUNC #undef LOAD_FUNC OpenALSoundRenderer::~OpenALSoundRenderer() @@ -1599,10 +1612,14 @@ void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state) { case SoundRenderer::INACTIVE_Active: alListenerf(AL_GAIN, 1.0f); + if(ALC.SOFT_pause_device) + alcDeviceResumeSOFT(Device); break; - /* FIXME: This doesn't stop anything. */ case SoundRenderer::INACTIVE_Complete: + if(ALC.SOFT_pause_device) + alcDevicePauseSOFT(Device); + /* fall-through */ case SoundRenderer::INACTIVE_Mute: alListenerf(AL_GAIN, 0.0f); break; diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index c9ebc70ea..88dcbc238 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -129,6 +129,7 @@ private: struct { bool EXT_EFX; bool EXT_disconnect; + bool SOFT_pause_device; } ALC; struct { bool EXT_source_distance_model; @@ -180,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(); From 66c61a7c8b8e15bbc731c87242c0cee682df98d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 3 May 2016 04:33:03 -0700 Subject: [PATCH 28/33] Set the appropriate start offset for non-3D sounds too --- src/sound/oalsound.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index c9ba16f2b..8303324d1 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1302,7 +1302,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 { @@ -1310,8 +1310,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) From e298f8389b452890c1b7306fdfe073a23fdd71a7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 3 May 2016 21:05:13 -0700 Subject: [PATCH 29/33] Avoid divide-by-0 when the area sound radius is less than the max distance --- src/sound/oalsound.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 8303324d1..71f021416 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1431,7 +1431,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener /* 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) ? - 1.f / GetRolloff(rolloff, AREA_SOUND_RADIUS) : 0.f + // 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) From 0b7b78c5d233a6066d92e872ac0b943821ed0fe2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 4 May 2016 12:05:43 -0700 Subject: [PATCH 30/33] Better handle channel configs when monoizing in LoadSound --- src/sound/oalsound.cpp | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 71f021416..8b13854c9 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -40,6 +40,7 @@ #include #endif +#include #include #include "except.h" @@ -636,6 +637,15 @@ extern ReverbContainer *ForcedEnvironment; #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) { @@ -1142,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); @@ -1161,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)); } From fa46965a71559b8fe479098b83efbf044655604a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 5 May 2016 09:18:00 -0700 Subject: [PATCH 31/33] Check for OpenAL device errors after pausing/resuming the device --- src/sound/oalsound.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index 8b13854c9..95fa4d39a 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -1634,12 +1634,18 @@ 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; case SoundRenderer::INACTIVE_Complete: if(ALC.SOFT_pause_device) + { alcDevicePauseSOFT(Device); + getALCError(Device); + } /* fall-through */ case SoundRenderer::INACTIVE_Mute: alListenerf(AL_GAIN, 0.0f); From ba1574e65a210478b84a3434cd817c9030f78d08 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 5 May 2016 10:36:53 -0700 Subject: [PATCH 32/33] Don't define OpenAL redirect macros with the IDE's parser At least with KDevelop4, macros like this interefere with contextual info by causing it to show information about the macro itself (where it's defined and what it defines to), rather than the function (parameters, comments, etc). It also gets in the way of auto-completion. --- src/sound/oalload.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 From fbf845982be7fc2f3df832cf6accf3cb302991d9 Mon Sep 17 00:00:00 2001 From: Jason Yundt Date: Sun, 1 May 2016 17:38:14 -0400 Subject: [PATCH 33/33] FORCE_INTERNAL_GME now defaults to OFF --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7d4e7a9c..5f0bf8293 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,7 +193,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 "" )