Add corona actor

This commit is contained in:
nashmuhandes 2022-08-11 00:09:41 +08:00
parent 4710a40fb5
commit 50d16c75d9
10 changed files with 226 additions and 0 deletions

View file

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

View file

@ -863,3 +863,5 @@ xx(lm_sampledist_ceiling)
xx(lm_suncolor)
xx(lm_sampledistance)
xx(lm_gridsize)
xx(Corona)

32
src/playsim/a_corona.cpp Normal file
View file

@ -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
src/playsim/a_corona.h Normal file
View file

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

View file

@ -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)
@ -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);
//==========================================================================
@ -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.
@ -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
@ -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)

View file

@ -29,6 +29,7 @@ class IShadowMap;
struct particle_t;
struct FDynLightData;
struct HUDSprite;
class ACorona;
class Clipper;
class HWPortal;
class FFlatVertexBuffer;
@ -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;
@ -300,6 +303,8 @@ public:
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);

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
class Corona : Actor native
{
Default
{
RenderRadius 1024.0;
}
}