Expose built-in region information
Related to this proposal and issue:
- https://github.com/godotengine/godot-proposals/issues/9355
- https://github.com/godotengine/godot/issues/57401
I'm not sure about the defines (#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)) but it works on both gl_compatibility and mobile rendering mode.
- Bugsquad edit, closes: https://github.com/godotengine/godot-proposals/issues/9355
It may be a good idea to schedule this for a rendering meeting next time.
Hello there, is there any progress to this PR?
Hello, is there any chance that this PR might be included in v4.4?
It would solve a lot of issues with complicated 2D UV-related shaders.
Many thanks!
It won't be in 4.4, no. We're in beta stage and we don't add features in beta stage. I can see this has been open for a while, and I'm sorry for that. We can tentatively take a look at it for 4.5
As a workaround for now, you can try using a canvas group and applying your shader to the canvas group.
I guess the team never revisited this PR after Mickeon's comment; they likely forgot. I will raise this in the Rocket chat channel; as QbieShay mentioned, it is too late for 4.4, but we can make it into the 4.5 dev1.
Edit: Oh, QbieShay is the rendering team member.
It won't be in 4.4, no. We're in beta stage and we don't add features in beta stage. I can see this has been open for a while, and I'm sorry for that. We can tentatively take a look at it for 4.5
Hello @QbieShay, yes, it's been open for a while. I understand for 4.4, it would be nice if it could be looked at for 4.5. maybe I can take a little time (in a few weeks because I can't right now in my personal life) to try to rebase the branch and manage the conflicts to be closer to the current code base that has evolved since maybe. So that it's easier to integrate for 4.5?
Don't worry, before you add any code, I think we should have a chat in the rendering meeting about the feature itself and the API, if we want to expose a function like the one you did, or directly give rect info and full UV info (see #32861).
Once this is discussed, we can come back to the implementation, so that you don't code things until we know exactly in which way we want this feature.
EDIT: right now rendering meetings prioritize release blockers and bugs of 4.4, so this will likely be discussed after 4.4 release.
Okay, that is understandable.
I will try the canvas group method in the meantime.
Thank you all for your time!
Cheers!
Hey, bumping this topic as 4.5 is starting
Hello, will it be in 4.5?💦
Will REGION_RECT will be exposed for textures without region? So the same shader can be the used on Atlas and non-atlas
Great news! Thank you @clayjohn for taking the time to discuss it and take a look. I propose (I would be happy to contribute to godot ) to modify my PR to only add and expose REGION_RECT (composed of the position (xy) and size of the region (zw) coming from draw_data.src_rect right?). Or would you prefer to do it yourself?
Will
REGION_RECTwill be exposed for textures without region? So the same shader can be the used on Atlas and non-atlas
I think expose it in any case is simpler and eleganter, maybe (0,0,1,1) can be a default value for non-atlas textures
@dsmtE if you have the bandwidth to change your PR, that'd be awesome!
Please also ensure the built-in is visible and available in visual shaders
@QbieShay i will try to take some time to update my PR ;) Ok for the visual shaders, If I have any difficulty doing this part I will come back to you, if you have any entry points to suggest to me in the code I would be interested .
I made the changes and exposed only the REGION_RECT uniform (composed of the position and size of the region used), which allows me to manipulate the region as I like in the shader.
I did a test (shader and visualShader) for the demo and it works great!
Can you give me feedback if there's anything I need to change/refine before I can merge?
In the case where the region is not used, I used the inverse texture_pixel_size to set it to the texture size and make the shader work too (it works but I don't know if it's the best way to do it or if there's another way to get the texture size).
How does the documentation work? I leave it to you?
The shader code used in my test :
shader_type canvas_item;
vec2 zoom_in_region(vec2 uv, float zoom_factor, vec2 region_position, vec2 region_size) {
// Convert texture space uv to region
vec2 region_uv = (uv - region_position) / region_size;
// Any local uv transformation : exemple with centered zoom effect
vec2 zoomed_uv = (region_uv-0.5)/zoom_factor+0.5;
// Convert back to texture uv to be sampled properly using the texture(TEXTURE, uv) function
return zoomed_uv * region_size + region_position;
}
void fragment() {
vec2 texture_uv = UV;
float time_factor = ((sin(TIME)+1.0)/2.0);
// Apply zoom to the region part using REGION_RECT
texture_uv = zoom_in_region(texture_uv, 1.0 + 0.4 * time_factor, REGION_RECT.xy, REGION_RECT.zw);
// Shift the region on the x axis using the region size (REGION_RECT.zw) to get the new part of the texture of the same region_size (next sprite sheet frame)
texture_uv.x += REGION_RECT.z;
// Sample the texture using right region UV after local transformation
COLOR = texture(TEXTURE, texture_uv);
}
- Upper left : shader
- Upper right : visual shader
- Bottom : same shader without using region (texture repeat enable to make the shift work)
Hello, I finally test it and fix it on all Rendering methods (Forward, Mobile & Compatibility) and it work well. Could you review my PR @clayjohn @QbieShay ? Thanks in advance !
Thanks for the review @clayjohn ! Done ! I just rebase my branch on the upstream Master and squash all my commits into one to have a clean history.
Thanks! Congratulations on your first merged contribution! 🎉
Critical enhancement for serious batching / atlas optimization. Thanks. Can this be backported to 3.x please ? cc @lawnjelly
PS: The rationale for my request to backport to 3.x is that batching breaks on shader uniforms. So passing the atlas region rect via uniforms to let the shader do the UV math is a no go (both in Godot 3 and 4). The only way to pass parameters (region rect) to the shader and keep batching is the Color modulate/self_modulate of the atlas sprite, and collect that from MODULATE in the shader. But passing the region rect via Color is consuming most of the 4-byte budget for 2048p atlases, leaving no room for other shader instance params, so no go again. Hence, to me this enhancement solves the problem of having the region rect in the fragment shader and is a critical enabler of batchning with atlases. Without it, atlases and batching don't fly.
Thanks to all for solving this, except that our project is Godot 3, but the good news is that it looks like backporting this to GLES2/GLES3 for Godot 3 it totally doable without much effort. cc @lawnjelly
Thanks to all for solving this, except that our project is Godot 3, but the good news is that it looks like backporting this to GLES2/GLES3 for Godot 3 it totally doable without much effort.
Unfortunately I suspect this wouldn't be trivial to add to 3.x batching. Adding new parameters to be passed in the FVF is most definitely not trivial (this is why it is extremely limited at present). It has to be done so as not to slow down existing paths, then be extensively checked for regressions etc.
I have no plans currently to look at this (it would require significant user demand to be worth it at this stage in Godot 3.x, and speaking for myself I have a lot of other areas on the road map before considering anything like this).
Unfortunately I suspect this wouldn't be trivial to add to 3.x batching
Heads up! Fortunately, this has nothing to do with the batching code per se. It is just exposing an existing struct in the shading language cf. Modified Files. However, it has big implications for not breaking atlas batching, which is the main idea of atlases after all. Without exposing this REGION_RECT in the shading language, atlas sprites with custom shaders cannot be batched, as explained previously.
Fair enough on the bag of load side of things... just to clarify that it's definitely not what you're thinking it is.
@oeleo1 in 3.x we often bake in the vertex positions on the CPU, so the region rect information is not necessarily always available. In 4.x the region information is always available because it is never baked directly into the vertex data and is always extracted in the shader
in 3.x we often bake in the vertex positions on the CPU, so the region rect information is not necessarily always available.
Yes, I got that after the fact. Exposing the rect in 3.x is doable but quite tricky indeed.
never-too-late-to-meet-Ignorance-ly y'rs