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

Textures created with ImageTexture.create_from_image are ignoring custom provided mipmaps #66848

Closed
Zylann opened this issue Oct 3, 2022 · 5 comments · Fixed by #74238
Closed
Milestone

Comments

@Zylann
Copy link
Contributor

Zylann commented Oct 3, 2022

Godot version

Godot 4 beta2

System information

Windows 10 64 bits NVIDIA GeForce GTX 1060

Issue description

I created an Image from code, integrating custom mipmaps. The image is successfully created, however when I use it to create an ImageTexture, the resulting texture appears to have no mipmaps.

Steps to reproduce

	var im = Image.new()
	im.create_from_data(size_x, size_y, true, Image.FORMAT_RGB8, pixels_with_mipmaps)
	var tex = ImageTexture.create_from_image(im)
	var sm = ShaderMaterial.new()
	sm.shader = load("res://show_mips.gdshader")
	sm.set_shader_parameter("u_texture", tex)
	_mesh_instance.material_override = sm
shader_type spatial;

uniform sampler2D u_texture;

void fragment() {
	ALBEDO = textureLod(u_texture, UV, fract(TIME) * 10.0).rgb;
}

Minimal reproduction project

ImageMipmaps.zip

In this project, every mip is a different random color. The expected result is a cube flickering with multiple colors. However only the first color shows up.

I'm not sure yet if I've done a mistake somewhere, because the way to create custom mipmaps is not documented, mipmaps aren't shown in editor inspector, and currently the remote inspector doesn't seem to work well enough to show remote textures.

After giving mipmaps to icon.png and testing this:

var tex = ImageTexture.create_from_image(load("res://icon.svg").get_image())

The result appears to have mipmaps. So I'm quite confused what I could have possibly missed.
Maybe Image isn't properly initializing? Maybe mipmaps I provide are completely ignored?

After more tests (adding noise to mip colors) it seems the latter is happening... ImageTexture finds that there are mipmaps, but ignores them and makes its own.

@Zylann Zylann changed the title Textures created with ImageTexture.create_from_image have no mipmaps, when the passed image has mipmaps Textures created with ImageTexture.create_from_image are ignoring custom provided mipmaps Oct 3, 2022
@clayjohn clayjohn added this to the 4.0 milestone Oct 4, 2022
@YuriSizov YuriSizov modified the milestones: 4.0, 4.1 Feb 27, 2023
@bitsawer
Copy link
Member

bitsawer commented Mar 1, 2023

Custom mipmaps should work as I use some in my project. It looks like the error is here:

var im = Image.new()
im.create_from_data(size_x, size_y, true, Image.FORMAT_RGB8, pixels)

That probably should be:

var im = Image.create_from_data(size_x, size_y, true, Image.FORMAT_RGB8, pixels)

as Image.create_from_data() is now a static function. After this, the demo project shows some colors. I was struggling with custom mipmaps too and just created this PR to make handling them a bit easier: #74142.

@Zylann
Copy link
Contributor Author

Zylann commented Mar 1, 2023

Fixing the static call to create_from_data does not fix the issue. Colors are not changing in Godot 4.0 stable.

Updated project:
ImageMipmaps.zip

Note, I included a randomization of the R component to show that mipmaps are cycling, because Godot is generating mipmaps, just not using those I provide.

@bitsawer
Copy link
Member

bitsawer commented Mar 1, 2023

Interesting. I can actually see some very subtle mipmap noise animation in that updated project. But try changing to Compatibility renderer and things start to work somewhat. Maybe a bug somewhere in Vulkan renderer?

Also, changing:

var pixel_size = 3 to var pixel_size = 4 and FORMAT_RGB8 to FORMAT_RGBA8 also seems to fix something and makes things work in Forward+ renderer, too.

@bitsawer
Copy link
Member

bitsawer commented Mar 1, 2023

Could be that some of these image->convert() calls might cause this, as they also regenerate mipmaps from the topmost image and discard custom mipmaps. The fix might be to convert each mipmap individually.

//this format is not mandatory for specification, check if supported first
if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
image->convert(Image::FORMAT_RGBA8);
}
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;

@Zylann
Copy link
Contributor Author

Zylann commented Mar 1, 2023

Interesting. I can actually see some very subtle mipmap noise animation in that updated project

This is

Note, I included a randomization of the R component to show that mipmaps are cycling, because Godot is generating mipmaps, just not using those I provide.

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

Successfully merging a pull request may close this issue.

6 participants