Well, this is kind of complex, so I will try to explain it the best way I can.
I want to create a bitmap that could then be used inside other scripts. Since the bitmap is a bit big (2048px x 1535px), the fastest way to create it is through a shader.
I already created a TextureRect , set its Texture to ExternalTexture, created a ShaderMaterial for it, and created a new shader, that I coded to create some sort of image.
Now, I would like to be able to access the generated bitmap from within a GDScript.
By "access", I mean, be able to access the pixel values, and even be able to generate a new bitmap, by changing the Uniform variables that are defined in the Shader.
Is this possible?
In a nutshell:
1) create a bitmap using a Shader (since it is fast) that can be accessed from a GDScript?
2) from within a GCScript, force the Shader to recreate a new bitmap with new parameters?
I think you will need to have the TextureRect as a child node of a Viewport with the same size as the bitmap. Then you can get a ViewportTexture and access the pixels from there.
You might be able to get the pixels from the TextureRect texture directly, but I am not sure. I know the Viewport solution should work.
To get the pixels themselves, you’ll need to lock the image and then call the get_pixel function: https://godotengine.org/qa/77048/getting-texture-pixel-data
Edit: for telling the script to make a new texture, you are going to want to define some shader uniforms that are the parameters for the shader. Then you can set those uniforms via GDScript: https://godotengine.org/qa/57814/how-to-modify-a-shaders-parameters-in-runtime
Yes, the Viewport Texture would be the way to go. It's based on pointers, so you don't have to "get" the data. It should be in some sort of shared memory, so once it is connected, they are the same object.
Thank you for the quick answer.
I will try it out as soon as possible. My wife got sick today and I was busy all day and I will get back to my job tomorrow. But I will try your solution as soon as possible.
Ok, got a little time before going to bed.
I tried:
var vpimg = get_node("Viewport").get_texture().get_data()
but got the error:
(Node not found: "Viewport" (relative to "/root/EditorNode/@@592/@@593/@@601/@@603/@@607/@@611/@@612/@@613/@@629/@@630/@@639/@@640/@@6275/@@6109/@@6110/@@6111/@@6112/@@6113/Spatial/MeshInstance_GDScript").)
res://Global_Scripts/Globe2.gd:53 - Attempt to call function 'get_texture' in base 'null instance' on a null instance.
The Viewport node exists and it is called "Viewport". I even tried changing its name to something else (adjusting the get_node parameter, of course), but got the same error.
Is this in a plug-in or tool script? You have limited access to the rest of the game in editor scripts.
Made it work by making the Viewport a child of the object that has the GDScript.
But now I can't seem to force the shader to update.
I tried to change one of its parameters, named "s_seed" with:
var mat = get_node("Viewport/TextureRect")
mat.material.set_shader_param("s_seed",sh_seed)
but nothing happens.
The function get_node() is relative. So if you call:
get_node("Object")
That implies that the node with name "Object" is a direct child of the node which the script is attached.
You can also go one layer up (a sibling of the parent) with:
get_node("../Object")
Or use absolute paths:
get_node("/root/Game/Object")
When the node "Game" is your root object and "Object" is a direct child of "Game"
In your last code, I think mat is a copy of the material, not the original reference. You can do this:
get_node("Viewport/TextureRect").material.set_shader_param("s_seed", sh_seed)
Thank you so much for the fast replay.
Indeed, I can change the shader parameters now.
But, the Viewport is not updated as I change the shader parameters in code.
I notice that, if I change those parameters, the image created by the shaders does update only when I click the Viewport.
Is there any way to force a recalculation of the Viewport image, in code?
After much fiddling, turning the "Update Mode" to Always did the trick :-)
© 2022 - 2024 — McMap. All rights reserved.