This commit is contained in:
nashmuhandes 2016-05-07 17:36:01 +08:00
commit c4afa993f4
24 changed files with 616 additions and 251 deletions

View file

@ -192,7 +192,7 @@ set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
option(FORCE_INTERNAL_ZLIB "Use internal zlib")
option(FORCE_INTERNAL_JPEG "Use internal jpeg")
option(FORCE_INTERNAL_BZIP2 "Use internal bzip2")
option(FORCE_INTERNAL_GME "Use internal gme" ON)
option(FORCE_INTERNAL_GME "Use internal gme")
# Fast math flags, required by some subprojects
set( ZD_FASTMATH_FLAG "" )

View file

@ -54,6 +54,7 @@
#include "gl/system/gl_cvars.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/data/gl_vertexbuffer.h"
//==========================================================================
@ -67,8 +68,7 @@ void gl_PatchMenu()
{
if (gl.glslversion == 0)
{
// Radial fog and Doom lighting are not available in SM < 4 cards
// The way they are implemented does not work well on older hardware.
// Radial fog and Doom lighting are not available without full shader support.
FOptionValues **opt = OptionValues.CheckKey("LightingModes");
if (opt != NULL)
@ -376,8 +376,9 @@ void FRenderState::DrawColormapOverlay()
// Sets up the parameters to render one dynamic light onto one plane
//
//==========================================================================
bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right,
float & scale, int desaturation, bool checkside, bool forceadditive)
float & scale, int desaturation, bool checkside, bool additive)
{
Vector fn, pos;
@ -392,7 +393,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt,
{
return false;
}
if (light->owned && light->target != NULL && !light->target->IsVisibleToPlayer())
if (!light->visibletoplayer)
{
return false;
}
@ -414,7 +415,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt,
#endif
float cs = 1.0f - (dist / radius);
if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive) cs *= 0.2f; // otherwise the light gets too strong.
if (additive) cs *= 0.2f; // otherwise the light gets too strong.
float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
@ -441,7 +442,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt,
g = (g*(32 - desaturation) + gray*desaturation) / 32;
b = (b*(32 - desaturation) + gray*desaturation) / 32;
}
glColor3f(r, g, b);
gl_RenderState.SetColor(r, g, b);
return true;
}
@ -455,7 +456,7 @@ bool gl_SetupLightTexture()
{
if (GLRenderer->gllight == nullptr) return false;
FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight, false);
pat->Bind(CLAMP_XY, 0);
pat->Bind(CLAMP_XY_NOMIP, 0);
return true;
}
@ -486,7 +487,7 @@ bool GLWall::PutWallCompat(int passflag)
if (sub->lighthead != nullptr) return false;
}
bool foggy = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE);
bool foggy = !gl_isBlack(Colormap.FadeColor) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
bool masked = passflag == 2 && gltexture->isMasked();
int list = list_indices[masked][foggy];
@ -500,6 +501,34 @@ bool GLWall::PutWallCompat(int passflag)
}
//==========================================================================
//
//
//
//==========================================================================
bool GLFlat::PutFlatCompat(bool fog)
{
// are lights possible?
if (gl_fixedcolormap != CM_DEFAULT || !gl_lights || !gltexture || renderstyle != STYLE_Translucent || alpha < 1.f - FLT_EPSILON || sector->lighthead == NULL) return false;
static int list_indices[2][2] =
{ { GLLDL_FLATS_PLAIN, GLLDL_FLATS_FOG },{ GLLDL_FLATS_MASKED, GLLDL_FLATS_FOGMASKED } };
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
int list = list_indices[masked][foggy];
if (list == GLLDL_FLATS_PLAIN)
{
if (gltexture->tex->gl_info.Brightmap && gl.glslversion >= 0.f) list = GLLDL_FLATS_BRIGHT;
}
gl_drawinfo->dldrawlists[list].AddFlat(this);
return true;
}
//==========================================================================
//
// Fog boundary without any shader support
@ -530,14 +559,14 @@ void GLWall::RenderFogBoundaryCompat()
glDepthFunc(GL_LEQUAL);
glColor4f(fc[0], fc[1], fc[2], fogd1);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(lolft.u, lolft.v);
glTexCoord2f(tcs[LOLFT].u, tcs[LOLFT].v);
glVertex3f(glseg.x1, zbottom[0], glseg.y1);
glTexCoord2f(uplft.u, uplft.v);
glTexCoord2f(tcs[UPLFT].u, tcs[UPLFT].v);
glVertex3f(glseg.x1, ztop[0], glseg.y1);
glColor4f(fc[0], fc[1], fc[2], fogd2);
glTexCoord2f(uprgt.u, uprgt.v);
glTexCoord2f(tcs[UPRGT].u, tcs[UPRGT].v);
glVertex3f(glseg.x2, ztop[1], glseg.y2);
glTexCoord2f(lorgt.u, lorgt.v);
glTexCoord2f(tcs[LORGT].u, tcs[LORGT].v);
glVertex3f(glseg.x2, zbottom[1], glseg.y2);
glEnd();
glDepthFunc(GL_LESS);
@ -548,6 +577,211 @@ void GLWall::RenderFogBoundaryCompat()
gl_RenderState.EnableTexture(true);
}
//==========================================================================
//
// Flats
//
//==========================================================================
void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
{
Plane p;
Vector nearPt, up, right, t1;
float scale;
FLightNode * node = sub->lighthead;
while (node)
{
ADynamicLight * light = node->lightsource;
if (light->flags2&MF2_DORMANT ||
(pass == GLPASS_LIGHTTEX && light->IsAdditive()) ||
(pass == GLPASS_LIGHTTEX_ADDITIVE && !light->IsAdditive()))
{
node = node->nextLight;
continue;
}
// we must do the side check here because gl_SetupLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
double planeh = plane.plane.ZatPoint(light);
if (gl_lights_checkside && ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling)))
{
node = node->nextLight;
continue;
}
p.Set(plane.plane);
if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, false, pass != GLPASS_LIGHTTEX))
{
node = node->nextLight;
continue;
}
gl_RenderState.Apply();
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
for (unsigned int k = 0; k < sub->numlines; k++)
{
vertex_t *vt = sub->firstline[k].v1;
ptr->x = vt->fX();
ptr->z = plane.plane.ZatPoint(vt) + dz;
ptr->y = vt->fY();
t1.Set(ptr->x, ptr->z, ptr->y);
Vector nearToVert = t1 - nearPt;
ptr->u = (nearToVert.Dot(right) * scale) + 0.5f;
ptr->v = (nearToVert.Dot(up) * scale) + 0.5f;
ptr++;
}
GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
node = node->nextLight;
}
}
//==========================================================================
//
//
//
//==========================================================================
void GLFlat::DrawLightsCompat(int pass)
{
gl_RenderState.Apply();
if (sub)
{
// This represents a single subsector
DrawSubsectorLights(sub, pass);
}
else
{
// Draw the subsectors belonging to this sector
for (int i = 0; i<sector->subsectorcount; i++)
{
subsector_t * sub = sector->subsectors[i];
if (gl_drawinfo->ss_renderflags[sub - subsectors] & renderflags)
{
DrawSubsectorLights(sub, pass);
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(renderflags&SSRF_RENDER3DPLANES))
{
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR) ?
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
while (node)
{
DrawSubsectorLights(sub, pass);
node = node->next;
}
}
}
}
//==========================================================================
//
// Sets up the texture coordinates for one light to be rendered
//
//==========================================================================
bool GLWall::PrepareLight(ADynamicLight * light, int pass)
{
float vtx[] = { glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2 };
Plane p;
Vector nearPt, up, right;
float scale;
p.Init(vtx, 4);
if (!p.ValidNormal())
{
return false;
}
if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, CM_DEFAULT, true, pass != GLPASS_LIGHTTEX))
{
return false;
}
if (tcs != NULL)
{
Vector t1;
int outcnt[4] = { 0,0,0,0 };
for (int i = 0; i<4; i++)
{
t1.Set(&vtx[i * 3]);
Vector nearToVert = t1 - nearPt;
tcs[i].u = (nearToVert.Dot(right) * scale) + 0.5f;
tcs[i].v = (nearToVert.Dot(up) * scale) + 0.5f;
// quick check whether the light touches this polygon
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
}
// The light doesn't touch this polygon
if (outcnt[0] == 4 || outcnt[1] == 4 || outcnt[2] == 4 || outcnt[3] == 4) return false;
}
draw_dlight++;
return true;
}
void GLWall::RenderLightsCompat(int pass)
{
FLightNode * node;
// black fog is diminishing light and should affect lights less than the rest!
if (pass == GLPASS_LIGHTTEX) gl_SetFog((255 + lightlevel) >> 1, 0, NULL, false);
else gl_SetFog(lightlevel, 0, &Colormap, true);
if (seg->sidedef == NULL)
{
return;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
// Iterate through all dynamic lights which touch this wall and render them
node = seg->sidedef->lighthead;
}
else if (sub)
{
// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
node = sub->lighthead;
}
else
{
return;
}
texcoord save[4];
memcpy(save, tcs, sizeof(tcs));
while (node)
{
ADynamicLight * light = node->lightsource;
if (light->flags2&MF2_DORMANT ||
(pass == GLPASS_LIGHTTEX && light->IsAdditive()) ||
(pass == GLPASS_LIGHTTEX_ADDITIVE && !light->IsAdditive()))
{
node = node->nextLight;
continue;
}
if (PrepareLight(light, pass))
{
RenderWall(RWF_TEXTURED, NULL);
}
node = node->nextLight;
}
memcpy(tcs, save, sizeof(tcs));
}
//==========================================================================
//
//
@ -556,7 +790,6 @@ void GLWall::RenderFogBoundaryCompat()
void FGLRenderer::RenderMultipassStuff()
{
return;
// First pass: empty background with sector light only
// Part 1: solid geometry. This is set up so that there are no transparent parts
@ -565,25 +798,28 @@ void FGLRenderer::RenderMultipassStuff()
gl_RenderState.EnableTexture(false);
gl_RenderState.EnableBrightmap(false);
gl_RenderState.Apply();
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_BASE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_BASE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_PLAIN);
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
// This creates a blank surface that only fills the nontransparent parts of the texture
gl_RenderState.EnableTexture(true);
gl_RenderState.SetTextureMode(TM_MASK);
gl_RenderState.EnableBrightmap(true);
gl_drawinfo->dldrawlists[GLLDL_WALLS_BRIGHT].DrawWalls(GLPASS_BASE_MASKED);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_BASE_MASKED);
gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_BASE_MASKED);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_BASE_MASKED);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_BRIGHT].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_PLAIN);
// Part 3: The base of fogged surfaces, including the texture
gl_RenderState.EnableBrightmap(false);
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_PLAIN);
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_PLAIN);
// second pass: draw lights
@ -632,11 +868,18 @@ void FGLRenderer::RenderMultipassStuff()
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_BRIGHT].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
}
else gl_lights = false;
glDepthFunc(GL_LESS);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f);
gl_RenderState.EnableFog(true);
gl_RenderState.BlendFunc(GL_ONE, GL_ZERO);
glDepthMask(true);
}

