Add canvastexture definition to animdefs.

Split canvas texture rendering from camera texture rendering.
This commit is contained in:
Magnus Norddahl 2022-07-23 20:49:21 +02:00 committed by Christoph Oelckers
parent aa083604e1
commit bb503950df
15 changed files with 111 additions and 54 deletions

View file

@ -279,11 +279,8 @@ class FCanvas : public DObject
{
DECLARE_CLASS(FCanvas, DObject)
public:
FCanvas()
{
Drawer->SetSize(256, 256);
}
std::shared_ptr<F2DDrawer> Drawer = std::make_shared<F2DDrawer>();
F2DDrawer Drawer;
FCanvasTexture* Tex = nullptr;
};
struct DShape2DBufferInfo : RefCountedBase

View file

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

View file

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

View file

@ -229,13 +229,6 @@ void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<voi
bounds.height = FHardwareTexture::GetTexDimension(tex->GetHeight());
renderFunc(bounds);
if (tex->Drawer)
{
::Draw2D(tex->Drawer.get(), gl_RenderState);
tex->Drawer->Clear();
}
GLRenderer->EndOffscreen();
tex->SetUpdated(true);

View file

@ -215,12 +215,6 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function<voi
renderFunc(bounds);
if (tex->Drawer)
{
::Draw2D(tex->Drawer.get(), *mRenderState);
tex->Drawer->Clear();
}
mRenderState->EndRenderPass();
VkImageTransition()

View file

@ -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<F2DDrawer> Drawer;
FCanvas* Canvas = nullptr;
protected:

View file

@ -2926,6 +2926,7 @@ static void Doom_CastSpriteIDToString(FString* a, unsigned int b)
extern DThinker* NextToThink;
extern TArray<FCanvas*> 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++)

View file

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

View file

@ -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<FAnimDef::FAnimFrame>& 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);

View file

@ -110,19 +110,29 @@ void SetCameraToTexture(AActor *viewpoint, const FString &texturename, double fo
}
}
void SetCanvasToTexture(FCanvas* canvas, const FString& texturename)
TArray<FCanvas*> 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<FCanvasTexture*>(tex->GetTexture());
canvasTex->Drawer = canvas->Drawer;
if (!canvasTex->Canvas)
{
canvasTex->Canvas = Create<FCanvas>();
canvasTex->Canvas->Tex = canvasTex;
canvasTex->Canvas->Drawer.SetSize(tex->GetTexelWidth(), tex->GetTexelHeight());
AllCanvases.Push(canvasTex->Canvas);
}
return canvasTex->Canvas;
}
}
return nullptr;
}
//==========================================================================

View file

@ -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<FCanvas*> AllCanvases;

View file

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

View file

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

View file

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

View file

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