Zylann / godot_voxel

Voxel module for Godot Engine
MIT License
2.59k stars 244 forks source link

Any other way to use multiple materials for Sdf? Or delay generation of block? #182

Open Favkis opened 4 years ago

Favkis commented 4 years ago

As I understood it's impossible to make multiple materials per voxel for SDF so I use new layer of voxel terrain for each new material. But for test I created 64 layers of voxel terrain and I get freezes when generating new blocks. Is there any way to stretch generation to multiple frames instead of one so I wont get freezes?

Zylann commented 4 years ago

As I understood it's impossible to make multiple materials per voxel for SDF so I use new layer of voxel terrain for each new material.

It is possible, just not implemented yet. One reason is Godot has severely limited amount of vertex attributes and I had to take a lot of them just to make Transvoxel stitching.

I created 64 layers of voxel terrain and I get freezes when generating new blocks.

Don't do this. Currently, 1 terrain creates at least 2 threads which run as fast as they can to generate and polygonize blocks. 64 terrains means you have 128 threads, and 64 more voxel data to deal with, which adds up to insane amounts.

Is there any way to stretch generation to multiple frames instead of one so I wont get freezes?

The module already do that... with 1 terrain. It's not applicable with many. I plan to centralize this at some point but even if it was today, it would just mean your world would take dozens of minutes to even load and still consume absurd amounts of memory.

Basically, this is not the right way to get multiple textures at the moment. Only shaders alone can help. To use voxels for that, the mesher needs an improvement based on the Transvoxel paper.

Favkis commented 4 years ago

@Zylann Even on very weak pc, additional terrain don't take long because they're mostly air. Occasional trees, player built houses from 5-8 materials. It doesn't really take FPS and memory all that much.

Plus shaders wont really help because it'll require rewriting mesher too, because otherwise placing planks and stone near would make that mesh interpolation, while when using separate VoxelTerrains it doesn't.

I'll run more benchmarks, to see what's up with performance, but for now the biggest hit is generating new empty blocks for some reason.

Maybe you could write special type of voxel terrain or give an idea how to make it? Currently we use one VoxelTerrain for main map (rock/grass), second for dirt, third for tree branches, forth for leaves and so on. I don't even think it hits performance outside of generating new blocks, because when you dig something, on example hatchet, hatchet uses only vt of treebranch. Pickaxe uses only vt for rocks etc. So existing voxelterrains/blocks/voxels don't even being worked with outside of generating new blocks.

Zylann commented 4 years ago

I'm just saying that the way you use it, is not how it was designed for. It will be possible to use multiple voxel nodes at once in the future without destroying CPU usage but again there isn't much to do until the SDF mesher includes material information.

See also https://github.com/Zylann/godot_voxel/issues/93

16millionoctopodes commented 4 years ago

I'm new to this plugin and Godot, so apologies if this is a dumb question. As far as I can tell, the demo example applies terrain textures based solely on face direction. Therefore, if I wanted smooth terrain that uses many different textures independant of face direction, I would have to:

(1) decide on which voxel channel I want to use to govern what texture is to be applied to the voxel, (2) write a new mesher that, based on that channel, sets vertex attributes UV and UV2, (3) write a new shader that applies different textures based on UV and UV2 vertex attributes, (4) for initial terrain setup, write a new generator that sets each voxel's channel data for texturing, (5) during gameplay, use the VoxelTool function to retexture voxels by changing the relevant channel data.

Is this correct?

Zylann commented 4 years ago

@16millionoctopodes yes.

16millionoctopodes commented 3 years ago

I've almost managed to complete the steps I described earlier, but I'm still having problems with the mesher. Currently I'm trying to pass data through channels 3-6, but I'm unable to access them properly in voxel_mesher_transvoxel.cpp.

More specifically, from within the functions VoxelMesherTransvoxel::build_internal() and VoxelMesherTransvoxel::build_transition(), I am trying to get_voxel() channel data 3-6 to create uv and uv2 Vector2 values, which I then pass to a modified VoxelMesherTransvoxel::emit_vertex() function. However, my calls to get_voxel() aren't returning the correct data; instead I get default empty values whenever I call either voxels.get_voxel(position, channel#) or get_voxel(voxels, positon, channel#).

Zylann commented 3 years ago

Are you testing your mesher standalone instead of with the whole terrain system? Because that would be the best way to work on this. The terrain system does a bunch of other things such as generating, storing in maps, threading etc which might interfer in what you want to do (maybe it's not copying your channels when sending them to VoxelServer).

That is, you should test this with only one VoxelBuffer that you populate, send to your mesher and display the result in a mesh instance node.

Also, 4 channels just for texturing sounds like a lot. Are you going for a classic RGBA splatting approach? If you do, a single 32-bit channel would be enough, and accessed faster.

16millionoctopodes commented 3 years ago

Turns out it was all just a stupid mistake on my part (yeah, I'm still very new to this). I had voxel_server.cpp use my new mesher, but forgot to activate the additional channels in the function copy_block_and_neighbors().

I am planning on eventually using a single 32-bit channel; using multiple 8-bit channels is just a temporary thing while I'm still familiarizing myself with the code.