Skip to content

Commit

Permalink
Add corona actor
Browse files Browse the repository at this point in the history
  • Loading branch information
nashmuhandes committed Aug 11, 2022
1 parent 4710a40 commit 50d16c7
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -920,6 +920,7 @@ set (PCH_SOURCES
playsim/mapthinkers/dsectoreffect.cpp
playsim/a_pickups.cpp
playsim/a_action.cpp
playsim/a_corona.cpp
playsim/a_decals.cpp
playsim/a_dynlight.cpp
playsim/a_flashfader.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/namedef_custom.h
Expand Up @@ -863,3 +863,5 @@ xx(lm_sampledist_ceiling)
xx(lm_suncolor)
xx(lm_sampledistance)
xx(lm_gridsize)

xx(Corona)
32 changes: 32 additions & 0 deletions src/playsim/a_corona.cpp
@@ -0,0 +1,32 @@
/*
** Light Coronas
** Copyright (c) 2022 Nash Muhandes, Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
*/


#include "actor.h"
#include "a_corona.h"
#include "a_dynlight.h"

IMPLEMENT_CLASS(ACorona, false, false)

void ACorona::Tick()
{
Super::Tick();
}
38 changes: 38 additions & 0 deletions src/playsim/a_corona.h
@@ -0,0 +1,38 @@
/*
** Light Coronas
** Copyright (c) 2022 Nash Muhandes, Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
*/

#pragma once

#include "actor.h"

EXTERN_CVAR(Bool, gl_coronas)

class AActor;

class ACorona : public AActor
{
DECLARE_CLASS(ACorona, AActor)

public:
void Tick();

float CoronaFade = 0.0f;
};
132 changes: 132 additions & 0 deletions src/rendering/hwrenderer/scene/hw_drawinfo.cpp
Expand Up @@ -44,6 +44,8 @@
#include "hw_vrmodes.h"
#include "hw_clipper.h"
#include "v_draw.h"
#include "a_corona.h"
#include "texturemanager.h"

EXTERN_CVAR(Float, r_visibility)
CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
Expand All @@ -55,6 +57,8 @@ CVAR(Bool, gl_texture, true, 0)
CVAR(Float, gl_mask_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_mask_sprite_threshold, 0.5f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)

CVAR(Bool, gl_coronas, true, CVAR_ARCHIVE);

sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);

//==========================================================================
Expand Down Expand Up @@ -165,6 +169,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni

for (int i = 0; i < GLDL_TYPES; i++) drawlists[i].Reset();
hudsprites.Clear();
Coronas.Clear();
vpIndex = 0;

// Fullbright information needs to be propagated from the main view.
Expand Down Expand Up @@ -569,6 +574,128 @@ void HWDrawInfo::RenderPortal(HWPortal *p, FRenderState &state, bool usestencil)

}

