From bb503950df7790773d024f2ef4e2371d90281976 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 23 Jul 2022 20:49:21 +0200 Subject: [PATCH] Add canvastexture definition to animdefs. Split canvas texture rendering from camera texture rendering. --- src/common/2d/v_2ddrawer.h | 7 +-- src/common/2d/v_draw.cpp | 61 ++++++++++++------- src/common/2d/v_drawtext.cpp | 6 +- src/common/rendering/gl/gl_framebuffer.cpp | 7 --- .../vulkan/system/vk_framebuffer.cpp | 6 -- src/common/textures/textures.h | 5 +- src/d_main.cpp | 3 + src/gamedata/textures/animations.cpp | 19 ++++++ src/gamedata/textures/animations.h | 1 + src/r_data/r_canvastexture.cpp | 16 ++++- src/r_data/r_canvastexture.h | 4 ++ src/rendering/hwrenderer/hw_entrypoint.cpp | 16 +++++ src/scripting/vmthunks.cpp | 10 +-- wadsrc/static/zscript/doombase.zs | 2 +- wadsrc/static/zscript/engine/base.zs | 2 +- 15 files changed, 111 insertions(+), 54 deletions(-) diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index bb1663ebb..1d9af77cb 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -279,11 +279,8 @@ class FCanvas : public DObject { DECLARE_CLASS(FCanvas, DObject) public: - FCanvas() - { - Drawer->SetSize(256, 256); - } - std::shared_ptr Drawer = std::make_shared(); + F2DDrawer Drawer; + FCanvasTexture* Tex = nullptr; }; struct DShape2DBufferInfo : RefCountedBase diff --git a/src/common/2d/v_draw.cpp b/src/common/2d/v_draw.cpp index 780692f2e..85f5e76c9 100644 --- a/src/common/2d/v_draw.cpp +++ b/src/common/2d/v_draw.cpp @@ -273,7 +273,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawTexture) auto tex = TexMan.GameByIndex(texid, animate); VMVa_List args = { param + 5, 0, numparam - 6, va_reginfo + 5 }; - DoDrawTexture(self->Drawer.get(), tex, x, y, args); + DoDrawTexture(&self->Drawer, tex, x, y, args); + self->Tex->NeedUpdate(); return 0; } @@ -348,7 +349,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawShape) auto tex = TexMan.GameByIndex(texid, animate); VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; - DrawShape(self->Drawer.get(), tex, shape, args); + DrawShape(&self->Drawer, tex, shape, args); + self->Tex->NeedUpdate(); return 0; } @@ -384,7 +386,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawShapeFill) color.a = int(amount * 255.0f); - DrawShapeFill(self->Drawer.get(), color, shape, args); + DrawShapeFill(&self->Drawer, color, shape, args); + self->Tex->NeedUpdate(); return 0; } @@ -420,7 +423,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, SetClipRect) PARAM_INT(y); PARAM_INT(w); PARAM_INT(h); - self->Drawer->SetClipRect(x, y, w, h); + self->Drawer.SetClipRect(x, y, w, h); + self->Tex->NeedUpdate(); return 0; } @@ -434,7 +438,8 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) DEFINE_ACTION_FUNCTION(FCanvas, ClearClipRect) { PARAM_SELF_PROLOGUE(FCanvas); - self->Drawer->ClearClipRect(); + self->Drawer.ClearClipRect(); + self->Tex->NeedUpdate(); return 0; } @@ -448,7 +453,8 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearScreen) DEFINE_ACTION_FUNCTION(FCanvas, ClearScreen) { PARAM_SELF_PROLOGUE(FCanvas); - self->Drawer->ClearScreen(); + self->Drawer.ClearScreen(); + self->Tex->NeedUpdate(); return 0; } @@ -464,7 +470,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, SetScreenFade) { PARAM_SELF_PROLOGUE(FCanvas); PARAM_FLOAT(x); - self->Drawer->SetScreenFade(float(x)); + self->Drawer.SetScreenFade(float(x)); + self->Tex->NeedUpdate(); return 0; } @@ -493,7 +500,7 @@ DEFINE_ACTION_FUNCTION(FCanvas, GetClipRect) { PARAM_SELF_PROLOGUE(FCanvas); int x, y, w, h; - self->Drawer->GetClipRect(&x, &y, &w, &h); + self->Drawer.GetClipRect(&x, &y, &w, &h); if (numret > 0) ret[0].SetInt(x); if (numret > 1) ret[1].SetInt(y); if (numret > 2) ret[2].SetInt(w); @@ -613,8 +620,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, GetFullscreenRect) DrawParms parms; DoubleRect rect; - parms.viewport.width = self->Drawer->GetWidth(); - parms.viewport.height = self->Drawer->GetHeight(); + parms.viewport.width = self->Drawer.GetWidth(); + parms.viewport.height = self->Drawer.GetHeight(); CalcFullscreenScale(&parms, virtw, virth, fsmode, rect); if (numret >= 1) ret[0].SetFloat(rect.left); if (numret >= 2) ret[1].SetFloat(rect.top); @@ -1526,7 +1533,7 @@ DEFINE_ACTION_FUNCTION(FCanvas, VirtualToRealCoords) PARAM_FLOAT(vh); PARAM_BOOL(vbottom); PARAM_BOOL(handleaspect); - VirtualToRealCoords(self->Drawer.get(), x, y, w, h, vw, vh, vbottom, handleaspect); + VirtualToRealCoords(&self->Drawer, x, y, w, h, vw, vh, vbottom, handleaspect); if (numret >= 1) ret[0].SetVector2(DVector2(x, y)); if (numret >= 2) ret[1].SetVector2(DVector2(w, h)); return min(numret, 2); @@ -1582,7 +1589,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawLine) PARAM_INT(y1); PARAM_INT(color); PARAM_INT(alpha); - self->Drawer->AddLine((float)x0, (float)y0, (float)x1, (float)y1, -1, -1, INT_MAX, INT_MAX, color | MAKEARGB(255, 0, 0, 0), alpha); + self->Drawer.AddLine((float)x0, (float)y0, (float)x1, (float)y1, -1, -1, INT_MAX, INT_MAX, color | MAKEARGB(255, 0, 0, 0), alpha); + self->Tex->NeedUpdate(); return 0; } @@ -1616,7 +1624,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawThickLine) PARAM_FLOAT(thickness); PARAM_INT(color); PARAM_INT(alpha); - self->Drawer->AddThickLine(x0, y0, x1, y1, thickness, color, alpha); + self->Drawer.AddThickLine(x0, y0, x1, y1, thickness, color, alpha); + self->Tex->NeedUpdate(); return 0; } @@ -1688,7 +1697,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, Clear) PARAM_INT(y2); PARAM_INT(color); PARAM_INT(palcol); - ClearRect(self->Drawer.get(), x1, y1, x2, y2, palcol, color); + ClearRect(&self->Drawer, x1, y1, x2, y2, palcol, color); + self->Tex->NeedUpdate(); return 0; } @@ -1766,7 +1776,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, Dim) PARAM_INT(w); PARAM_INT(h); PARAM_INT(style); - Dim(self->Drawer.get(), color, float(amount), x1, y1, w, h, &LegacyRenderStyles[style]); + Dim(&self->Drawer, color, float(amount), x1, y1, w, h, &LegacyRenderStyles[style]); + self->Tex->NeedUpdate(); return 0; } @@ -1835,7 +1846,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawLineFrame) PARAM_INT(width); PARAM_INT(height); PARAM_INT(thickness); - DrawFrame(self->Drawer.get(), color, left, top, width, height, thickness); + DrawFrame(&self->Drawer, color, left, top, width, height, thickness); + self->Tex->NeedUpdate(); return 0; } @@ -1859,7 +1871,7 @@ DEFINE_ACTION_FUNCTION(FCanvas, SetOffset) PARAM_SELF_PROLOGUE(FCanvas); PARAM_FLOAT(x); PARAM_FLOAT(y); - ACTION_RETURN_VEC2(self->Drawer->SetOffset(DVector2(x, y))); + ACTION_RETURN_VEC2(self->Drawer.SetOffset(DVector2(x, y))); } DEFINE_ACTION_FUNCTION(_Screen, EnableStencil) @@ -1878,7 +1890,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, EnableStencil) PARAM_SELF_PROLOGUE(FCanvas); PARAM_BOOL(on); - self->Drawer->AddEnableStencil(on); + self->Drawer.AddEnableStencil(on); + self->Tex->NeedUpdate(); return 0; } @@ -1902,7 +1915,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, SetStencil) PARAM_INT(op); PARAM_INT(flags); - self->Drawer->AddSetStencil(offs, op, flags); + self->Drawer.AddSetStencil(offs, op, flags); + self->Tex->NeedUpdate(); return 0; } @@ -1920,7 +1934,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, ClearStencil) { PARAM_SELF_PROLOGUE(FCanvas); - self->Drawer->AddClearStencil(); + self->Drawer.AddClearStencil(); + self->Tex->NeedUpdate(); return 0; } @@ -1941,7 +1956,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, SetTransform) PARAM_SELF_PROLOGUE(FCanvas); PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); - self->Drawer->SetTransform(*transform); + self->Drawer.SetTransform(*transform); + self->Tex->NeedUpdate(); return 0; } @@ -1960,7 +1976,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, ClearTransform) { PARAM_SELF_PROLOGUE(FCanvas); - self->Drawer->ClearTransform(); + self->Drawer.ClearTransform(); + self->Tex->NeedUpdate(); return 0; } diff --git a/src/common/2d/v_drawtext.cpp b/src/common/2d/v_drawtext.cpp index c475707e9..143cc911a 100644 --- a/src/common/2d/v_drawtext.cpp +++ b/src/common/2d/v_drawtext.cpp @@ -247,7 +247,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawChar) PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array VMVa_List args = { param + 6, 0, numparam - 7, va_reginfo + 6 }; - DrawChar(self->Drawer.get(), font, cr, x, y, chr, args); + DrawChar(&self->Drawer, font, cr, x, y, chr, args); + self->Tex->NeedUpdate(); return 0; } @@ -450,7 +451,8 @@ DEFINE_ACTION_FUNCTION(FCanvas, DrawText) VMVa_List args = { param + 6, 0, numparam - 7, va_reginfo + 6 }; const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); - DrawText(self->Drawer.get(), font, cr, x, y, txt, args); + DrawText(&self->Drawer, font, cr, x, y, txt, args); + self->Tex->NeedUpdate(); return 0; } diff --git a/src/common/rendering/gl/gl_framebuffer.cpp b/src/common/rendering/gl/gl_framebuffer.cpp index 422eccccd..52cf004d0 100644 --- a/src/common/rendering/gl/gl_framebuffer.cpp +++ b/src/common/rendering/gl/gl_framebuffer.cpp @@ -229,13 +229,6 @@ void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::functionGetHeight()); renderFunc(bounds); - - if (tex->Drawer) - { - ::Draw2D(tex->Drawer.get(), gl_RenderState); - tex->Drawer->Clear(); - } - GLRenderer->EndOffscreen(); tex->SetUpdated(true); diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.cpp b/src/common/rendering/vulkan/system/vk_framebuffer.cpp index ee40a739b..55ce448fd 100644 --- a/src/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -215,12 +215,6 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::functionDrawer) - { - ::Draw2D(tex->Drawer.get(), *mRenderState); - tex->Drawer->Clear(); - } - mRenderState->EndRenderPass(); VkImageTransition() diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index 89f0b9212..6af12ea4c 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -303,7 +303,7 @@ public: friend class FTextureManager; }; -class F2DDrawer; +class FCanvas; // A texture that can be drawn to. @@ -321,10 +321,11 @@ public: void NeedUpdate() { bNeedsUpdate = true; } void SetUpdated(bool rendertype) { bNeedsUpdate = false; bFirstUpdate = false; bLastUpdateType = rendertype; } + bool CheckNeedsUpdate() const { return bNeedsUpdate; } void SetAspectRatio(double aspectScale, bool useTextureRatio) { aspectRatio = (float)aspectScale * (useTextureRatio? ((float)Width / Height) : 1); } - std::shared_ptr Drawer; + FCanvas* Canvas = nullptr; protected: diff --git a/src/d_main.cpp b/src/d_main.cpp index df1051af5..7b90b5fc4 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2926,6 +2926,7 @@ static void Doom_CastSpriteIDToString(FString* a, unsigned int b) extern DThinker* NextToThink; +extern TArray AllCanvases; static void GC_MarkGameRoots() { @@ -2933,6 +2934,8 @@ static void GC_MarkGameRoots() GC::Mark(staticEventManager.LastEventHandler); for (auto Level : AllLevels()) Level->Mark(); + for (auto canvas : AllCanvases) + GC::Mark(canvas); // Mark players. for (int i = 0; i < MAXPLAYERS; i++) diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 84d87f113..61bb6d29c 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -325,6 +325,10 @@ void FTextureAnimator::InitAnimDefs () { ParseWarp(sc); } + else if (sc.Compare("canvastexture")) + { + ParseCanvasTexture(sc); + } else if (sc.Compare ("cameratexture")) { ParseCameraTexture(sc); @@ -683,6 +687,21 @@ void FTextureAnimator::ParseWarp(FScanner &sc) } } + +//========================================================================== +// +// ParseCameraTexture +// +// Parses a canvas texture definition +// +//========================================================================== + +void FTextureAnimator::ParseCanvasTexture(FScanner& sc) +{ + // This is currently identical to camera textures. + ParseCameraTexture(sc); +} + //========================================================================== // // ParseCameraTexture diff --git a/src/gamedata/textures/animations.h b/src/gamedata/textures/animations.h index b519cfbf1..b52151980 100644 --- a/src/gamedata/textures/animations.h +++ b/src/gamedata/textures/animations.h @@ -69,6 +69,7 @@ class FTextureAnimator FAnimDef* ParseRangeAnim(FScanner& sc, FTextureID picnum, ETextureType usetype, bool missing); void ParsePicAnim(FScanner& sc, FTextureID picnum, ETextureType usetype, bool missing, TArray& frames); void ParseWarp(FScanner& sc); + void ParseCanvasTexture(FScanner& sc); void ParseCameraTexture(FScanner& sc); FTextureID ParseFramenum(FScanner& sc, FTextureID basepicnum, ETextureType usetype, bool allowMissing); void ParseTime(FScanner& sc, uint32_t& min, uint32_t& max); diff --git a/src/r_data/r_canvastexture.cpp b/src/r_data/r_canvastexture.cpp index 95fe33ac7..3986aff97 100644 --- a/src/r_data/r_canvastexture.cpp +++ b/src/r_data/r_canvastexture.cpp @@ -110,19 +110,29 @@ void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fo } } -void SetCanvasToTexture(FCanvas* canvas, const FString& texturename) +TArray AllCanvases; + +FCanvas* GetTextureCanvas(const FString& texturename) { FTextureID textureid = TexMan.CheckForTexture(texturename, ETextureType::Wall, FTextureManager::TEXMAN_Overridable); if (textureid.isValid()) { - // Only proceed if the texture actually has a canvas. + // Only proceed if the texture is a canvas texture. auto tex = TexMan.GetGameTexture(textureid); if (tex && tex->GetTexture()->isCanvas()) { FCanvasTexture* canvasTex = static_cast(tex->GetTexture()); - canvasTex->Drawer = canvas->Drawer; + if (!canvasTex->Canvas) + { + canvasTex->Canvas = Create(); + canvasTex->Canvas->Tex = canvasTex; + canvasTex->Canvas->Drawer.SetSize(tex->GetTexelWidth(), tex->GetTexelHeight()); + AllCanvases.Push(canvasTex->Canvas); + } + return canvasTex->Canvas; } } + return nullptr; } //========================================================================== diff --git a/src/r_data/r_canvastexture.h b/src/r_data/r_canvastexture.h index b69c46687..7ea137504 100644 --- a/src/r_data/r_canvastexture.h +++ b/src/r_data/r_canvastexture.h @@ -1,6 +1,8 @@ #pragma once +class FCanvas; class FCanvasTexture; + // This list keeps track of the cameras that draw into canvas textures. struct FCanvasTextureEntry { @@ -22,3 +24,5 @@ struct FCanvasTextureInfo void Mark(); }; + +extern TArray AllCanvases; diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index d3d409356..f27abec59 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -41,6 +41,7 @@ #include "v_palette.h" #include "d_main.h" #include "g_cvars.h" +#include "v_draw.h" #include "hw_lightbuffer.h" #include "hw_cvars.h" @@ -350,6 +351,21 @@ sector_t* RenderView(player_t* player) // Shader start time does not need to be handled per level. Just use the one from the camera to render from. if (player->camera) CheckTimer(*RenderState, player->camera->Level->ShaderStartTime); + + // Draw all canvases that changed + for (FCanvas* canvas : AllCanvases) + { + if (canvas->Tex->CheckNeedsUpdate()) + { + screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) + { + Draw2D(&canvas->Drawer, *screen->RenderState()); + canvas->Drawer.Clear(); + }); + canvas->Tex->SetUpdated(true); + } + } + // prepare all camera textures that have been used in the last frame. // This must be done for all levels, not just the primary one! for (auto Level : AllLevels()) diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 37102bde6..61afa2f33 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -102,15 +102,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCameraTextureAspectRatio, SetCameraTex return 0; } -void SetCanvasToTexture(FCanvas* canvas, const FString& texturename); +FCanvas* GetTextureCanvas(const FString& texturename); -DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, SetCanvasToTexture, SetCanvasToTexture) +DEFINE_ACTION_FUNCTION(_TexMan, GetCanvas) { PARAM_PROLOGUE; - PARAM_OBJECT(canvas, FCanvas); PARAM_STRING(texturename); - SetCanvasToTexture(canvas, texturename); - return 0; + FCanvas* canvas = GetTextureCanvas(texturename); + if (numret > 0) ret[0].SetPointer(canvas); + return numret; } //===================================================================================== diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 365e9d256..2abfce6ed 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -28,7 +28,7 @@ extend struct TexMan { native static void SetCameraToTexture(Actor viewpoint, String texture, double fov); native static void SetCameraTextureAspectRatio(String texture, double aspectScale, bool useTextureRatio = true); - native static void SetCanvasToTexture(Canvas canvas, String texture); + native static Canvas GetCanvas(String texture); deprecated("3.8", "Use Level.ReplaceTextures() instead") static void ReplaceTextures(String from, String to, int flags) { level.ReplaceTextures(from, to, flags); diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 7bc46a7a2..118ba51db 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -502,7 +502,7 @@ class Shape2D : Object native native void PushTriangle( int a, int b, int c ); } -class Canvas : Object native +class Canvas : Object native abstract { native void Clear(int left, int top, int right, int bottom, Color color, int palcolor = -1); native void Dim(Color col, double amount, int x, int y, int w, int h, ERenderStyle style = STYLE_Translucent);