I’m new at GD. I need to be in c++ godot object (module?) and I’ll be talking to a privately instantiated object, which will hand me CPU-RAM based video bits (RGB) per frame. I need to copy those bits, per frame, to a Texture2D. That Texture2D should be on a material/shader that is being used to render a mesh in Godot. Eventually this “module” thing will hand me a GPU-based texture, and I’ll want to do a GPU-GPU BitBlt. So, in my module thing, I need to be passed a Texture2D (on the correct thread) and I need to get at the native DX11/12 texture pointer it’s really using. Is this even possible?!
grunt. I need more specific answers. Probably from somebody who’s literally done this. Not “anything is possible” answers, because I’m sure I could spend a year and figure it out, but I’m looking for some quick info from somebody who’s done this or can point to a sample or demo or tutorial.
I’ll be more narrowed down in my question focus: I’m in a C++ Module I wrote myself. I’ve passed in a Texture2D to fill. In my function that’s been called with a Ref, I want to set that texture’s bits with bits of my own choosing. Nevermind what I said above, I just want to fill the texture with some pattern of my own choosing. I’d ideally like to lock the texture for writing, copy a bunch of bits into it, unlock it, and return.
I’m in the function now, in C++, and I’m thinking I need to get the Image from the texture, then fill the image, but the abstraction confuses me. Should I really do it through the image? Why isn’t there a way to just call Texture2D’s imaginary method, SetBits( byte* pArray ) ? Has this really not been needed in Godot yet?
like this:
void rdCoreSrc::FillTextureWithStuff(Ref<Texture2D> tex)
{
Ref<Image> i = tex->get_image();
int width = i->get_width();
int height = i->get_height();
char* pBits = new char[width*height*4];
i->set_data( width, height, false, Image::Format::FORMAT_RGBA8, pBits);
delete [] pBits;
}
whatever it takes to fill a texture2d with my ARGB bits, is fine. I need to do it very fast. 4K images @ 60FPS, at least. Each frame, the CPU bits differ, they are not the same. so, each frame, I need to stuff those bits into the Texture2D’s GPU RAM bits… How to do this eludes me. Even from a shader POV, how do I pass a shader arrays that big and have them set the texture bits from it?
I’m sure somebody out there has had to do this… I can’t be the only one. Not being able to put live video into a texture at runtime sort of implies Godot is a toy runtime/editor. Don’t mean to be insulting, but this is a pretty common feature, animating a texture.
I see a lot of people out there wanting to do the same thing, but their PR’s have been stuck for years without getting in. What’s up with that?
Okay we are getting a bit farther. I knew about get_rid(), but I didn’t know about RenderingServer.texture_get_native_handle(). I’m sure that’s going to come in handy for step 2.
Q2: you referenced filling an image with a certain color. Close, but not quite. I need to fill the entire image with bits I specify. From a buffer pointer in native mode. I guess the only way to do it is via a PackedByteArray? Yeah, I can live with that if true. My question is, once I have the packed byte array and call image->set_data(), how do I get the texture to update itself?
what’s wrong with this code?
void rdCoreSrc::FillTextureWithStuff(Ref<Texture2D> tex)
{
Ref<Image> i = tex->get_image();
int width = i->get_width();
int height = i->get_height();
PackedByteArray image_data;
image_data.resize(width*height*sizeof(uint32_t));
uint8_t* image_data_ptr = image_data.ptrw();
uint32_t* image_data_ptr_w = reinterpret_cast<uint32_t*>(image_data_ptr);
for( int x = 0 ; x < width * height ; x++)
{
*image_data_ptr_w++ = x;
}
i->set_data( width, height, false, Image::Format::FORMAT_RGBA8, image_data);
// how to update the texture? Would have thought updating the image we got
// from the texture, would do the trick?
print_line("FillTexture!");
}
If you want to share a texture created from an external program then you need to use RenderingServer.texture_create_from_native_handle()
Another option which will give you more control is to use a Texture2DRD and get its RID by using the main RenderingDevice with RenderingServer.get_rendering_device() and creating a view to that texture with RenderingDevice.texture_create_from_extension().
In both cases you won’t be able to modify its data from within Godot and it’s up to your other program to do that.
Yes, now we’re talking. I don’t want to update it from Godot, I need to update it from my c++ module. I’m hoping in my C++ Godot Module, I can instantiate my own D3D12 device, and texture/surface. Use THAT to stuff bits into, and use Godot to simply call my module and have it update itself. I want Godot to use that texture to draw onto a mesh. This will be “screen bits” scraped from my desktop.
Figured out I can’t pass in the texture and have it update. Couldn’t figure that out. But I can pass in an Image and have that update. Then in GD, call texture.update(image). I don’t know how slow this is, haven’t profiled it, I assume it’s terrible. But it’s a start.
That was just an example showcasing how to update a texture using an Image. For this you need to use a ImageTexture or interact with the RenderingServer directly to create/update/free the texture. You already found out how to update the whole image data with Image.set_data()
You can’t update the Texture directly. A Texture is basically a pointer to a GPU object internally. The Image is the data.
It’s like updating a texture moving the data from CPU to GPU. It’ll be a bit faster than creating a new texture each time though.
But all this won’t matter if your idea is to have an external texture you want to share with Godot. Then the lifetime of the external texture and its updates are up to you. In Godot you’ll need to create the resource id (RID) with RenderingServer.texture_create_from_native_handle() or the other method I posted above. I’m not sure if the update will be reflected in Godot once you update the texture externally or not.