void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist)
{
spriteframe_t* sprframe = &SpriteFrames[sprites[corona->sprite].spriteframes + (size_t)corona->SpawnState->GetFrame()];
FTextureID patch = sprframe->Texture[0];
if (!patch.isValid()) return;
auto tex = TexMan.GetGameTexture(patch, false);
if (!tex || !tex->isValid()) return;

// Project the corona sprite center
FVector4 worldPos((float)corona->X(), (float)corona->Z(), (float)corona->Y(), 1.0f);
FVector4 viewPos, clipPos;
VPUniforms.mViewMatrix.multMatrixPoint(&worldPos[0], &viewPos[0]);
VPUniforms.mProjectionMatrix.multMatrixPoint(&viewPos[0], &clipPos[0]);
if (clipPos.W < -1.0f) return; // clip z nearest
float halfViewportWidth = screen->GetWidth() * 0.5f;
float halfViewportHeight = screen->GetHeight() * 0.5f;
float invW = 1.0f / clipPos.W;
float screenX = halfViewportWidth + clipPos.X * invW * halfViewportWidth;
float screenY = halfViewportHeight - clipPos.Y * invW * halfViewportHeight;

float alpha = corona->CoronaFade * float(corona->Alpha);

// distance-based fade - looks better IMO
float distNearFadeStart = float(corona->RenderRadius()) * 0.1f;
float distFarFadeStart = float(corona->RenderRadius()) * 0.5f;
float distFade = 1.0f;

if (float(dist) < distNearFadeStart)
distFade -= abs(((float(dist) - distNearFadeStart) / distNearFadeStart));
else if (float(dist) >= distFarFadeStart)
distFade -= (float(dist) - distFarFadeStart) / distFarFadeStart;

alpha *= distFade;

state.SetColorAlpha(0xffffff, alpha, 0);
if (isSoftwareLighting()) state.SetSoftLightLevel(255);
else state.SetNoSoftLightLevel();

state.SetLightIndex(-1);
state.SetRenderStyle(corona->RenderStyle);
state.SetTextureMode(corona->RenderStyle);

state.SetMaterial(tex, UF_Sprite, CTF_Expand, CLAMP_XY_NOMIP, 0, 0);

float scale = screen->GetHeight() / 1000.0f;
float tileWidth = corona->Scale.X * tex->GetDisplayWidth() * scale;
float tileHeight = corona->Scale.Y * tex->GetDisplayHeight() * scale;
float x0 = screenX - tileWidth, y0 = screenY - tileHeight;
float x1 = screenX + tileWidth, y1 = screenY + tileHeight;

float u0 = 0.0f, v0 = 0.0f;
float u1 = 1.0f, v1 = 1.0f;

auto vert = screen->mVertexData->AllocVertices(4);
auto vp = vert.first;
unsigned int vertexindex = vert.second;

vp[0].Set(x0, y0, 1.0f, u0, v0);
vp[1].Set(x1, y0, 1.0f, u1, v0);
vp[2].Set(x0, y1, 1.0f, u0, v1);
vp[3].Set(x1, y1, 1.0f, u1, v1);

state.Draw(DT_TriangleStrip, vertexindex, 4);
}

static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
{
FRenderViewpoint* data = (FRenderViewpoint*)userdata;
if (res.HitType == TRACE_HitActor && res.Actor && res.Actor == data->ViewActor)
{
return TRACE_Skip;
}

return TRACE_Stop;
}


void HWDrawInfo::DrawCoronas(FRenderState& state)
{
state.EnableDepthTest(false);
state.SetDepthMask(false);

HWViewpointUniforms vp = VPUniforms;
vp.mViewMatrix.loadIdentity();
vp.mProjectionMatrix = VRMode::GetVRMode(true)->GetHUDSpriteProjection();
screen->mViewpoints->SetViewpoint(state, &vp);

float timeElapsed = (screen->FrameTime - LastFrameTime) / 1000.0f;
LastFrameTime = screen->FrameTime;

for (ACorona* corona : Coronas)
{
DVector3 direction = Viewpoint.Pos - corona->Pos();
double dist = direction.Length();

// skip coronas that are too far
if (dist > corona->RenderRadius())
continue;

static const float fadeSpeed = 9.0f;

direction.MakeUnit();
FTraceResults results;
if (!Trace(corona->Pos(), corona->Sector, direction, dist, MF_SOLID, ML_BLOCKEVERYTHING, corona, results, 0, CheckForViewpointActor, &Viewpoint))
{
corona->CoronaFade = std::min(corona->CoronaFade + timeElapsed * fadeSpeed, 1.0f);
}
else
{
corona->CoronaFade = std::max(corona->CoronaFade - timeElapsed * fadeSpeed, 0.0f);
}

if (corona->CoronaFade > 0.0f)
DrawCorona(state, corona, dist);
}

state.SetTextureMode(TM_NORMAL);
screen->mViewpoints->Bind(state, vpIndex);
state.EnableDepthTest(true);
state.SetDepthMask(true);
}

