godot icon indicating copy to clipboard operation
godot copied to clipboard

Expose built-in region information

Open dsmtE opened this issue 1 year ago • 1 comments

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

dsmtE avatar Apr 09 '24 15:04 dsmtE

It may be a good idea to schedule this for a rendering meeting next time.

Mickeon avatar Jul 05 '24 23:07 Mickeon

Hello there, is there any progress to this PR?

Delsin-Yu avatar Jan 01 '25 17:01 Delsin-Yu

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!

jtcaya avatar Feb 06 '25 17:02 jtcaya

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

QbieShay avatar Feb 07 '25 10:02 QbieShay

As a workaround for now, you can try using a canvas group and applying your shader to the canvas group.

QbieShay avatar Feb 07 '25 10:02 QbieShay

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.

Delsin-Yu avatar Feb 07 '25 10:02 Delsin-Yu

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?

dsmtE avatar Feb 07 '25 11:02 dsmtE

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.

QbieShay avatar Feb 07 '25 12:02 QbieShay

Okay, that is understandable.

I will try the canvas group method in the meantime.

Thank you all for your time!

Cheers!

jtcaya avatar Feb 08 '25 14:02 jtcaya

Hey, bumping this topic as 4.5 is starting

lucastucious avatar Mar 21 '25 12:03 lucastucious

Hello, will it be in 4.5?💦

KirisameY avatar Mar 29 '25 09:03 KirisameY

Will REGION_RECT will be exposed for textures without region? So the same shader can be the used on Atlas and non-atlas

lucastucious avatar Apr 01 '25 16:04 lucastucious

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?

dsmtE avatar Apr 01 '25 17:04 dsmtE

Will REGION_RECT will 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

KirisameY avatar Apr 02 '25 02:04 KirisameY

@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 avatar Apr 02 '25 14:04 QbieShay

@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 .

dsmtE avatar Apr 03 '25 09:04 dsmtE

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);
}

godotRegionPR

  • Upper left : shader
  • Upper right : visual shader
  • Bottom : same shader without using region (texture repeat enable to make the shift work)

dsmtE avatar Apr 03 '25 15:04 dsmtE

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 !

dsmtE avatar Apr 08 '25 18:04 dsmtE

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.

dsmtE avatar Apr 30 '25 09:04 dsmtE

Thanks! Congratulations on your first merged contribution! 🎉

Repiteo avatar Apr 30 '25 14:04 Repiteo

Critical enhancement for serious batching / atlas optimization. Thanks. Can this be backported to 3.x please ? cc @lawnjelly

oeleo1 avatar Aug 27 '25 11:08 oeleo1

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

oeleo1 avatar Aug 28 '25 08:08 oeleo1

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).

lawnjelly avatar Aug 28 '25 09:08 lawnjelly

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 avatar Aug 28 '25 10:08 oeleo1

@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

clayjohn avatar Sep 01 '25 19:09 clayjohn

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

oeleo1 avatar Sep 01 '25 20:09 oeleo1