godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.48k stars 21.26k forks source link

Viewport Texture generate mipmaps ignored #23417

Open szamq opened 6 years ago

szamq commented 6 years ago

Note: This issue has been confirmed several times already. No need to confirm it further.


Not sure if that's expected behavior but Im using the viewport texture on sprite and I tried to use textureLod(...) so I could get blurry version of that and it doesn't work. Setting flags in editor doesn't help either.

Any workarounds to force generating Lods from Viewport Texture? something like in SCREEN_TEXTURE that has Lods

bojidar-bg commented 6 years ago

Which Godot version and (if 3.1) renderer?

szamq commented 6 years ago

it's 3.1 and gles3 edit: it works on gles2

BastiaanOlij commented 6 years ago

Imho this would be expected. The viewport is a render buffer to which you render an output. You can't just add mipmaps to it without breaking the render buffer. I could be wrong though :)

A work around would be to extract the image data to create a new image and add mipmaps to that. Something like:

var source_image = $viewport.get_texture().$get_data()
var copied_image = Image().copy_from(source_image)
copied_image.generate_mipmap()
var new_texture = ImageTexture.create_from_image(copied_image)

there are probably typos in the above but hopefully it'll point you into the right direction

Ovnuniarchos commented 5 years ago

Confirmed in 953cd03ea6ee9fd6d0d3fde9658777cc4020d0a7. It still doesn't generate mipmaps.

mikeleeman commented 5 years ago

I'm trying to get mipmaps to work on a viewport texture as well, I'm rendering to a large Image and scaling it down, but there is the usual pixel artefacts due to nearest neighbour.

