Jump to content

Recommended Posts

  • Active+ Member

RenderTarget - Rework

 

This is an extend to the original RenderTarget system with several quality-of-life features,

rendering improvements, and a cleaner API, making it significantly easier to integrate into modern systems such as

Wiki, Dungeon Info, Item Preview, Etc..

68747470733a2f2f692e6962622e636f2f524a32

68747470733a2f2f692e6962622e636f2f787464

68747470733a2f2f692e6962622e636f2f7a574e

68747470733a2f2f692e6962622e636f2f383442

68747470733a2f2f692e6962622e636f2f707658


---

Features

Automatic RenderTarget Index Allocation

RenderTarget IDs are now allocated automatically by the engine.

This completely removes manual index management and guarantees that multiple systems can safely create RenderTargets without conflicting IDs.

### Old Method

def __init__(self):
    ui.Whatever.__init__(self)
    self.renderKey = 5

def OnRenderMob(self, race):
    self.modelRenderer = ui.RenderTarget()
    self.modelRenderer.SetParent(self.board)
    self.modelRenderer.SetSize(260, 170)
    self.modelRenderer.SetRenderTarget(self.renderKey)
    self.modelRenderer.Show()

    renderTarget.SetBackground(self.renderKey, "background.sub")
    renderTarget.SetVisibility(self.renderKey, True)
    renderTarget.SelectModel(self.renderKey, race)

### New Method

def OnRenderMob(self, race):
    self.modelRenderer = ui.RenderTarget()
    self.modelRenderer.SetParent(self.board)
    self.modelRenderer.SetSize(260, 170)
    self.modelRenderer.Show()

    key = self.modelRenderer.GetRenderTargetIndex()

    renderTarget.SetBackground(key, "background.sub")
    renderTarget.SetVisibility(key, True)
    renderTarget.SelectModel(key, race)

No manual IDs.

No duplicated RenderTargets.

Completely plug-and-play.

 

Note

this:
	key = self.modelRenderer.GetRenderTargetIndex()

will only be available after:
	self.modelRenderer.SetSize(260, 170)

not before !

 

Smooth Mouse Rotation

Drag the model with the mouse to rotate it smoothly.

Rotation uses inertia for a much more natural feeling.

---

Smooth Mouse Wheel Zoom

Zooming is velocity-based with damping instead of instantly jumping between positions.

---

Automatic Camera Fitting

The camera automatically adjusts itself based on the rendered model's height.

This allows players, monsters, NPCs and objects to appear correctly centered without requiring manual camera values for every race.

 

.gif

---

Hair Preview Camera

Hair preview can automatically switch to a dedicated camera focused on the character's head.

.png 

 

Example

renderTarget.SetHair(key, hairCostumeVnum, True)   # Hair Preview

renderTarget.SetHair(key, hairCostumeVnum)         # Normal Preview (False is the default value)

 

Automatic Hair Model Detection

Simply pass the costume hair VNUM.

The RenderTarget automatically resolves the correct hair model internally without requiring manual `value(3)` extraction.

---

Equipment Persistence

The RenderTarget automatically remembers compatible equipment for every race.

Supported parts:

* Armor
* Weapon
* Hair
* Acce
* Weapon Shining
* Armor Shining

Switching between races automatically restores the appropriate equipment whenever possible.

---

Optional Auto Rotation

Auto rotation can be enabled per model.

Example

renderTarget.SelectModel(key, race, True)   # Auto Rotate

renderTarget.SelectModel(key, race)         # Static Model (False is the default value)

 

 

Automatic Weapon Selection for Weapon Shining

If no weapon is equipped, the RenderTarget automatically equips a compatible default weapon before applying the weapon shining.

This allows weapon shining previews to work correctly without requiring additional setup.

---

Modern C++ Memory Management

The RenderTarget has been modernized using smart pointers (`std::unique_ptr` / `std::shared_ptr`) for safer and cleaner resource management.

---

Cleaner API

Several APIs have been simplified to reduce boilerplate and make RenderTarget integration much easier for future systems.

 

 

Final Note

 

These improvements are not a drag-and-drop solution.

Although they dramatically simplify the implementation process—especially for large systems like the Wiki—you still need to understand what you're doing. They are meant to eliminate a lot of the repetitive work and common headaches, making development much faster and cleaner, not replacing proper integration.

If you've already gone through the features listed above, you'll notice that many tedious tasks are now handled automatically, allowing you to focus on building your system instead of dealing with render target management.

Also, keep in mind that the GrpRenderTargetTexture implementation I shared is written for DirectX 9. If your source is still using DirectX 8, you'll likely need to make a few adjustments to ensure compatibility.

-

Lastly, I may have missed or forgotten something while putting this together. If you notice anything missing or think there's an improvement worth adding, feel free to leave a comment. I'll review it and, if appropriate, add it to the repository so everyone can benefit.

 

Spoiler
This is the hidden content, please

Alternative download links →

This is the hidden content, please

 

 

 
  • Metin2 Dev 19
  • Flame 1
  • Good 5
  • Love 1
  • Love 14

I don’t know — I think.

 

Discord

 

Link to comment
https://metin2.dev/topic/34585-rendertarget-rework/
Share on other sites

  • 4 weeks later...
  • Active+ Member

Update: Memory Leak Fix

 

I found and fixed a real memory/VRAM leak in the RenderTarget lifecycle.

The issue was that destroying a:

ui.RenderTarget()

did not release its corresponding CRenderTarget from CRenderTargetManager.

The manager only supported clearing all RenderTargets at once through Destroy(), which only happened when teleporting:

self.equipmentDialogDict = {}

uiChat.DestroyChatInputSetWindow()

if app.ENABLE_MODEL_RENDER_TARGET:
	renderTarget.Destroy()

So every time a UI widget containing a RenderTarget was recreated, the old model and GPU texture stayed alive until the next teleport.

 

Now imagine a big system that heavily creates and destroys ui.RenderTarget() widgets...

 

Yes, the new system handles the indexing correctly, but the old RenderTargets would still remain inside the manager forever. The keys would keep increasing, along with RAM and VRAM usage.

So I made a very simple fix.

Per-index RenderTarget release

void CRenderTargetManager::ReleaseRenderTarget(int index)
{
    if (m_renderTargets.erase(index) > 0)
    {
        if (static_cast<uint32_t>(index) < m_smallestFree)
            m_smallestFree = index;
    }
}

And the widget now automatically releases its RenderTarget when it is destroyed:

CUiRenderTarget::~CUiRenderTarget()
	{
		if (m_dwIndex != -1)
			CRenderTargetManager::Instance().ReleaseRenderTarget(m_dwIndex);
	}

 

which makes 

m_renderTargets.erase(index)

 remove the RenderTarget from the manager, which also releases the model and GPU texture through the existing smart-pointer based resource ownership.

 

Then:

if (static_cast<uint32_t>(index) < m_smallestFree)
	m_smallestFree = index;

allows the released index to be reused again.

 

Everything happens automatically in the background. You don't have to manually manage or release anything from Python.

This means RenderTargets are now properly cleaned up as part of their normal C++ lifecycle, without requiring an additional Python side pool (LIKE I DID ONCE) or manual cleanup system.

The repository has been updated with this fix.

Enjoy!

  • Love 2

I don’t know — I think.

 

Discord

 

Link to comment
https://metin2.dev/topic/34585-rendertarget-rework/#findComment-176006
Share on other sites

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.