View file

@ -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

View file

@ -116,6 +116,7 @@ public:
bool owned;
bool halo;
BYTE color2[3];
bool visibletoplayer;
int bufferindex;
// intermediate texture coordinate data

View file

@ -170,7 +170,10 @@ FModelVertex *FModelVertexBuffer::LockVertexBuffer(unsigned int size)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBufferData(GL_ARRAY_BUFFER, size * sizeof(FModelVertex), nullptr, GL_STATIC_DRAW);
return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
if (gl.version >= 3.0)
return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
else
return (FModelVertex*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
}
else
{
@ -208,7 +211,10 @@ unsigned int *FModelVertexBuffer::LockIndexBuffer(unsigned int size)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size * sizeof(unsigned int), NULL, GL_STATIC_DRAW);
return (unsigned int*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, size * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
if (gl.version >= 3.0)
return (unsigned int*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, size * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
else
return (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
}
else
{
@ -519,6 +525,7 @@ void gl_InitModels()
{
if (sc.Compare("model"))
{
path = "";
sc.MustGetString();
memset(&smf, 0, sizeof(smf));
smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
@ -529,7 +536,6 @@ void gl_InitModels()
{
sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
}
GetDefaultByType(smf.type)->hasmodel=true;
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
@ -743,6 +749,7 @@ void gl_InitModels()
if (map[c]) continue;
smf.frame=c;
SpriteModelFrames.Push(smf);
GetDefaultByType(smf.type)->hasmodel = true;
map[c]=1;
}
}
@ -933,16 +940,19 @@ void gl_RenderModel(GLSprite * spr)
const double x = spr->actor->Vel.X;
const double y = spr->actor->Vel.Y;
const double z = spr->actor->Vel.Z;
// [BB] Calculate the pitch using spherical coordinates.
if(z || x || y) pitch = float(atan( z/sqrt(x*x+y*y) ) / M_PI * 180);
// Correcting pitch if model is moving backwards
if(x || y)
if (spr->actor->Vel.LengthSquared() > EQUAL_EPSILON)
{
if((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1;
// [BB] Calculate the pitch using spherical coordinates.
if (z || x || y) pitch = float(atan(z / sqrt(x*x + y*y)) / M_PI * 180);
// Correcting pitch if model is moving backwards
if (fabs(x) > EQUAL_EPSILON || fabs(y) > EQUAL_EPSILON)
{
if ((x * cos(angle * M_PI / 180) + y * sin(angle * M_PI / 180)) / sqrt(x * x + y * y) < 0) pitch *= -1;
}
else pitch = fabs(pitch);
}
else pitch = fabs(pitch);
}
if( smf->flags & MDL_ROTATING )
@ -964,7 +974,7 @@ void gl_RenderModel(GLSprite * spr)
// Applying model transformations:
// 1) Applying actor angle, pitch and roll to the model
gl_RenderState.mModelMatrix.rotate(-angle, 0, 1, 0);
gl_RenderState.mModelMatrix.rotate(pitch, 0, 0, 1);
gl_RenderState.mModelMatrix.rotate(-pitch, 0, 0, 1);
gl_RenderState.mModelMatrix.rotate(-roll, 1, 0, 0);
// 2) Applying Doomsday like rotation of the weapon pickup models

View file

@ -95,7 +95,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mSkyVBO = NULL;
gl_spriteindex = 0;
mShaderManager = NULL;
glpart2 = glpart = mirrortexture = NULL;
gllight = glpart2 = glpart = mirrortexture = NULL;
mLights = NULL;
}
@ -112,6 +112,7 @@ void FGLRenderer::Initialize()
}
else mVAOID = 0;
gllight = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/gllight.png"), FTexture::TEX_MiscPatch);
glpart2 = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart2.png"), FTexture::TEX_MiscPatch);
glpart = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart.png"), FTexture::TEX_MiscPatch);
mirrortexture = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/mirror.png"), FTexture::TEX_MiscPatch);
@ -350,7 +351,7 @@ void FGLRenderer::DrawTexture(FTexture *img, DrawParms &parms)
if (pal) translation = -pal->GetIndex();
}
}
gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, 0, !!(parms.style.Flags & STYLEF_RedIsAlpha));
gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, -1, !!(parms.style.Flags & STYLEF_RedIsAlpha));
u1 = gltex->GetUL();
v1 = gltex->GetVT();

