godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.15k stars 97 forks source link

Add feature to visualize 'mipmap' level changes in a preview mode . . . #2704

Open charlesmlamb opened 3 years ago

charlesmlamb commented 3 years ago

Describe the project you are working on

A Tomb raider game, in a series, of games <3

Describe the problem or limitation you are having in your project

I'd like to visualize mipmap compression factor, in the viewport . . I'm not sure it's already a feature, so far I haven't found it . . It'd help me make smaller textures, for objects far away, without impacting visual quality, so on . .

I'm not sure how it could be done, maybe a green - to - red change, or something, grey-scale would be difficult to compare . . Something like, 'overlay' mode, but where one can see when ' mipmaps ' are changed, on screen . . .

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Well, I want about 512x512 textures, for each 1x1m square . . but, to make larger levels, where some objects will only be seen in the distance, might as well compress the texture, to begin with, to the level, they will be seen in the game, to save texture memory, also over-all download size . . Is this something that can be done, or is there a mode, not sure . . hope it will make game run faster, so the ' higher ' res. images, won't be needed to be loaded, to ' begin ' with, also save file - size . .

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Well, SOME way of visualizing, when a new ' mipmap ' texture LOD is on an object or, surface . . Since some stuff will be in the background, might only need to make 256x256 for each, 1x1m surface, which would be a big help, and help me make massive games, also :O :O . . . Thx <3

If this enhancement will not be used often, can it be worked around with a few lines of script?

I don't know, or if it's some advanced feature, hidden in the engine, some-where . . .

Is there a reason why this should be core and not an add-on in the asset library?

Not sure, I'm also not even sure, if this will help performance . . Right now, I can't see when the mipmaps are loaded, at different resolution, it'd be a simple way of optimizing texture memory, in scenes with things, in the far distance . . .

So, I can see, maybe with mipmap levels having different colors, or so . . 2021-05-09 1813

Maybe some system, where each mipmap level, is shown as a color, on objects, like ' weight painting ' . . . <3

2021-05-09 1815

Thx . . .

ps. Greyscale would be nice, but I think it'd be difficult, to tell . . or, some pattern, maybe checker, for each level :OO . . .

pps. I'm not sure this would actually work, or create graphically problems or, so . . It'd at least allow one to create more optimized textures, for things in the distance, prob. is I have no idea, when the mipmaps are ' swapped ' <3 . . .

Zireael07 commented 3 years ago

Jasper, this is one of your best proposals. Concise and to the point.

Someone managed to code a shader + a custom texture to show mipmap levels in Unity: https://aras-p.info/blog/2011/05/03/a-way-to-visualize-mip-levels/, another unity example: https://forum.unity.com/threads/color-coded-mipmap-levels-shader.256290/

Some other examples of mipmap visualizations: http://www.racer.nl/tutorial/stub_textures.htm (RacerNL, an indie racer game) https://www.geeks3d.com/20100311/tips-mipmap-levels-debugging-with-a-dds-debug-texture/

charlesmlamb commented 3 years ago

Ok, was thinking maybe one could make 'green' for level 1, yellow for level 2, yellow with checker for level 3 . . I didn't know the texture was swapped ' over ' an object, thought it happened for the ' entire ' texture . .

Was thinking, in my game the floor might be level 2, all the time, it's isometric RPG . . like 'Path of Exile' . . Since the player will never see the floor, might as well make lowest mipmap level, maybe 128x128, that way, I can save 8x memory usage, for all floor textures, while maintaining a uniform 512x512 texture size, for each 1x1m surface . . .

2021-05-09 1900

  1. I'm not sure if this will actually, or be meaningful, if there's any gain . .
  2. If it'll only work for objects, at a certain distance, and so only 'optimize' a few objects . .

Was hoping someone here, would know about this . . From my mipmap experiments, it looks like textures are swapped, at as little as 4 - 5 m distance, but can't really see ' when ' :OO :OO Maybe someone here knows, if this is a ' dumb ' idea, I don't know . . . . .

