Drawing to texture directly?

Is there any way of painting to a texture directly without storing it in a PNMImage, then painting the PNMImage and reloading it into a texture? That’s what the manual says, but doing so is really slow, I can’t afford to do it every frame, which I need to do.

Yes. You have to do a bit more work, because you have to be cognizant of the internal format of the texture, but you can write directly to the texture’s memory by using texture->modify_ram_image() to get a writable pointer to its image data. You can also use set_ram_image() if you just want to wholesale replace the image, and you can modify the individual mipmaps as well (if you care) with modify/set_ram_mipmap_image().

Note that if you are modifying a texture with mipmapping enabled, you might want to set “driver-generate-mipmaps 1” in your Config.prc file, to avoid Panda having to recompute the mipmaps automatically each time you make a change.

You should consult at least get_x_size(), get_y_size(), get_num_components(), and get_component_type(). You might also find get_format() and get_component_width() useful. Presumably you already know that your texture is an ordinary 2-d texture, so you won’t have to consult get_z_size() or get_texture_type().


Thanks a lot. A couple of questions, though.

  1. I assume that in order to not complicate things I should turn compression off for the textures I want to modify in this manner. Will doing this will suffix?

Should I take any other measure? (I figure that will suffix but I ask in case the libsquish behavior or w/e depends on the hardware.)

  1. Any inconsistency between DX and OpenGL to take into account?

After changing the compression mode, you’ll probably need to call reload().

  1. Ah yes, good call. Compression should be off unless you’re prepared to deal directly with the compressed data. :slight_smile: That call should suffice on the CVS trunk, because it will automatically force a reload; but as rdb points out, earlier versions of Panda3D (including 1.6.2) might require an explicit call to reload().

  2. No, no issues there; the Texture object is at a higher level than GL or DX; the data is massaged as needed when it is uploaded to either backend.


Thanks again, it works great. Also, it seems I don’t have to worry about compression, since modify_ram_image() makes a new image without compression if it’s turned off.

Well, although it’s true it will allow you to store an uncompressed ram image, if you have compression enabled on the texture overall, it will still compress the image when it loads it into graphics memory. If you are modifying the texture frequently, this will mean the driver will be compelled to re-compress it frequently. If you don’t mind the performance hit for this, you can safely leave compression enabled.


Ah, my bad then. I was under the impression that the decompression happened once, when I called modify_ram_image() for the first time, and then it stayed like that, in which case I didn’t mind the penalty (we are talking about 20 ms for a 512x512 texture). But if it’s gonna be doing it every time, then obviously I can’t rely on that.