View file

@ -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));

View file

@ -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)
};

View file

@ -443,6 +443,11 @@ void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIG
}
if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case GLPASS_LIGHTTEX:
case GLPASS_LIGHTTEX_ADDITIVE:
DrawLightsCompat(pass);
break;
}
}
@ -463,6 +468,10 @@ inline void GLFlat::PutFlat(bool fog)
{
Colormap.Clear();
}
if (gl.lightmethod == LM_SOFTWARE)
{
if (PutFlatCompat(fog)) return;
}
if (renderstyle!=STYLE_Translucent || alpha < 1.f - FLT_EPSILON || fog || gltexture == NULL)
{
// translucent 3D floors go into the regular translucent list, translucent portals go into the translucent border list.

View file

@ -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.
}

View file

@ -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;
}
}
}

View file

@ -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 (i<vi->numheights && vi->heightlist[i] <= zbottom[0]) i++;
while (i<vi->numheights && 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--;
}

View file

@ -119,6 +119,13 @@ public:
RWF_NORENDER = 8,
};
enum
{
LOLFT,
UPLFT,
UPRGT,
LORGT,
};
friend struct GLDrawList;
friend class GLPortal;
@ -126,7 +133,7 @@ public:
GLSeg glseg;
vertex_t * vertexes[2]; // required for polygon splitting
float ztop[2],zbottom[2];
texcoord uplft, uprgt, lolft, lorgt;
texcoord tcs[4];
float alpha;
FMaterial *gltexture;
@ -177,13 +184,14 @@ private:
void CheckTexturePosition();
void RenderFogBoundaryCompat();
void RenderLightsCompat(int pass);
void Put3DWall(lightlist_t * lightlist, bool translucent);
void SplitWallComplex(sector_t * frontsector, bool translucent, float maplightbottomleft, float maplightbottomright);
void SplitWall(sector_t * frontsector, bool translucent);
void SetupLights();
bool PrepareLight(texcoord * tcs, ADynamicLight * light);
bool PrepareLight(ADynamicLight * light, int pass);
void RenderWall(int textured, unsigned int *store = NULL);
void RenderTextured(int rflags);
@ -236,10 +244,10 @@ private:
void RenderMirrorSurface();
void RenderTranslucentWall();
void SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr);
void SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr);
void SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr);
void SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr);
void SplitLeftEdge (FFlatVertex *&ptr);
void SplitRightEdge(FFlatVertex *&ptr);
void SplitUpperEdge(FFlatVertex *&ptr);
void SplitLowerEdge(FFlatVertex *&ptr);
public:
@ -288,7 +296,6 @@ public:
GLSectorPlane plane;
int lightlevel;
bool stack;
bool foggy;
bool ceiling;
BYTE renderflags;
int vboindex;
@ -296,9 +303,13 @@ public:
int dynlightindex;
// compatibility fallback stuff.
void DrawSubsectorLights(subsector_t * sub, int pass);
void DrawLightsCompat(int pass);
bool PutFlatCompat(bool fog);
void SetupSubsectorLights(int pass, subsector_t * sub, int *dli = NULL);
void DrawSubsector(subsector_t * sub);
void DrawSubsectorLights(subsector_t * sub, int pass);
void DrawSkyboxSector(int pass, bool processlights);
void DrawSubsectors(int pass, bool processlights, bool istrans);
void ProcessLights(bool istrans);

View file

@ -142,7 +142,7 @@ void GLWall::PutWall(bool translucent)
if (gl.lightmethod == LM_SOFTWARE && !translucent)
{
// This is not yet ready.
//if (PutWallCompat(passflag[type])) return;
if (PutWallCompat(passflag[type])) return;
}
bool masked;
@ -297,10 +297,10 @@ void GLWall::SplitWallComplex(sector_t * frontsector, bool translucent, float ma
copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1] - ztop[0]);
copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1] - zbottom[0]);
copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright - glseg.fracleft);
copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u - uplft.u);
copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v - uplft.v);
copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u - lolft.u);
copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v - lolft.v);
copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u);
copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v);
copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u);
copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v);
copyWall1.SplitWall(frontsector, translucent);
copyWall2.SplitWall(frontsector, translucent);
@ -338,10 +338,10 @@ void GLWall::SplitWallComplex(sector_t * frontsector, bool translucent, float ma
copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1] - ztop[0]);
copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1] - zbottom[0]);
copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright - glseg.fracleft);
copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u - uplft.u);
copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v - uplft.v);
copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u - lolft.u);
copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v - lolft.v);
copyWall1.tcs[UPRGT].u = copyWall2.tcs[UPLFT].u = tcs[UPLFT].u + coeff * (tcs[UPRGT].u - tcs[UPLFT].u);
copyWall1.tcs[UPRGT].v = copyWall2.tcs[UPLFT].v = tcs[UPLFT].v + coeff * (tcs[UPRGT].v - tcs[UPLFT].v);
copyWall1.tcs[LORGT].u = copyWall2.tcs[LOLFT].u = tcs[LOLFT].u + coeff * (tcs[LORGT].u - tcs[LOLFT].u);
copyWall1.tcs[LORGT].v = copyWall2.tcs[LOLFT].v = tcs[LOLFT].v + coeff * (tcs[LORGT].v - tcs[LOLFT].v);
copyWall1.SplitWall(frontsector, translucent);
copyWall2.SplitWall(frontsector, translucent);
@ -432,10 +432,10 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent)
flags |= GLWF_NOSPLITUPPER;
ztop[0]=copyWall1.zbottom[0]=maplightbottomleft;
ztop[1]=copyWall1.zbottom[1]=maplightbottomright;
uplft.v=copyWall1.lolft.v=copyWall1.uplft.v+
(maplightbottomleft-copyWall1.ztop[0])*(copyWall1.lolft.v-copyWall1.uplft.v)/(zbottom[0]-copyWall1.ztop[0]);
uprgt.v=copyWall1.lorgt.v=copyWall1.uprgt.v+
(maplightbottomright-copyWall1.ztop[1])*(copyWall1.lorgt.v-copyWall1.uprgt.v)/(zbottom[1]-copyWall1.ztop[1]);
tcs[UPLFT].v=copyWall1.tcs[LOLFT].v=copyWall1.tcs[UPLFT].v+
(maplightbottomleft-copyWall1.ztop[0])*(copyWall1.tcs[LOLFT].v-copyWall1.tcs[UPLFT].v)/(zbottom[0]-copyWall1.ztop[0]);
tcs[UPRGT].v=copyWall1.tcs[LORGT].v=copyWall1.tcs[UPRGT].v+
(maplightbottomright-copyWall1.ztop[1])*(copyWall1.tcs[LORGT].v-copyWall1.tcs[UPRGT].v)/(zbottom[1]-copyWall1.ztop[1]);
copyWall1.Put3DWall(&lightlist[i], translucent);
}
if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1])
@ -574,8 +574,8 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
if (tci)
{
uplft.v = tci->FloatToTexV(-ztop[0] + texturetop);
lolft.v = tci->FloatToTexV(-zbottom[0] + texturetop);
tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop);
tcs[LOLFT].v = tci->FloatToTexV(-zbottom[0] + texturetop);
}
}
else
@ -595,7 +595,7 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
if (tci)
{
lolft.v = uplft.v = tci->FloatToTexV(-ztop[0] + texturetop);
tcs[LOLFT].v = tcs[UPLFT].v = tci->FloatToTexV(-ztop[0] + texturetop);
}
}
@ -612,8 +612,8 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
if (tci)
{
uprgt.v = tci->FloatToTexV(-ztop[1] + texturetop);
lorgt.v = tci->FloatToTexV(-zbottom[1] + texturetop);
tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop);
tcs[LORGT].v = tci->FloatToTexV(-zbottom[1] + texturetop);
}
}
else
@ -632,12 +632,12 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
zbottom[1] = ztop[1] = inter_y;
if (tci)
{
lorgt.v = uprgt.v = tci->FloatToTexV(-ztop[1] + texturetop);
tcs[LORGT].v = tcs[UPRGT].v = tci->FloatToTexV(-ztop[1] + texturetop);
}
}
uplft.u = lolft.u = l_ul + texlength * glseg.fracleft;
uprgt.u = lorgt.u = l_ul + texlength * glseg.fracright;
tcs[UPLFT].u = tcs[LOLFT].u = l_ul + texlength * glseg.fracleft;
tcs[UPRGT].u = tcs[LORGT].u = l_ul + texlength * glseg.fracright;
if (gltexture != NULL)
{
@ -646,15 +646,15 @@ bool GLWall::SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float textureto
else if (flags & GLT_CLAMPY)
{
// for negative scales we can get negative coordinates here.
normalize = (uplft.v > lolft.v || uprgt.v > lorgt.v);
normalize = (tcs[UPLFT].v > tcs[LOLFT].v || tcs[UPRGT].v > tcs[LORGT].v);
}
if (normalize)
{
// we have to shift the y-coordinate from [-1..0] to [0..1] when using texture clamping with a negative scale
uplft.v += 1.f;
uprgt.v += 1.f;
lolft.v += 1.f;
lorgt.v += 1.f;
tcs[UPLFT].v += 1.f;
tcs[UPRGT].v += 1.f;
tcs[LOLFT].v += 1.f;
tcs[LORGT].v += 1.f;
}
}
@ -675,21 +675,21 @@ void GLWall::CheckTexturePosition()
// clamp texture coordinates to a reasonable range.
// Extremely large values can cause visual problems
if (uplft.v < uprgt.v)
if (tcs[UPLFT].v < tcs[UPRGT].v)
{
sub = float(xs_FloorToInt(uplft.v));
sub = float(xs_FloorToInt(tcs[UPLFT].v));
}
else
{
sub = float(xs_FloorToInt(uprgt.v));
sub = float(xs_FloorToInt(tcs[UPRGT].v));
}
uplft.v -= sub;
uprgt.v -= sub;
lolft.v -= sub;
lorgt.v -= sub;
tcs[UPLFT].v -= sub;
tcs[UPRGT].v -= sub;
tcs[LOLFT].v -= sub;
tcs[LORGT].v -= sub;
if ((uplft.v == 0.f && uprgt.v == 0.f && lolft.v <= 1.f && lorgt.v <= 1.f) ||
(uplft.v >= 0.f && uprgt.v >= 0.f && lolft.v == 1.f && lorgt.v == 1.f))
if ((tcs[UPLFT].v == 0.f && tcs[UPRGT].v == 0.f && tcs[LOLFT].v <= 1.f && tcs[LORGT].v <= 1.f) ||
(tcs[UPLFT].v >= 0.f && tcs[UPRGT].v >= 0.f && tcs[LOLFT].v == 1.f && tcs[LORGT].v == 1.f))
{
flags |= GLT_CLAMPY;
}
@ -698,13 +698,13 @@ void GLWall::CheckTexturePosition()
// This intentionally only tests the seg's frontsector.
if (seg->frontsector->special == GLSector_Skybox)
{
sub = (float)xs_FloorToInt(uplft.u);
uplft.u -= sub;
uprgt.u -= sub;
lolft.u -= sub;
lorgt.u -= sub;
if ((uplft.u == 0.f && lolft.u == 0.f && uprgt.u <= 1.f && lorgt.u <= 1.f) ||
(uplft.u >= 0.f && lolft.u >= 0.f && uprgt.u == 1.f && lorgt.u == 1.f))
sub = (float)xs_FloorToInt(tcs[UPLFT].u);
tcs[UPLFT].u -= sub;
tcs[UPRGT].u -= sub;
tcs[LOLFT].u -= sub;
tcs[LORGT].u -= sub;
if ((tcs[UPLFT].u == 0.f && tcs[LOLFT].u == 0.f && tcs[UPRGT].u <= 1.f && tcs[LORGT].u <= 1.f) ||
(tcs[UPLFT].u >= 0.f && tcs[LOLFT].u >= 0.f && tcs[UPRGT].u == 1.f && tcs[LORGT].u == 1.f))
{
flags |= GLT_CLAMPX;
}
@ -1039,10 +1039,10 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
// split the poly!
GLWall split;
int i,t=0;
float v_factor=(zbottom[0]-ztop[0])/(lolft.v-uplft.v);
float v_factor=(zbottom[0]-ztop[0])/(tcs[LOLFT].v-tcs[UPLFT].v);
// only split the vertical area of the polygon that does not contain slopes.
float splittopv = MAX(uplft.v, uprgt.v);
float splitbotv = MIN(lolft.v, lorgt.v);
float splittopv = MAX(tcs[UPLFT].v, tcs[UPRGT].v);
float splitbotv = MIN(tcs[LOLFT].v, tcs[LORGT].v);
// this is split vertically into sections.
for(i=0;i<v;i++)
@ -1063,16 +1063,16 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
// if not use the top of the remaining polygon
if (splitrect[i].top>splittopv)
{
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();
}

View file

@ -175,14 +175,8 @@ void GLWall::SetupLights()
void GLWall::RenderWall(int textured, unsigned int *store)
{
static texcoord tcs[4]; // making this variable static saves us a relatively costly stack integrity check.
bool split = (gl_seamless && !(textured&RWF_NOSPLIT) && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT));
tcs[0]=lolft;
tcs[1]=uplft;
tcs[2]=uprgt;
tcs[3]=lorgt;
if (!(textured & RWF_NORENDER))
{
gl_RenderState.Apply();
@ -193,18 +187,18 @@ void GLWall::RenderWall(int textured, unsigned int *store)
FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
unsigned int count, offset;
ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[0].u, tcs[0].v);
ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v);
ptr++;
if (split && glseg.fracleft == 0) SplitLeftEdge(tcs, ptr);
ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[1].u, tcs[1].v);
if (split && glseg.fracleft == 0) SplitLeftEdge(ptr);
ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v);
ptr++;
if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs, ptr);
ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[2].u, tcs[2].v);
if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(ptr);
ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v);
ptr++;
if (split && glseg.fracright == 1) SplitRightEdge(tcs, ptr);
ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[3].u, tcs[3].v);
if (split && glseg.fracright == 1) SplitRightEdge(ptr);
ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v);
ptr++;
if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs, ptr);
if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(ptr);
count = GLRenderer->mVBO->GetCount(ptr, &offset);
if (!(textured & RWF_NORENDER))
{
@ -265,8 +259,8 @@ void GLWall::RenderMirrorSurface()
if (gl.glslversion >= 0.f)
{
// we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is.
lolft.u = lorgt.u = uplft.u = uprgt.u = v.X();
lolft.v = lorgt.v = uplft.v = uprgt.v = v.Z();
tcs[LOLFT].u = tcs[LORGT].u = tcs[UPLFT].u = tcs[UPRGT].u = v.X();
tcs[LOLFT].v = tcs[LORGT].v = tcs[UPLFT].v = tcs[UPRGT].v = v.Z();
gl_RenderState.EnableTextureMatrix(true);
gl_RenderState.mTextureMatrix.computeNormalMatrix(gl_RenderState.mViewMatrix);
@ -448,5 +442,10 @@ void GLWall::Draw(int pass)
RenderTranslucentWall();
break;
}
case GLPASS_LIGHTTEX:
case GLPASS_LIGHTTEX_ADDITIVE:
RenderLightsCompat(pass);
break;
}
}

View file

@ -302,9 +302,9 @@ void DFlicker::Tick ()
DFlicker::DFlicker (sector_t *sector, int upper, int lower)
: DLighting (sector)
{
m_MaxLight = upper;
m_MinLight = lower;
sector->lightlevel = upper;
m_MaxLight = sector_t::ClampLight(upper);
m_MinLight = sector_t::ClampLight(lower);
sector->lightlevel = m_MaxLight;
m_Count = (pr_flicker()&64)+1;
}

View file

@ -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
#endif

View file

@ -40,6 +40,9 @@
#include <dlfcn.h>
#endif
#include <memory>
#include <chrono>
#include "except.h"
#include "doomstat.h"
#include "templates.h"
@ -69,7 +72,7 @@ static void* hmodOpenAL;
#ifdef __APPLE__
#define OPENALLIB "OpenAL.framework/OpenAL"
#else
#define OPENALLIB "libopenal.so"
#define OPENALLIB "libopenal.so.1"
#endif
#define LoadLibrary(x) dlopen((x), RTLD_LAZY)
#define GetProcAddress(a,b) dlsym((a),(b))
@ -273,6 +276,8 @@ class OpenALSoundStream : public SoundStream
alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL);
alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);
}
if(Renderer->AL.EXT_SOURCE_RADIUS)
alSourcef(Source, AL_SOURCE_RADIUS, 0.f);
alGenBuffers(BufferCount, Buffers);
return (getALError() == AL_NO_ERROR);
@ -626,12 +631,21 @@ public:
extern ReverbContainer *ForcedEnvironment;
#define AREA_SOUND_RADIUS (128.f)
#define AREA_SOUND_RADIUS (32.f)
#define PITCH_MULT (0.7937005f) /* Approx. 4 semitones lower; what Nash suggested */
#define PITCH(pitch) (snd_pitched ? (pitch)/128.f : 1.f)
static size_t GetChannelCount(ChannelConfig chans)
{
switch(chans)
{
case ChannelConfig_Mono: return 1;
case ChannelConfig_Stereo: return 2;
}
return 0;
}
static float GetRolloff(const FRolloffInfo *rolloff, float distance)
{
@ -686,7 +700,12 @@ template<typename T>
static void LoadALFunc(const char *name, T *x)
{ *x = reinterpret_cast<T>(alGetProcAddress(name)); }
template<typename T>
static void LoadALCFunc(ALCdevice *device, const char *name, T *x)
{ *x = reinterpret_cast<T>(alcGetProcAddress(device, name)); }
#define LOAD_FUNC(x) (LoadALFunc(#x, &x))
#define LOAD_DEV_FUNC(d, x) (LoadALCFunc(d, #x, &x))
OpenALSoundRenderer::OpenALSoundRenderer()
: Device(NULL), Context(NULL), SFXPaused(0), PrevEnvironment(NULL), EnvSlot(0)
{
@ -744,8 +763,10 @@ OpenALSoundRenderer::OpenALSoundRenderer()
DPrintf(" Extensions: " TEXTCOLOR_ORANGE"%s\n", alGetString(AL_EXTENSIONS));
ALC.EXT_EFX = !!alcIsExtensionPresent(Device, "ALC_EXT_EFX");
ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");;
ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect");
ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device");
AL.EXT_source_distance_model = !!alIsExtensionPresent("AL_EXT_source_distance_model");
AL.EXT_SOURCE_RADIUS = !!alIsExtensionPresent("AL_EXT_SOURCE_RADIUS");
AL.SOFT_deferred_updates = !!alIsExtensionPresent("AL_SOFT_deferred_updates");
AL.SOFT_loop_points = !!alIsExtensionPresent("AL_SOFT_loop_points");
@ -766,6 +787,12 @@ OpenALSoundRenderer::OpenALSoundRenderer()
alProcessUpdatesSOFT = _wrap_ProcessUpdatesSOFT;
}
if(ALC.SOFT_pause_device)
{
LOAD_DEV_FUNC(Device, alcDevicePauseSOFT);
LOAD_DEV_FUNC(Device, alcDeviceResumeSOFT);
}
ALenum err = getALError();
if(err != AL_NO_ERROR)
{
@ -905,6 +932,7 @@ OpenALSoundRenderer::OpenALSoundRenderer()
if(EnvSlot)
Printf(" EFX enabled\n");
}
#undef LOAD_DEV_FUNC
#undef LOAD_FUNC
OpenALSoundRenderer::~OpenALSoundRenderer()
@ -1042,7 +1070,7 @@ std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int
{
int sum = 0;
for(int c = 0;c < channels;c++)
sum = ((short*)sfxdata)[i*channels + c];
sum += ((short*)sfxdata)[i*channels + c];
((short*)sfxdata)[i] = sum / channels;
}
}
@ -1052,7 +1080,7 @@ std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int
{
int sum = 0;
for(int c = 0;c < channels;c++)
sum = sfxdata[i*channels + c] - 128;
sum += sfxdata[i*channels + c] - 128;
sfxdata[i] = (sum / channels) + 128;
}
}
@ -1124,7 +1152,7 @@ std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int le
SampleType type;
int srate;
SoundDecoder *decoder = CreateDecoder(&reader);
std::unique_ptr<SoundDecoder> decoder(CreateDecoder(&reader));
if(!decoder) return std::make_pair(retval, true);
decoder->getInfo(&srate, &chans, &type);
@ -1143,46 +1171,53 @@ std::pair<SoundHandle,bool> 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<char> data = decoder->readAll();
if(chans != ChannelConfig_Mono && monoize)
{
// TODO: Handle this better if ChannelConfig ever gets more channel configurations.
size_t frames = data.Size() / 2 / (type == SampleType_Int16 ? 2 : 1);
size_t chancount = GetChannelCount(chans);
size_t frames = data.Size() / chancount /
(type == SampleType_Int16 ? 2 : 1);
if(type == SampleType_Int16)
{
short *sfxdata = (short*)&data[0];
for(size_t i = 0;i < frames;i++)
sfxdata[i] = (sfxdata[i*2 + 0]-0 + sfxdata[i*2 + 1]-0)/2;
{
int sum = 0;
for(size_t c = 0;c < chancount;c++)
sum += sfxdata[i*chancount + c];
sfxdata[i] = sum / chancount;
}
}
else if(type == SampleType_UInt8)
{
BYTE *sfxdata = (BYTE*)&data[0];
for(size_t i = 0;i < frames;i++)
sfxdata[i] = (sfxdata[i*2 + 0]-128 + sfxdata[i*2 + 1]-128)/2 + 128;
{
int sum = 0;
for(size_t c = 0;c < chancount;c++)
sum += sfxdata[i*chancount + c] - 128;
sfxdata[i] = (sum / chancount) + 128;
}
}
data.Resize(data.Size()/2);
data.Resize(data.Size()/chancount);
}
ALenum err;
ALuint buffer = 0;
alGenBuffers(1, &buffer);
alBufferData(buffer, format, &data[0], data.Size(), srate);
ALenum err;
if((err=getALError()) != AL_NO_ERROR)
{
Printf("Failed to buffer data: %s\n", alGetString(err));
alDeleteBuffers(1, &buffer);
getALError();
delete decoder;
return std::make_pair(retval, true);
}
retval.data = MAKE_PTRID(buffer);
delete decoder;
return std::make_pair(retval, (chans == ChannelConfig_Mono || monoize));
}
@ -1262,6 +1297,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
alSourcef(source, AL_ROLLOFF_FACTOR, 0.f);
alSourcef(source, AL_MAX_GAIN, SfxVolume);
alSourcef(source, AL_GAIN, SfxVolume*vol);
if(AL.EXT_SOURCE_RADIUS)
alSourcef(source, AL_SOURCE_RADIUS, 0.f);
if(EnvSlot)
{
@ -1282,7 +1319,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
else
alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan)
if(!reuse_chan || reuse_chan->StartTime.AsOne == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f);
else
{
@ -1290,8 +1327,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f);
else
{
// FIXME: set offset based on the current time and the StartTime
alSourcef(source, AL_SEC_OFFSET, 0.f);
float offset = std::chrono::duration_cast<std::chrono::duration<float>>(
std::chrono::steady_clock::now().time_since_epoch() -
std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne)
).count();
if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset);
}
}
if(getALError() != AL_NO_ERROR)
@ -1321,7 +1361,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
chan->Rolloff.RolloffType = ROLLOFF_Log;
chan->Rolloff.RolloffFactor = 0.f;
chan->Rolloff.MinDistance = 1.f;
chan->DistanceScale = 1.f;
chan->DistanceSqr = 0.f;
chan->ManualRolloff = false;
@ -1404,7 +1443,16 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
float gain = GetRolloff(rolloff, sqrtf(dist_sqr) * distscale);
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
}
if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
if(AL.EXT_SOURCE_RADIUS)
{
/* Since the OpenAL distance is decoupled from the sound's distance, get the OpenAL
* distance that corresponds to the area radius. */
alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ?
// Clamp in case the max distance is <= the area radius
1.f/MAX<float>(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f
);
}
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
@ -1414,20 +1462,24 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
}
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
else
{
FVector3 dir = pos - listener->position;
FVector3 dir = pos;
if(AL.EXT_SOURCE_RADIUS)
alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? AREA_SOUND_RADIUS : 0.f);
else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{
dir -= listener->position;
float mindist = rolloff->MinDistance/distscale;
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a;
float mindist = rolloff->MinDistance/distscale;
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
float a = sqrtf(dist_sqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a;
dir += listener->position;
dir += listener->position;
}
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
}
else
alSource3f(source, AL_POSITION, pos[0], pos[1], -pos[2]);
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
alSource3f(source, AL_DIRECTION, 0.f, 0.f, 0.f);
@ -1456,7 +1508,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
else
alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan)
if(!reuse_chan || reuse_chan->StartTime.AsOne == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f);
else
{
@ -1464,8 +1516,11 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
alSourcef(source, AL_SEC_OFFSET, reuse_chan->StartTime.Lo/1000.f);
else
{
// FIXME: set offset based on the current time and the StartTime
alSourcef(source, AL_SAMPLE_OFFSET, 0.f);
float offset = std::chrono::duration_cast<std::chrono::duration<float>>(
std::chrono::steady_clock::now().time_since_epoch() -
std::chrono::steady_clock::time_point::duration(reuse_chan->StartTime.AsOne)
).count();
if(offset > 0.f) alSourcef(source, AL_SEC_OFFSET, offset);
}
}
if(getALError() != AL_NO_ERROR)
@ -1493,7 +1548,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
else chan->SysChannel = MAKE_PTRID(source);
chan->Rolloff = *rolloff;
chan->DistanceScale = distscale;
chan->DistanceSqr = dist_sqr;
chan->ManualRolloff = manualRolloff;
@ -1579,10 +1633,20 @@ void OpenALSoundRenderer::SetInactive(SoundRenderer::EInactiveState state)
{
case SoundRenderer::INACTIVE_Active:
alListenerf(AL_GAIN, 1.0f);
if(ALC.SOFT_pause_device)
{
alcDeviceResumeSOFT(Device);
getALCError(Device);
}
break;
/* FIXME: This doesn't stop anything. */
case SoundRenderer::INACTIVE_Complete:
if(ALC.SOFT_pause_device)
{
alcDevicePauseSOFT(Device);
getALCError(Device);
}
/* fall-through */
case SoundRenderer::INACTIVE_Mute:
alListenerf(AL_GAIN, 0.0f);
break;
@ -1631,26 +1695,26 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
if(chan == NULL || chan->SysChannel == NULL)
return;
alDeferUpdatesSOFT();
FVector3 dir = pos - listener->position;
chan->DistanceSqr = (float)dir.LengthSquared();
if(chan->ManualRolloff)
{
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
{
float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr) * chan->DistanceScale);
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
}
if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
if(!AL.EXT_SOURCE_RADIUS && areasound &&
chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{
FVector3 amb(0.f, !(dir.Y>=0.f) ? -1.f : 1.f, 0.f);
float a = sqrtf(chan->DistanceSqr) / AREA_SOUND_RADIUS;
dir = amb + (dir-amb)*a;
}
if(dir.DoesNotApproximatelyEqual(FVector3(0.f, 0.f, 0.f)))
{
float gain = GetRolloff(&chan->Rolloff, sqrtf(chan->DistanceSqr)*chan->DistanceScale);
dir.MakeResize((gain > 0.00001f) ? 1.f/gain : 100000.f);
}
}
else if(areasound && chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
else if(!AL.EXT_SOURCE_RADIUS && areasound &&
chan->DistanceSqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS)
{
float mindist = chan->Rolloff.MinDistance / chan->DistanceScale;
FVector3 amb(0.f, !(dir.Y>=0.f) ? -mindist : mindist, 0.f);
@ -1659,6 +1723,8 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh
}
dir += listener->position;
alDeferUpdatesSOFT();
ALuint source = GET_PTRID(chan->SysChannel);
alSource3f(source, AL_POSITION, dir[0], dir[1], -dir[2]);
alSource3f(source, AL_VELOCITY, vel[0], vel[1], -vel[2]);
@ -1802,7 +1868,7 @@ void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan)
{
// FIXME: Get current time (preferably from the audio clock, but the system
// time will have to do)
chan->StartTime.AsOne = 0;
chan->StartTime.AsOne = std::chrono::steady_clock::now().time_since_epoch().count();
}
float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan)

View file

@ -58,6 +58,11 @@
#define AL_FORMAT_71CHN32 0x1212
#endif
#ifndef AL_EXT_SOURCE_RADIUS
#define AL_EXT_SOURCE_RADIUS 1
#define AL_SOURCE_RADIUS 0x1031
#endif
#include "efx.h"
@ -124,9 +129,11 @@ private:
struct {
bool EXT_EFX;
bool EXT_disconnect;
bool SOFT_pause_device;
} ALC;
struct {
bool EXT_source_distance_model;
bool EXT_SOURCE_RADIUS;
bool SOFT_deferred_updates;
bool SOFT_loop_points;
} AL;
@ -174,6 +181,9 @@ private:
ALvoid (AL_APIENTRY*alDeferUpdatesSOFT)(void);
ALvoid (AL_APIENTRY*alProcessUpdatesSOFT)(void);
void (ALC_APIENTRY*alcDevicePauseSOFT)(ALCdevice *device);
void (ALC_APIENTRY*alcDeviceResumeSOFT)(ALCdevice *device);
void LoadReverb(const ReverbContainer *env);
void PurgeStoppedSources();
static FSoundChan *FindLowestChannel();

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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)