Add: It looks like mipmaps aren't swapped for an ' entire ' object, like suddenly a box is level 3, or so on . . . It looks like, it's some ' fluent ' gradient, which is ' weird ' . . . Was hoping to make some distant objects, may-be a skyscraper, where only sees level 2, or so . . It'd help me have much bigger objects, in the distance, and ' know ' which mipmap was the correct, for an object, to maintain an ' effective ' look, of 512x512, per 1x1m surface . . Thx . . .

Maybe this is dumb and, won't effect performance or, so . . .

From link, above : 2021-05-09 1907

I'd think any surface, say a plane, would either have level 1 or, level 2, not a gradient :OO look like, it requires much more performance, to make those ' blends ', well, I'm noob, not sure this isn't in the engine, in some really weird optimization menu, so far, haven't seen it . . . . .

ps. Like in the racing game, was hoping to take the most distant objects, like buildings, and make them maybe 128x128, since the player will never notice, the mipmaps will be swapped anyway, and as the player zooms further out, it'll maintain the ' chain ', I think . . . <3 Thx . . .

Was hoping someone here, would know that, an expert, on all things 3-d . . .

ps. Note in image above, mipmaps are actually swapped, at a relative close distance, to the camera, might as well use textures, of lowest size, could help me make bigger levels, that take less graphics memory, I like ' optimized ' stuff + bigger levels, not sure . . . .

Last, notice the car, assuming it has real-world size, relative to engine, it looks like mipmaps are swapped, at like, each 2 - 3 meter distance 'step', from the camera . . . Was hoping there could be some performance gains, by making use of that, or so . . . But, I have no idea if it actually has impact, on ' most ' games . . . .

SIsilicon commented 3 years ago

I agree with @Zireael07. This is a pretty good proposal. BTW, there's this image file type called a ".dds", otherwise known as a "Direct Draw Surface". As far as I know, it's the only file type supported by Godot that can store custom mipmaps. This means you could create and edit such an image with each mipmap level distinguishable from each other, allowing you to see where the graphics processor uses each level. I've never used such a file format before though, so I'm not even sure if it still works with Godot as documented, but it's definitely a workaround worth considering in the meantime. Again, great proposal. I totally understand what you're getting at. 👍

Edit:

I'd think any surface, say a plane, would either have level 1 or, level 2, not a gradient :OO look like, it requires much more performance, to make those ' blends ', well, I'm noob, not sure this isn't in the engine, in some really weird optimization menu, so far, haven't seen it

What you've described is called linear mipmap filtering. This is when the mipmap levels are interpolated between each other to hide the transitions between them. If nearest mipmap filtering were used, you'd see a seam in the texture where the mipmap levels are swapped according to the apparent texture size. With today's GPUs, the performance hit caused by using linear filtering is practically negligible, so optimizing it by using nearest filtering isn't really necessary.

charlesmlamb commented 3 years ago

Well, that's the problem, I made some mipmap tests, with some texture with a low pixel edge ( called pixel ' bleed ', in Blender, or so . . ), and the seams also appeared in linear mipmap filtering . .

I assume, Godot is also using linear filtering, by default . . I now know, those lines near the seams, were from mipmap compression, or the scaled down being swapped, at a distance, not sure . .

Well, here was the idea, for instance in a game in a house, that one can't leave ( horror, not sure, door's locked, or it is magically sealed, not sure . . . ) that, I could have some trees, in the yard, that were visible through the windows . . . Then, if player would only ever see them at mipmap level 3 . . To just paint them at that level, but that wouldn't work ?? Bec. then, the mipmap filtering would mean, that one would see them at level 3, plus 3 extra levels of compression, due to camera forcing mipmap compression, as well as my ' pre-compressed ' texture :OO . .

Well, so if I did that, in the game, say made a 512x512, into a 128x128, or 3x compression, then trying to ' run ' that, it'd be displayed as 16x16 ( 3x ) bec. the camera would detect, this object is certain distance away, auto-compress 3x . .

I'd have to disable mipmaps, to do this, so it didn't ' add ' up the compression . .

This is where, I sort of get confused, when things get this ' technical ', it's really complex :(( . . .

Maybe there is some use for this, in order for this to work, one would have to be able to set the ' rest ' mipmap level, for some object, ie. find mipmap level and, add 3 to it, in the above example, then it'd work . . . Otherwise, my pre-compression, at texture level, would get added, to what happens, due to distance, relative to camera :OO . .

also, with mipmaps being gradients, it becomes quite difficult, to decide what level to start at, ie. it won't be clear, but one could optimize stuff that way . . . It'd have to be done at a per object basis, or set for specific textures, when importing . . .

Maybe someone here, who really understands if this could work, could ' look ' it over, for errors . . . <3 <3 . .

ps. I'm not that good, at figuring stuff out, at least this technical . . Well, I don't know, I think it depends on one being able to set a ' mipmap offset ' value, since they are done in order, of 50 % compression, ie. for a 512x512 texture, level 1 mipmap is 256x256, if one could set a ' default mipmap value ', one could sort of, make the computer realize the texture has a, 'relative mipmap offset ' or, this is where my 'brain' crashes, lol . . . that way, the texture would be drawn and, the higher level one's, ie. IF I moved closer, would simply not ' be ' there, so if I could walk to the tree, in the yard, it would just look like a 128x128 <3 not sure, if this is useful :OO maybe it's a new optimization technique, sigh it's hopelessly complex . . . ( as if, the higher mipmap levels didn't exist ) . . .

Well, maybe it's too complex, one would have to be able to set, a constant mipmap offset value . . . .

Help, I don't know if this is even possible . . :(( <3 . . .

The problem with pre-compressing is, the camera will detect, this object is far away, and then use mipmap compression level 3, as well as, the pre-compression I make, resulting in things looking pixelated . . This only works, if one can set a ' mipmap offset value ', should be an integer . . I'm not sure if this would have much effect, but looking at images above, it looks like mipmaps are swapped at a short distance, so there could be some gain, for far-away objects, where one could even use 16x pre-compressed textures, or so . . then, just set mipmap offset to 4x ( or, 3x ) and, it works . . and, one saves 16x texture memory, for that one texture <3

ps. Did some test, with a model with low pixel edge, in the texture, near UV's, and zoomed in, the object had no seam mipmap errors, or so . . . But, even after zooming 3 - 4 meters away, the compression errors near, the seams were quite visible, so I think textures are swapped, at relatively low distance and, also at a rather high frequency, looking at above images . . . If that's the case, one could at least optimize a level somewhat, and have much more objects, in the distance . . However, this might be ' completely ' wrong, or so . . .

Sort of, for far-away objects, since one only sees the 3x mipmap compressed version, why not just a pre-compressed one, since the ' bigger ' one, is just going to ' waste ' . . if mipmap compression is severe, like some images, ie. it happens at short distance and, quite often, this might save memory, that's the idea, I'm not sure . . . . .

Example, let's say mipmaps are swapped, for each 3 m distance step, to the camera . . . Then suddenly optimizing this becomes maybe valid, the problem is I can't visualize that, atm . . So, I have no idea . . Wanted to ask some pros, if this could be used <3 <3 . . . .

SIsilicon commented 3 years ago

Well, that's the problem, I made some mipmap tests, with some texture with a low pixel edge ( called pixel ' bleed ', in Blender, or so . . ), and the seams also appeared in linear mipmap filtering . .

I think you and I are talking about different seams. The seams you're talking about now aren't caused by the mipmap blending with each other, but rather by the way the mipmaps are generated automatically. When generating each successive mipmap level, the pixels are averaged together to make a texture half the size of the previous miplevel. For a continuous texture this works fine, but for a texture that is used by a uv-mapped model, the pixels that don't normally show up in the model start to bleed into the UV islands with each mipmap level, which causes those seam artifacts when viewed from a distance. That's why pixel bleed helps; because it gives the mipmap generator some redundant data to keep the pixel data correct in more mipmaps. Unfortunately, it's not a complete solution. If the UV islands are too close, they'll end up bleeding into each other too no matter how much pixel bleeding you use. The best solution to avoid those seams entirely would be to create/edit the mipmaps manually, and that's where the .dds file shines.

charlesmlamb commented 3 years ago

Well, I'll let you figure it out, I don't fully understand it, if it would be ' useful ', Thanks . . .

ps. Think it requires to manually set a mipmap offset, ie. start at mipmap no. 3 or, so :OO . . .

SIsilicon commented 3 years ago

ps. Think it requires to manually set a mipmap offset, ie. start at mipmap no. 3 or, so :OO . . .

I'm saying that it's the mipmaps themselves that have the problem. The seams get larger with each subsequent mipmap level. If you tried offset the sampling offset to use the smaller mipmap levels, you'd only make it worse. Biasing the levels the opposite way would help make the seams less noticeable at a greater distance, but the underlying problem still remains.

TL;DR If the generated mipmaps aren't good enough for you, make them yourself.

charlesmlamb commented 3 years ago

Well, it was an idea, not ' sure ' if it worked, oh well . . . :OO . .

SIsilicon commented 3 years ago

It's all good, so long as we understand each other. 👌

charlesmlamb commented 3 years ago

Ok, this is the problem, suppose a 3-d model is, at mipmap level 2, ie. that's what is on the ' object ', or so . . .

2021-05-13 1009

Sort of, in this case, first one is a 1024x1024, then at certain distance, it's ' rendered ' from the 256x256, at level 2 . . One THINKS, one could just make a 256x256 texture, and save memory that way, but then when engine sees 256x256 as, level 0, then it will use a 64x64 texture, and it will look pixelated . .

So, imo one needs to be able to offset the mipmap level, say ' start at ' level 2, not sure . . .

That way, as one moves closer to the object, it keeps the 256x256, at level 1, and level 0 . . :OO . .

Theoretically, for background objects, if that was possible, since each mipmap level ' saved ' means 4x texture memory ' advantage ', one could optimize levels that way . .

Theoretically, a 4 MB texture, could become a 1 MB texture at level 1, 0.25 MB texture, at level 2 . . That way, one could 'optimize' a level, but one could also just make a feature, where one ' sets ' mipmap offset level, so an object simple ' skips ' the higher level textures, doesn't load them into texture memory and, maybe do that . . It'd also be easier to see visually, if one could just ' adjust ' the slider, and see if it had an effect, or so . . ie., when ' pixel ' quality becomes clear, it is falling, on the object, it means one could just use the highest mipmap, that doesn't cause loss, of visual quality . . . So, if one made a feature, that could auto-remove mipmap levels, basically it'd just have to scale texture 50 %, 25 % and, then save it . . . Combined with a mipmap offset value, one could cut down on texture size dramatically, without losing visual quality or, so <3 . . .

charlesmlamb commented 3 years ago

Last, here's the math . . Say, you have a tree, or so . . that will only be shown, at mipmap level 2, then one can save texture size, with a mipmap offset level . .

Level 1 -- 1/4 size Level 2 -- 1/16 size Level 3 -- 1/64 size Level 4 -- 1/256 size

Both, in the hard-drive files and, in texture memory . .

Let's say, one has an object that look, to be at level 5, at all times . .

Then, one could just set the offset, to 3 levels, no one would even notice, and even if it's not super - optimized, it'd save, for level 3 . .

1/64 of, normal texture size . .

Prob. is, not sure at what levels this happens, can't 'see' it, from the images it looks like, it happens after a few meters, not sure . . . .

2021-05-13 1119

However, in this image, it looks like it happens even more . . .

2021-05-13 1121

There might be some ' optimization ' that's possible, if one could preview it, and has an ' offset ' value, then when one is happy, it doesn't cause loss of visual quality, his ' adjust texture ', and it just compressed it to, say 0.5 x 0.5 size . . Might be nice for stuff, in the background, like far-away trees or, well so on . . . .

Calinou commented 2 years ago

Related to https://github.com/godotengine/godot-proposals/issues/3213.

In general, I'm not sure how useful it is to show the mipmap level. Showing UV1 density is likely more relevant in most scenarios (when you want to see if textures are overly detailed at a given camera position).