modifying a texture at run time

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Wavesonics

I’m working on a little prototype, and I need to edit the Pixel data at run time.

My plan is to use GD native, and have a class that contains a reference to an image. Then I can use the images pixel data and modify it how I need.

I’ve done this before using SFML, and it was a little more straightforward, maybe because I knew the library better, but I could see how to get it to reupload to the GPU after I changed it.

Does anyone have any hints or tips on how to accomplish this using Godot?

Basically textures/images can be modified with the Image class:

Image — Godot Engine (3.1) documentation in English

It contains simple get/set pixel methods but has also a create_from_data method which can receive various formats.

My experience with the image class is very limited though (and I did GDScript only).

wombatstampede | 2019-10-11 07:45

:bust_in_silhouette: Reply From: Zylann

To be modifiable at runtime from a script, a texture needs to be an ImageTexture, because you need pixel data in RAM to be able to edit it using the CPU. If it’s not, it would need to be converted and re-assigned to whatever uses it.

If you generate such textures from scratch, you may keep an Image in a variable and use ImageTexture to render it. Then editing would be something like this:

var _image : Image
var _texture : ImageTexture

func edit_pixels():
	
	_image.lock()

	_image.set_pixel(x, y, color)
	...

	_image.unlock()

	# If it's the first time, or if you want to upload the whole image
	_texture.create_from_image(_image, Texture.FLAGS_FILTER | Texture.FLAGS_REPEAT)

	# If the texture already has data,
	# you can upload pixels partially by providing the sub-rectangle you edited
	VisualServer.texture_set_data_partial(_texture.get_rid(), _image, min_x, min_y, size_x, size_y, dst_x, dst_y, 0, 0)

Note: there is another way to “edit” textures at runtime, using the GPU instead, is by directly rendering onto them with Viewport (a bit like SFML’s RenderTexture). Viewports can also be treated as a texture if you get_texture() from them, so whatever you draw inside will be reflected on nodes you used their texture from.

Perfect! This is exactly what I was looking for, thanks! I’m prototyping some pixel destruction similar to worms, so the partial upload will be a huge help.

Wavesonics | 2019-10-12 18:06