Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AtlasTextures work with SpatialMaterial/3D meshes #1708

Open
Shadowblitz16 opened this issue Oct 22, 2020 · 12 comments
Open

Make AtlasTextures work with SpatialMaterial/3D meshes #1708

Shadowblitz16 opened this issue Oct 22, 2020 · 12 comments

Comments

@Shadowblitz16
Copy link

Describe the project you are working on:
3d rouge like

Describe the problem or limitation you are having in your project:
I have a image which I want to swap out later for dungeon variation.
however it seems like texture atlas doesn't work with albedo in spatial shaders.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
I suggest all types of texture work for 3d objects.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
image

If this enhancement will not be used often, can it be worked around with a few lines of script?:
I guarantee this would be used and while it can be worked around with shaders or uvs its not ideal and seems kinda like a bug.

Is there a reason why this should be core and not an add-on in the asset library?:
normal textures work why can't other textures?

@Calinou Calinou changed the title Please make all types of textures work with 3d meshes Make AtlasTextures work with SpatialMaterial/3D meshes Oct 22, 2020
@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Oct 23, 2020

godotengine/godot#25895

@SIsilicon
Copy link

Why is this closed?

@Shadowblitz16
Copy link
Author

Shadowblitz16 commented Oct 23, 2020

it seems to be the same issue as the sampler2D.
should I reopen it?

@SIsilicon
Copy link

Well I mean, you are proposing something to be changed/added in Godot.
And I personally would love this feature to be a thing as well. :)

@Shadowblitz16
Copy link
Author

ok

@Shadowblitz16 Shadowblitz16 reopened this Oct 23, 2020
@Shadowblitz16
Copy link
Author

Note something would need to be done about texture repeat for texture atlases

@SIsilicon
Copy link

SIsilicon commented Oct 24, 2020

I have an idea of how it could work.
An intermediate viewport texture can be used to render that atlas texture to. This would solve the problems of texture repeat and use in shaders.
However, since it uses a viewport, it'd probably be best that it comes as an option. Like a property called use_in_shaders.

@lewiji
Copy link

lewiji commented Sep 23, 2021

I would really like this, though not necessarily for the performance benefits of using AtlasTextures in 2D (if @SIsilicon is right and the only way is to first render to a viewport, that sounds like it may even reduce performance?), but actually just as a workflow QOL thing. It would just be nice to be able to use regions for SpatialMaterials. I do a fair bit of work doing pixel art textures in 3D, and constantly having to split up spritesheets and tileset images into hundreds or thousands of tiny pngs to use in 3D is a bit tiresome and hard to manage sometimes, not to mention sometimes I may only want a section of that tiny png as a surface's material.

Obviously this is something that's better suited to something like Blender or GIMP, but it'd be real nice to have an option to do it in Godot just for speed and time efficiency. To have to boot up those programs, locate my file in the filesystem, create slices and selections, UV maps, export into formats, etc, vs just applying the texture as usual in the material/shader and selecting a region, done.

Sprite3D allows for the use of a single region in its texture, something like that would be really nice in regular SpatialMaterials, I'm not sure on the implementation details/differences between the two or how applicable that code would be.

Edit: In the past where I have nice neat sprites arranged in a grid in a single image, I've created a shader with exact UVs that can take the "custom data" from a MultiMesh to create a 3D "texture atlas" style efficient mesh renderer with a single uniform int for the frame number. It can work great when setup correctly, but it's a bit of a pain to get right and still you're limited to a fixed size rather than just selecting an arbitrary section of a texture to use.

Edit2: having slept on it, I have an idea to make an add-on that could use MultiMeshInstance to make an "easy" primitive builder for spritesheets (to quickly build walls and floors in a "ProBuilder" or "Sprytile" kind of style using regions of a spritesheet) using the shader above. I'm going to prototype it and see what happens, and maybe it'll shed some light on a good implementation for the engine, but either way I will publish it to GitHub sooner or later. Unfortunately it'll be Mono C# only at first as I don't know GDScript all that well.

@itsTheFae
Copy link

itsTheFae commented Apr 12, 2023

I recently ran into this myself while playing about with 2D scenes, in Godot 4.0.2. I was expecting the AtlasTexture to submit the configured region and not the whole atlas image to the Sampler2D shader uniform. The editor shows the selected region, so I find it a tad counter-intuitive that we need to set up extra uniforms to do the region selection in the shader manually.

I think having a toggle option for whether or not AtlasTexture should send the full atlas or just it's configured region to the shader Sampler uniform would be a good addition. It would not exclude existing use-cases if the default was to just send the full atlas while reducing the amount of fiddling to get the shader to sample the same texture space that Sprite2D and other nodes are getting from the atlas resource. I'd like to think that sending a cropped region would be more efficient than sending the whole atlas and cropping in-shader.

Based on the issue name, I'm conflicted whether or not to post here or open a new proposal. While searching through related issues, much of them seem to link back here directly or indirectly. So hopefully this isn't off-topic or against the rules, and provides more data/justification on the scope of the proposal...

@tavurth
Copy link

tavurth commented May 17, 2023

Oh damn, I was wondering why this was not working 😢

I can thankfully play around with the UV values for my grid map version but this is really strange to see.

Anyone working on this?

@tavurth
Copy link

tavurth commented May 24, 2023

The way I fixed this was just creating meshes in a GridMap using a UV on a StandardMaterial3D.

So you take any mesh, and want to apply an Atlas texture to it in a single plane (easier).

You can send in a StandardMaterial3D with the correct UV coordinates:

func make_atlas_materials(
	mesh: Mesh,
	uv_position: Vector2,
	uv_scale: Vector2,
) -> Mesh:
	var to_set: StandardMaterial3D
	var to_return := mesh.duplicate(true)

	for idx in range(to_return.get_surface_count()):
		to_set = to_return.surface_get_material(idx).duplicate(true)

		to_set.albedo_texture = self.get_texture()
		to_set.set_cull_mode(BaseMaterial3D.CullMode.CULL_DISABLED)
		to_set.set_uv1_scale(Vector3(uv_scale.x, uv_scale.y, 1.0))
		to_set.set_uv1_offset(Vector3(uv_position.x, uv_position.y, 0.0))
		
		to_return.surface_set_material(idx, to_set)

	return to_return

@AThousandShips

This comment was marked as outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants