godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.14k stars 93 forks source link

Add NoiseTexture3D #4946

Closed Lasuch69 closed 1 year ago

Lasuch69 commented 2 years ago

Describe the project you are working on

Just testing features before release.

Describe the problem or limitation you are having in your project

Fog volumes could be procedural for nice vfx but lacks an option to do so OOTB (maybe custom material will work but it would be awesome anyway to have built-in). I am talking about using noise in density texture but noise doesn't have 3D output, and isn't even an option to choose (there is a 3D mode in noise but output is projected onto 2D texture).

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

Adding support for using noise texture with something like a real 3D mode in a FogVolume's material. This change could greatly increase volume usability and as i stated before, allow to create really nice visual effects easier.

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

NoiseTexture with maybe something like "3D" parameter could be used inside FogVolume density texture.

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

I think that it is possible but it is inconvenient.

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

i think that it is a basic feature that would be used not only in fog volumes because "NoiseTexture3D" could be used in a variety of shaders

Calinou commented 2 years ago

See https://github.com/godotengine/godot-proposals/issues/2261#issuecomment-775345186.

Note that in a lot of cases, using 2D noise to adjust fog density will look good enough. This is especially true since volumetric fog isn't designed to represent high-frequency detail.

cc @clayjohn

clayjohn commented 2 years ago

I think the best approach would be to create a NoiseTexture3D resource that has pretty much the same API as the current NoiseTexture2D. I believe the current Noise API is designed to make implementing this fairly straightforward.

Lasuch69 commented 2 years ago

I think the best approach would be to create a NoiseTexture3D resource that has pretty much the same API as the current NoiseTexture2D. I believe the current Noise API is designed to make implementing this fairly

Exactly what i need

Calinou commented 2 years ago

Last year, I started working on adding a NoiseTexture3D resource, but I couldn't get it working: https://github.com/Calinou/godot/tree/add-noisetexture3d

This was before the transition from OpenSimplexNoise to FastNoise, so the underlying code will have to change significantly. Feel free to look at that branch for inspiration nonetheless :slightly_smiling_face:

Lasuch69 commented 2 years ago

I've stumbled upon a design decision and i don't know what would be a better approach for a godot resource. Would it be better to modify a "noise_texture" code or to make a modified copy for a 3D usage?

Calinou commented 2 years ago

I've stumbled upon a design decision and i don't know what would be a better approach for a godot resource. Would it be better to modify a "noise_texture" code or to make a modified copy for a 3D usage?

NoiseTexture3D will need to be an entirely different class, as it's creating a different resource type (Texture3D instead of Texture2D). Feel free to copy-paste code if needed, still.

Lasuch69 commented 2 years ago

I have a problem. It looks like noise as a whole need some precompiled(?) files because when i forked the main branch then downloaded it there wasn't dependencies of noise. On docs i haven't seen anything about this, maybe i missed something?

Calinou commented 2 years ago

It looks like noise as a whole need some precompiled(?) files because when i forked the main branch then downloaded it there wasn't dependencies of noise.

All third-party libraries in Godot are included in the repository, and are compiled as part of its buildsystem. You don't need to manually download and compile third-party libraries before you can compile Godot itself.

Can you paste the full error message here?

Lasuch69 commented 2 years ago

It looks like noise as a whole need some precompiled(?) files because when i forked the main branch then downloaded it there wasn't dependencies of noise.

All third-party libraries in Godot are included in the repository, and are compiled as part of its buildsystem. You don't need to manually download and compile third-party libraries before you can compile Godot itself.

Can you paste the full error message here?

Okay but i still don't have a needed files to even compile a unmodified noise or maybe they are created during compilation.

Lasuch69 commented 2 years ago

Missclick. I will give it another try tommorow and if it wouldn't work i will send an error message.

Lasuch69 commented 2 years ago

I don't have problems with compilation now, but i don't know what could be better: creating extra functions in noise.cpp or to use existing ones and just stack generated noise images. From what i have in my code you can confidently say that there is stacking images in code, but i think doing it with existing functions could make noise look sliced or maybe i don't understand something.

Lasuch69 commented 2 years ago

I have a great news! Screenshot from 2022-08-10 22-52-52

I am really close to making it work!!!!

Lasuch69 commented 2 years ago

Okay so 256x256x256 is making my pc cry for help

Calinou commented 2 years ago

Okay so 256x256x256 is making my pc cry for help

A 256×256×256 Texture3D has the same amount of pixels as a 4096×4096 Texture2D, which is understandably quite demanding (especially when no VRAM compression is used). I'd suggest sticking to 64×64×64 in most cases (or maybe 128×64×128).

Lasuch69 commented 2 years ago

I have a issues with maximum value of Vector3 (i use it as size) so i don't think i even can. I will try to remove this cap by using something else.

Lasuch69 commented 2 years ago

My fork is updated and i think this texture is awesome here is an example:

Screenshot from 2022-08-11 15-37-37

This dense mist has 128 volume size and 64 volume depth. Even on default this gives so much ambience.

Calinou commented 2 years ago

@Lasuch69 Looks great! You can probably open a pull request now :slightly_smiling_face:

Lasuch69 commented 2 years ago

No. It is stable BUT seamless creation isn't done (only in 2 dimensions) and i get a lot of errors with mipmapping and texture format. I also need to look into code a little bit more.

Lasuch69 commented 2 years ago

Is mipmapping even useful in 3D textures?

clayjohn commented 2 years ago

Is mipmapping even useful in 3D textures?

Yes it is. It is important both for memory efficiency, but also for smoothing out aliasing over distance.

clayjohn commented 2 years ago

Is mipmapping even useful in 3D textures?

Yes it is. It is important both for memory efficiency, but also for smoothing out aliasing over distance.

Lasuch69 commented 2 years ago

ok so the only things left are seamless and mipmaps generation and also probably editor previews

Lasuch69 commented 2 years ago

Mipmaps work!!! Now seamless creation and refactoring and this texture will be ready to open PR :tada:

Lasuch69 commented 2 years ago

I think i will put a PR now because when i see code behind getting seamless image my brain hurts, and i have other things to work on so now i will move to refactorization. :(

Lasuch69 commented 2 years ago

1 bug left in the texture, sadly no seamless generation at least for now.

"Data for slice index 0 (mapped to layer 0) differs in size (supplied: 299596) than what is required by the format (299592)." This bug is nothing major, it is just making using the texture a little bit annoying.

When i will be done with making it i will try to make a little demo showcasing how beatiful it can be and how easy it is to setup. But i don't promise anything.

Lasuch69 commented 2 years ago

I've opened a PR https://github.com/godotengine/godot/pull/64654

aaronfranke commented 2 years ago

Considering that NoiseTexture inherits Texture2D, I think the rename to NoiseTexture2D stands on its own, so we can do this before adding NoiseTexture3D.

Lasuch69 commented 2 years ago

i got defeated by git.... lmao

Zireael07 commented 2 years ago

I assume this should be reopened then?

Calinou commented 2 years ago

I assume this should be reopened then?

This proposal was reopened already, but @Lasuch69 needs to open another pull request as https://github.com/godotengine/godot/pull/64660 was automatically closed (it was not merged to upstream master).

Lasuch69 commented 2 years ago

I will work on this more because i thought that i don't have much time for PR (that this could be merged in 4.0 and not 4.x) and i wanted to continue with my other projects. In the meantime i will work on polishing and i think that in 4.1 this will be merged as full featured texture (seamless generation, fix bugs etc.)

Lasuch69 commented 2 years ago

The math is going to be a nightmare with seamless generation and probably a new function in noise.cpp.

Maybe not math but reading code for seamless generation xD.

Lasuch69 commented 1 year ago

I gave it another shot. I will make updates on this.

Calinou commented 1 year ago

@Lasuch69 I've tried to apply the latest commit of https://github.com/Lasuch69/add_noisetexture3d/tree/add-noisetexture3d to the latest master branch, but it crashes when assigning a new NoiseTexture3D to any node:

ERROR: FATAL: Index p_index = 0 is out of bounds (size() = 0).
   at: get (./core/templates/cowdata.h:155)

================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.beta.custom_build (4d3e539da381715f35cd103292c17501cf4ae3e5)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib64/libc.so.6(+0x3cb20) [0x7fd17d05fb20] (??:0)
[2] bin/godot.linuxbsd.editor.x86_64() [0x3563e5b] (/home/hugo/Documents/Git/godotengine/godot/./core/templates/cowdata.h:155)
[3] bin/godot.linuxbsd.editor.x86_64() [0x3566a42] (/home/hugo/Documents/Git/godotengine/godot/modules/noise/noise_texture_3d.cpp:200)
[4] bin/godot.linuxbsd.editor.x86_64() [0x29f949a] (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:298 (discriminator 4))
[5] bin/godot.linuxbsd.editor.x86_64() [0x29f5447] (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:441)
[6] bin/godot.linuxbsd.editor.x86_64() [0x29ee9cf] (/home/hugo/Documents/Git/godotengine/godot/./core/object/method_bind.h:320)
[7] bin/godot.linuxbsd.editor.x86_64() [0x932864e] (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:733 (discriminator 2))
[8] bin/godot.linuxbsd.editor.x86_64() [0x8dbe194] (/home/hugo/Documents/Git/godotengine/godot/core/variant/callable.cpp:62)
[9] bin/godot.linuxbsd.editor.x86_64() [0x931e066] (/home/hugo/Documents/Git/godotengine/godot/core/object/message_queue.cpp:230)
[10] bin/godot.linuxbsd.editor.x86_64() [0x931e3cb] (/home/hugo/Documents/Git/godotengine/godot/core/object/message_queue.cpp:277)
[11] bin/godot.linuxbsd.editor.x86_64() [0x59719db] (/home/hugo/Documents/Git/godotengine/godot/scene/main/scene_tree.cpp:432)
[12] bin/godot.linuxbsd.editor.x86_64() [0x27e2179] (/home/hugo/Documents/Git/godotengine/godot/main/main.cpp:3087)
[13] bin/godot.linuxbsd.editor.x86_64() [0x274f3e4] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/os_linuxbsd.cpp:878)
[14] bin/godot.linuxbsd.editor.x86_64() [0x2742210] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/godot_linuxbsd.cpp:75)
[15] /lib64/libc.so.6(+0x27510) [0x7fd17d04a510] (??:0)
[16] /lib64/libc.so.6(__libc_start_main+0x89) [0x7fd17d04a5c9] (??:0)
[17] bin/godot.linuxbsd.editor.x86_64() [0x2741ff5] (??:?)
-- END OF BACKTRACE --
================================================================
[1]    29558 IOT instruction (core dumped)  bin/godot.linuxbsd.editor.x86_64 /tmp/4/project.godot
Lasuch69 commented 1 year ago

@Calinou I was testing something before and i haven't made it working again. I can fix it today. Maybe I will hopefully come up with a solution to my problems with this resource.

Lasuch69 commented 1 year ago

Rebased to latest commit https://github.com/Lasuch69/add_noisetexture3d/tree/add-noisetexture3d Works fine. Now let's do some mipmapping. :(

Calinou commented 1 year ago

Rebased to latest commit Lasuch69/add_noisetexture3d@add-noisetexture3d Works fine. Now let's do some mipmapping. :(

Tested locally, it still crashes on creating a NoiseTexture3D. This occurs even if I create the resource directly in the inspector, without assigning it to any node.

Lasuch69 commented 1 year ago

Rebased to latest commit Lasuch69/add_noisetexture3d@add-noisetexture3d Works fine. Now let's do some mipmapping. :(

Tested locally, it still crashes on creating a NoiseTexture3D. This occurs even if I create the resource directly in the inspector, without assigning it to any node.

That's weird. What is your platform? Nevermind, I recreated it.

Lasuch69 commented 1 year ago

Fixed the problem with crashing. I will update it in a moment.

Done! For now disable mipmaps to generate texture, and i will make mipmaps later as i need to learn how to make everything go nicely before adding all features. GDScript binding needs to be fixed in this resource.

Calinou commented 1 year ago

@Lasuch69 I still get a crash on commit 4d3e539da381715f35cd103292c17501cf4ae3e5 of your fork when creating a NoiseTexture3D:

ERROR: FATAL: Index p_index = 0 is out of bounds (size() = 0).
   at: get (./core/templates/cowdata.h:155)

================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.beta.custom_build (4d3e539da381715f35cd103292c17501cf4ae3e5)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib64/libc.so.6(+0x3cb20) [0x7fc00d97fb20] (??:0)
[2] bin/godot.linuxbsd.editor.x86_64() [0x3563e5b] (/home/hugo/Documents/Git/godotengine/godot/./core/templates/cowdata.h:155)
[3] bin/godot.linuxbsd.editor.x86_64() [0x3566a42] (/home/hugo/Documents/Git/godotengine/godot/modules/noise/noise_texture_3d.cpp:200)
[4] bin/godot.linuxbsd.editor.x86_64() [0x29f949a] (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:298 (discriminator 4))
[5] bin/godot.linuxbsd.editor.x86_64() [0x29f5447] (/home/hugo/Documents/Git/godotengine/godot/./core/variant/binder_common.h:441)
[6] bin/godot.linuxbsd.editor.x86_64() [0x29ee9cf] (/home/hugo/Documents/Git/godotengine/godot/./core/object/method_bind.h:320)
[7] bin/godot.linuxbsd.editor.x86_64() [0x932864e] (/home/hugo/Documents/Git/godotengine/godot/core/object/object.cpp:733 (discriminator 2))
[8] bin/godot.linuxbsd.editor.x86_64() [0x8dbe194] (/home/hugo/Documents/Git/godotengine/godot/core/variant/callable.cpp:62)
[9] bin/godot.linuxbsd.editor.x86_64() [0x931e066] (/home/hugo/Documents/Git/godotengine/godot/core/object/message_queue.cpp:230)
[10] bin/godot.linuxbsd.editor.x86_64() [0x931e3cb] (/home/hugo/Documents/Git/godotengine/godot/core/object/message_queue.cpp:277)
[11] bin/godot.linuxbsd.editor.x86_64() [0x59719db] (/home/hugo/Documents/Git/godotengine/godot/scene/main/scene_tree.cpp:432)
[12] bin/godot.linuxbsd.editor.x86_64() [0x27e2179] (/home/hugo/Documents/Git/godotengine/godot/main/main.cpp:3087)
[13] bin/godot.linuxbsd.editor.x86_64() [0x274f3e4] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/os_linuxbsd.cpp:878)
[14] bin/godot.linuxbsd.editor.x86_64() [0x2742210] (/home/hugo/Documents/Git/godotengine/godot/platform/linuxbsd/godot_linuxbsd.cpp:75)
[15] /lib64/libc.so.6(+0x27510) [0x7fc00d96a510] (??:0)
[16] /lib64/libc.so.6(__libc_start_main+0x89) [0x7fc00d96a5c9] (??:0)
[17] bin/godot.linuxbsd.editor.x86_64() [0x2741ff5] (??:?)
-- END OF BACKTRACE --
================================================================
[1]    18680 IOT instruction (core dumped)  bin/godot.linuxbsd.editor.x86_64 
Lasuch69 commented 1 year ago

@Calinou I am currently taking a break from programming. I will be back in a couple of days, after that I will be fully dedicated to it.

Lasuch69 commented 1 year ago

Okay so I made GDScript bindings work based on ImageTexture3D implementation. I will try to test some things then move on to mipmaps.

I will update repo in a moment. Done!

Calinou commented 1 year ago

Okay so I made GDScript bindings work based on ImageTexture3D implementation. I will try to test some things then move on to mipmaps.

I will update repo in a moment. Done!

Tested locally, it works great this time! Nice work :slightly_smiling_face:

Testing project: test_noisetexture3d.zip

There are two issues I noticed, but these are not critical for using a NoiseTexture3D as a density map within a FogVolume:

image

Lasuch69 commented 1 year ago

@Calinou I think that mipmaps are higher priority right now so I wasn't trying to implement seamless generation yet. Also good point with changing format with color ramp :)

Lasuch69 commented 1 year ago

Made it work the same way as 2D equivalent, L8 normally and RGBA8 with color ramp. I tried to make mipmaps... no progress so far, now I am doing seamless generation.

Lasuch69 commented 1 year ago

When I think about how much iterations are required for making seamless generation without modifying noise class I doubt that it is going to be usable on something higher than maybe 256x256x256. I need to iterate over a lot of images and arrays, arrays aren't that bad but I need to blend every single pixel on a lot of images.

Lasuch69 commented 1 year ago

I've managed to make seamless generation work but it is performance hog, definitely needs rewriting.

It is so heavy that on my CPU (ryzen 5 3400g) 128x128x128 texture isn't updating in real time with seamless generation turned on.

Lasuch69 commented 1 year ago

Screenshot from 2023-04-04 12-18-55 Wait hold on... no seams on z (depth) axis?! I've made seamless generation and found funny little bug with previous method of normalizing images, horrible banding was present because of normalizing on each image individually rather than whole 3D texture at once. It is fixed now though. I need to fix 2 things, some cleanup and (I hope finally) openning a PR.

On this image I am using x and z coordinates and not x and y.