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

Describe ImageTexture, Image creation and usage #42412

Merged
merged 1 commit into from
Nov 17, 2020
Merged

Describe ImageTexture, Image creation and usage #42412

merged 1 commit into from
Nov 17, 2020

Conversation

Xrayez
Copy link
Contributor

@Xrayez Xrayez commented Sep 29, 2020

Closes #20972.
Helps #41106, #42346, #38112, #23148, #16678, #17848.

Having this documented, I'd prefer #39396 or #42653 to get merged, as it's mostly documentation issue by now, see #24222 for instance.

Linking to the Importing images docs as well.

@Xrayez Xrayez requested a review from a team as a code owner September 29, 2020 14:52
@Calinou Calinou added cherrypick:3.x Considered for cherry-picking into a future 3.x release documentation enhancement labels Sep 29, 2020
@Calinou Calinou added this to the 4.0 milestone Sep 29, 2020
[b]Note:[/b] The maximum image size is 16384×16384 pixels due to graphics hardware limitations. Larger images will fail to import.
Native image datatype. Contains image data which can be converted to an [ImageTexture] and provides commonly used [i]image processing[/i] methods. The maximum width and height for an [Image] are [constant MAX_WIDTH] and [constant MAX_HEIGHT].
An [Image] cannot be assigned to a [code]texture[/code] property of an object directly (such as [Sprite2D]), and has to be converted manually to an [ImageTexture] first.
[b]Note:[/b] The maximum image size is 16384×16384 pixels due to graphics hardware limitations. Larger images may fail to import.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true in master now, as it depends on MAX_PIXELS constant, but true for 3.2, will have to be updated (need to expose MAX_PIXELS constant first). The limits are still legit for textures.

texture.create_from_image(image)
$Sprite.texture = texture
[/codeblock]
[b]Warning:[/b] Always prefer to load imported textures over loading them from within the filesystem dynamically, as it may not work in exported projects:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this warning multiple times from many sources, but still don't understand the why's of it. I also continue to not understand how to know when an texture is "imported" properly v.s. just present. There is also an implication that "imported" objects are inside the project folder before the game is exported but I've not seen this clearly defined. Lastly what should someone do if they truly intend for an image/texture to be loaded from user://?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory this should be documented at Import process page describing the reasons why assets like images have to be imported in Godot.

By default, any foreign file format is not recognized by Godot, so it will be ignored and not visible throughout the "FileSystem" dock (which looks into res:// path, which happens to be a project's root on your filesystem, or the contents of game.pck when you export a project).

On the high-level, files like *.png are recognized by Godot, but they have to be made compatible with the existing datatypes first, like Image or Texture. Therefore, those foreign files have to be converted first, aka imported as Resources. Those imported resources get saved into the .import folder which is hidden in Godot's UI.

The problem is that there may be different ways to convert such files, so the "Import" dock gives you the ability to configure the default import procedure for each file, as described in #20972 (comment).

Now, if you want to actually interact with those imported resources, loading them by the "original path" is enough:

var texture = load("res://icon.png")

What happens is that the ResourceLoader takes the original path ("res://icon.png"), looks whether such a file was previously imported (looks into .import directory), and retrieves the resource for you, so it doesn't really load the original file anymore.

Now, the problem with such approach is that this is limited to the project's virtual resource filesystem ("res://"). If you need to load any external files outside of "res://" in exported projects, this will fail, because all of the game contents get packed into game.pck. Methods like Image.load() are not even aware of this virtual filesystem in Godot and rely on the typical OS-specific filesystem methods for loading data (using the internal FileAccess class, aka File in GDScript), and not GDScript's load(). The reason it works in the editor is because those image files are still there on your filesystem. In theory, you can also disable automatic re-import, delete those original files outside of the editor, and still able to run your game. 🙂

Lastly what should someone do if they truly intend for an image/texture to be loaded from user://?

For best results, you have to replicate the same import process manually at run-time, because most of the import methods are only available in the editor. Yes, I know, this can be a big limitation in your project if your game takes advantage of user-generated content. And the most practical and feasible way to "import" textures at run-time is by loading an Image and creating an ImageTexture from that. 🙂

The procedure would be the same as in the first snippet in this PR, but use "user://" instead. You have to clearly define what content would be able to be loaded externally and design your game architecture accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks this was very helpful

@Xrayez
Copy link
Contributor Author

Xrayez commented Sep 30, 2020

Updated documentation to provide some rationale as to why textures are better to be loaded with load rather than Image.load() in most cases, and suggest that Image.load() is only safe to use in the context of the editor and for the use case of loading external images (user://) in exported projects.

@Xrayez
Copy link
Contributor Author

Xrayez commented Sep 30, 2020

Updated upon discussion in #42346 (comment).

@Xrayez
Copy link
Contributor Author

Xrayez commented Oct 2, 2020

Updated upon #42346 (comment). Added error messages for ImageTexture.update() function and create_from_image().

ImageTexture.set_data() in 3.2 is ImageTexture.update() in 4.0.

@xarses
Copy link
Contributor

xarses commented Oct 2, 2020

LGTM, the changes resolve the problems I ran into.

@akien-mga akien-mga merged commit c56a071 into godotengine:master Nov 17, 2020
@akien-mga
Copy link
Member

Thanks!

@Xrayez Xrayez deleted the doc-image-texture branch November 17, 2020 15:18
@akien-mga
Copy link
Member

This is not trivial to cherry-pick as the API for textures changed, and this impacts some of the written documentation. Can you make a dedicated PR for 3.2?

@akien-mga akien-mga removed the cherrypick:3.x Considered for cherry-picking into a future 3.x release label Nov 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mono: Image.Load() doesn't recognize res:// outside of editor
4 participants