//-----------------------------------------------------------------------------
//
// Draws player sprites and color blend
Expand All @@ -580,6 +707,11 @@ void HWDrawInfo::EndDrawScene(sector_t * viewsector, FRenderState &state)
{
state.EnableFog(false);

if (gl_coronas && Coronas.Size() > 0)
{
DrawCoronas(state);
}

// [BB] HUD models need to be rendered here.
const bool renderHUDModel = IsHUDModelForPlayerAvailable(players[consoleplayer].camera->player);
if (renderHUDModel)
Expand Down
5 changes: 5 additions & 0 deletions src/rendering/hwrenderer/scene/hw_drawinfo.h
Expand Up @@ -29,6 +29,7 @@ class IShadowMap;
struct particle_t;
struct FDynLightData;
struct HUDSprite;
class ACorona;
class Clipper;
class HWPortal;
class FFlatVertexBuffer;
Expand Down Expand Up @@ -150,6 +151,8 @@ struct HWDrawInfo
TArray<HWPortal *> Portals;
TArray<HWDecal *> Decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
TArray<HUDSprite> hudsprites; // These may just be stored by value.
TArray<ACorona*> Coronas;
uint64_t LastFrameTime = 0;

TArray<MissingTextureInfo> MissingUpperTextures;
TArray<MissingTextureInfo> MissingLowerTextures;
Expand Down Expand Up @@ -300,6 +303,8 @@ struct HWDrawInfo

void DrawDecals(FRenderState &state, TArray<HWDecal *> &decals);
void DrawPlayerSprites(bool hudModelStep, FRenderState &state);
void DrawCoronas(FRenderState& state);
void DrawCorona(FRenderState& state, ACorona* corona, double dist);

void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub);
Expand Down
7 changes: 7 additions & 0 deletions src/rendering/hwrenderer/scene/hw_sprites.cpp
Expand Up @@ -33,6 +33,7 @@
#include "r_sky.h"
#include "r_utility.h"
#include "a_pickups.h"
#include "a_corona.h"
#include "d_player.h"
#include "g_levellocals.h"
#include "events.h"
Expand Down Expand Up @@ -703,6 +704,12 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
return;
}

if (thing->IsKindOf(NAME_Corona))
{
di->Coronas.Push(static_cast<ACorona*>(thing));
return;
}

const auto &vp = di->Viewpoint;
AActor *camera = vp.camera;

Expand Down
1 change: 1 addition & 0 deletions wadsrc/static/menudef.txt
Expand Up @@ -2637,6 +2637,7 @@ OptionMenu "OpenGLOptions" protected
Option "$GLPREFMNU_SPRBILLFACECAMERA", gl_billboard_faces_camera, "OnOff"
Option "$GLPREFMNU_PARTICLESTYLE", gl_particles_style, "Particles"
Option "$GLPREFMNU_RENDERQUALITY", gl_seamless, "Precision"
Option "$GLPREFMNU_CORONAS", gl_coronas, "OnOff"
StaticText " "
Slider "$GLPREFMNU_MENUBLUR", gl_menu_blur, 0, 5.0, 0.5, 2
StaticText " "
Expand Down
1 change: 1 addition & 0 deletions wadsrc/static/zscript.txt
Expand Up @@ -92,6 +92,7 @@ version "4.9"
#include "zscript/actors/shared/fastprojectile.zs"
#include "zscript/actors/shared/randomspawner.zs"
#include "zscript/actors/shared/dynlights.zs"
#include "zscript/actors/shared/corona.zs"

#include "zscript/actors/doom/doomplayer.zs"
#include "zscript/actors/doom/possessed.zs"
Expand Down
7 changes: 7 additions & 0 deletions wadsrc/static/zscript/actors/shared/corona.zs
@@ -0,0 +1,7 @@
class Corona : Actor native
{
Default
{
RenderRadius 1024.0;
}
}

0 comments on commit 50d16c7

Please sign in to comment.