From 50d16c75d9af7c24335cd5f22030d6906be5ae5e Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Thu, 11 Aug 2022 00:09:41 +0800 Subject: [PATCH] Add corona actor --- src/CMakeLists.txt | 1 + src/namedef_custom.h | 2 + src/playsim/a_corona.cpp | 32 +++++ src/playsim/a_corona.h | 38 +++++ .../hwrenderer/scene/hw_drawinfo.cpp | 132 ++++++++++++++++++ src/rendering/hwrenderer/scene/hw_drawinfo.h | 5 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 7 + wadsrc/static/menudef.txt | 1 + wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/actors/shared/corona.zs | 7 + 10 files changed, 226 insertions(+) create mode 100644 src/playsim/a_corona.cpp create mode 100644 src/playsim/a_corona.h create mode 100644 wadsrc/static/zscript/actors/shared/corona.zs diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1ceb566f4..824087af6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 65bb6119f..b05bed0af 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -863,3 +863,5 @@ xx(lm_sampledist_ceiling) xx(lm_suncolor) xx(lm_sampledistance) xx(lm_gridsize) + +xx(Corona) diff --git a/src/playsim/a_corona.cpp b/src/playsim/a_corona.cpp new file mode 100644 index 000000000..0e0cb4a98 --- /dev/null +++ b/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(); +} diff --git a/src/playsim/a_corona.h b/src/playsim/a_corona.h new file mode 100644 index 000000000..2c66f0a20 --- /dev/null +++ b/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; +}; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 427a91dfd..14eb54c83 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -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) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 52f397dcc..931d888dc 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -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 Portals; TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray hudsprites; // These may just be stored by value. + TArray Coronas; + uint64_t LastFrameTime = 0; TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -300,6 +303,8 @@ public: void DrawDecals(FRenderState &state, TArray &decals); void DrawPlayerSprites(bool hudModelStep, FRenderState &state); + void DrawCoronas(FRenderState& state); + void DrawCorona(FRenderState& state, ACorona* corona, double dist); void ProcessLowerMinisegs(TArray &lowersegs); void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index d5652f409..3e44171db 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -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(thing)); + return; + } + const auto &vp = di->Viewpoint; AActor *camera = vp.camera; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index a69447894..08e5125d5 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -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 " " diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index d3c7dd883..7ab36d785 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -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" diff --git a/wadsrc/static/zscript/actors/shared/corona.zs b/wadsrc/static/zscript/actors/shared/corona.zs new file mode 100644 index 000000000..986f441e4 --- /dev/null +++ b/wadsrc/static/zscript/actors/shared/corona.zs @@ -0,0 +1,7 @@ +class Corona : Actor native +{ + Default + { + RenderRadius 1024.0; + } +}