Creating a custom, procedural Texture2D resource

Godot Version

4.21

Question

Hello!

I’m trying to make a custom resource that extends the Texture2D/ImageTexture resource that creates a texture from bits and pieces of a given image.

So if for example I have this wood board texture:

wood_planks

And I want to define how many individual boards this image contains (like a spritesheet) and then the resource dynamically updates to fill the bounds with the correct number of boards.

I already made a working version of this system using just the _draw() function of a ColorRect control node, however Control nodes interact with z-sort in a way that makes this solution cumbersome if not flat out broken.

Now I’m trying to use a Sprite2D node that z-sorts correctly by allowing me to set the z-sort origin, however using the _draw() function feels a bit excessive? I feel like there is a better solution to this problem, either a shader or a custom texture resource.

My problem is that I can’t seem to get my custom Texture2D resource to display anything at all! Here’s my current code that (the way I see it), should pretty much do the exact same thing as a regular old CompressedImageTexture resource:

class_name TiledTexture extends Texture2D

@export var texture: Texture2D:
	set(value):
		texture = value
		emit_changed()

func _get_height():
	texture.get_height()

func _get_width():
	texture.get_width()
	
func _get_rid():
	texture.get_rid()
	
func _has_alpha():
	texture.has_alpha()
	
func _is_pixel_opaque(x, y):
	texture.is_pixel_opaque(x, y)
	
func _get_size():
	texture.get_size()

func _draw(to_canvas_item, pos, modulate, transpose):
	if !texture:
		return
		
	texture.draw(to_canvas_item, pos, modulate, transpose)

func _draw_rect(to_canvas_item, rect, tile, modulate, transpose):
	if !texture:
		return
		
	texture.draw_rect(to_canvas_item, rect, tile, modulate, transpose)

func _draw_rect_region(to_canvas_item, rect, src_rect, modulate, transpose, clip_uv):
	if !texture:
		return
		
	texture.draw_rect_region(to_canvas_item, rect, src_rect, modulate, transpose, clip_uv)

If the best solution for this problem turns out to ultimately be _draw() calls or some sort of shader, then that’s perfectly fine by me, possibly even preferred! However I’m already so far down this rabbit hole of creating a custom Texture2D resource and I kind of want to get this custom resource to render something just for the sake of learning something new that may prove useful in the future.

If anybody has some knowledge to share I’m all ears!

Thank you in advance!

When you say Texture Resource, are you talking about saving this created image/texture in the project files, or just creating one at runtime and putting it in a sprite in the scene?

1 Like

As far as I’m aware, it’s not possible to extend Texture2D that way as the engine uses the RID internally and you can’t create a RID yourself. Only a few methods in the RenderingServer server can create RID for textures but those textures have to have an Image resource.

Use the CanvasItem._draw() method instead. It’s what every CanvasItem node (Control and Node2D nodes) use internally.

1 Like

Thank you so much for the discussion!

@roc4u1000 I meant the latter!

@mrcdk Aha, ok, good to know! In that case, I’ll just use the _draw() method instead:) It already worked well enough with ColorRect and I’m sure it’ll be the same with Sprite2D as well.