Would be nice if there's a way to generate mipmaps without creating an Image and reading it's texture every frame. (edit: actually not sure if this works, haven't tested it)

Maujoe commented 5 years ago

A work around would be to extract the image data to create a new image and add mipmaps to that. Something like:

var source_image = $viewport.get_texture().$get_data()
var copied_image = Image().copy_from(source_image)
copied_image.generate_mipmap()
var new_texture = ImageTexture.create_from_image(copied_image)

there are probably typos in the above but hopefully it'll point you into the right direction

It seems to be enough to create an Image texture from the source image:

var new_texture = ImageTexture.new()
new_texture.create_from_image(viewport.get_texture().get_data())

godot_vp_mipmap_comp

But this is not a really a practicable solution for frequent updates because as expected it's super slow even with a small texture and things like update when visible also doesn't work.

Would nice to have a solution/option for that, viewports are useful for many purposes like the procedural ripples above.

clayjohn commented 5 years ago

reduz has said that we won't be adding mipmaps to SCREEN_TEXTURE here: https://github.com/godotengine/godot/pull/26044. I think the same reasoning probably applies to adding mip maps to viewport textures.

sdfgeoff commented 5 years ago

+1 this is needed for many custom post processing effects (if implemented as per the method here: https://docs.godotengine.org/en/3.1/tutorials/viewports/custom_postprocessing.html )

Examples of such effects:

In my mind I'd like to see a "generate_mips" checkbox on the viewport node so we can control if they are generated or not. I'd also like to see the option to sample viewport textures with something other than GL_NEAREST

DoctorWhoof commented 5 years ago

Just ran into this. Using mipmaps for a quick and dirty glow effect that runs super fast on crappy old laptops (unlike the built-in glow, which drops my frame rate to single digits when in full screen).

Let me add a little wrinkle to it: clicking the "Mipmaps" checkbox on and off causes it to work, but only in GLES2 and in the editor (3.1.1, macOS)... it's still broken when I launch the game.

(Took me forever to find out why the exported game looked different than the editor!)

DoctorWhoof commented 5 years ago

By the way, the related bugs seem to imply that viewport mipmaps work in GLES 3, but not 2. That's not the case, I can't get them to work consistently either way (GLES 2 works in the editor, but not standalone. GLES 3 doesn't work either way).

I don't care much if in the end it doesn't work in GLES2, but I feel it should work as expected for GLES3.

Thanks!

KoBeWi commented 4 years ago

Can anyone still reproduce this bug in Godot 3.2.3 or any later release?

If yes, please ensure that an up-to-date Minimal Reproduction Project (MRP) is included in this report (a MRP is a zipped Godot project with the minimal elements necessary to reliably trigger the bug). You can upload ZIP files in an issue comment with a drag and drop.

vitorbalbio commented 4 years ago

@KoBeWi I can confirm the bug persists in 3.2.3. I'm overcoming it by reading the screen texture instead of using the viewport texture but it would be totally unnecessary and probably will not fix every case of use. It's very important to many post process effects and FX. Thanks for the interest in fix it.

Here's a reproductible project. GodotBug.zip

Calinou commented 4 years ago

This most likely can't be fixed in the 3.2 branch, only in master with some kind of fast filtering implementation (as is already used in sky shaders): https://github.com/godotengine/godot/issues/23417#issuecomment-471230124

vitorbalbio commented 4 years ago

This most likely can't be fixed in the 3.2 branch, only in master with some kind of fast filtering implementation (as is already used in sky shaders): #23417 (comment)

Hi @Calinou. The pointed problem by this comment (https://github.com/godotengine/godot/pull/26044) is that SCREEN_TEXTURE don't have mipmaps in OpenGL2.0 (Works in OpenGL3.0 as you can check in the demo i posted above and i'm using it as a workaround)

This thread is about access mipmaps in viewport textures in OpenGL 3.0. How those are related?

amonroejj commented 3 years ago

A work around would be to extract the image data to create a new image and add mipmaps to that.

This doesn't work in func _ready() (although it does work when called in a button handler). I verified this by saving the extracted Image to a png and viewing it in Gimp. Is it that the viewport gets added to the tree (and _ready() is called) before the Viewport is rendered? If that's the case, how would you go about solving this chicken and egg problem?

Calinou commented 3 years ago

This doesn't work in func _ready() (although it does work when called in a button handler). I verified this by saving the extracted Image to a png and viewing it in Gimp.

It will probably work if you defer this by one frame using call_deferred() or yield(get_tree(), "idle_frame") (then placing your code after that yield()).

It's possible that you may even need to defer this by two frames by calling yield() twice in succession.

amonroejj commented 3 years ago

It's possible that you may even need to defer this by two frames by calling yield() twice in succession.

I had to wait two frames, yeah.

func _ready():
    #call_deferred("tex_stuff")         # didn't work
    yield(get_tree(), "idle_frame")     # didn't work with a single yield
    yield(get_tree(), "idle_frame")     # double yield worked
    tex_stuff()
Leakbang commented 3 years ago

This is still an issue in Godot 3.3.4.

RPicster commented 2 years ago

Not wanting to beat on dead horses... but this is still a very annoying issue for all kind of vfx.

Calinou commented 2 years ago

@RPicster Please don't bump issues without contributing significant new information. Use the :+1: reaction button on the first post instead.

Anixias commented 2 months ago

Sorry to bump such an old issue, but even today in v4.3.stable.mono.official [77dcf97d8] I'm still encountering this issue. Trying to use a ViewportTexture on a Sprite3D node and I can't seem to get mipmaps no matter what settings I modify. The above workaround is way too slow for practical use.

Calinou commented 3 weeks ago

Something like https://github.com/godotengine/godot-proposals/issues/10096 should improve the appearance of ViewportTextures without mipmaps significantly, especially at intermediate distances. Proper mipmaps are still preferable at far distances still.

Using TAA or FSR2 will also improve the appearance of textures without mipmaps (with or without texture supersampling), as the temporal nature of these antialiasing algorithms works out nicely here.

This can already be implemented with a custom shader by converting a BaseMaterial3D to a ShaderMaterial and using the RGSS sampling code from https://github.com/Calinou/godot/commit/basematerial3d-add-rgss.