This is incredibly dense content. Most tutorials I want sped up. This one I had to slow down! Very well laid out, you put a lot of work and thought into this. Thanks for sharing!!
The problem with clipmaps from my experience is that it cannot render the terrain at distances larger than the clipmap itself. For instance, if your clipmap is 2048 by 2048 and the map is 4098 by 4098 if you are somewhere in the corner of the map you won't be able to see any topological features beyond the 2048 threshold and that for me is simply not acceptable. I mean, yes, you could blame it on the fog but it will just ruing the immersion. Fog can be used to hide stuff such as grass chunks popping in in the distance, but you should still be able to see the mountains to make the player get a sense of just how large the map is. While quad tree based terrains are a little more difficult to implement I'd rather spend a day or two getting it to work the way I want it instead of sacrificing the immersion of an outdoor level for the sake of simplicity.
Well, infinite... if your height map has one texel per meter (which one would need to resolve river beds), then it'll start glitching 1000 km away from the origin. That's like, the size of France. Pretty huge indeed!
Origin shifting solves that, I actually made a terrain that goes up tp 16000 km, the only thing limiting the size now is gpu bit precision, for the heightmap generators.
There are ways of getting a lot more out of the heightmaps. Technically, It will always repeat eventually.. but it's effectively infinite lol. I'm going to make that the topic of my next video.
@@ditzyninja Yeah, that's the thing, I managed to make a truly infinite terrain that actually never repeats, it is 100% procedural, nothing is pre-rendered.
@4:50 you made the Take On Me music video! Cool tutorial! Hoping for more multiplayer stuff soon! Also, godot now exposes more pathfinding options for postprocessing.
Wow. I'd love to experiment with some more complex fragment shader for this terrain to make it look better. Thank you for releasing the code, though please specify a license - otherwise nobody knows what is and isn't ok to do with your code! MIT is the most liberal - people can grab the code and use it even in proprietary projects, GPL is more restrictive - it'll force whoever uses the code to also license theirs under the same or compatible license.
That's awesome man. I'm really glad this helped out. I don't make tutorials anymore, but I've learned a lot since making this. Let me know if you run into any other hurdles. I might be able to give some tips.
@@ditzyninja For context, Im using this framework as collision for my raycast based driving system. The major hurdle I'm running into currently is whenever the collision plane regenerates the raycast slips through for a frame making the driving feel jittery and unpredictable at times. If you found a fix to that or had a similar problem a general tip would be great. If not that's fine Im still extremely grateful for the tutorial!
important! adding the player to the export var, otherwise it will not work. and also get_settings is now get_setting_with_override. thats all i could find :)
okay this is great! most videos on these shader-based terrains come off as too complicated. But I have this one implemented now and working, so thanks. One question, I am trying to give some other characters collision with the terrain as well, but when I create a new static body and give it a new collision map, they are updating each other. I'm pretty confused on why/how this is happening. Didn't know if you had tried this and seem something similar. Thanks! EDIT: I figured it out! The reason it didn't work was because it was changing the shape property the collisionmap scene, which then affected every collision map. I ended up giving the static body node its own controller which insantiates a collision shape at startup for whatever physics_target you choose.
Hey Ditzy! Cool tutorial (both parts), also the dynamic texturing one is cool!!!! have a question. have you figured out how to calculate the normals in the fragment shader? i found some tuts, but they dont work with your specific case (i think because of the world pos of the vertex) im a noob in shaders, so i would love you could help me!
Hey thank! I have worked out the normals. That was going to be my next video, but I put my YoutTube channel on the back burner for a little bit. (Work, life, etc. they may be short but they take days to make). I'll try to get it up soon!
this line: var image:Image = load(ProjectSettings.get_setting("shader_globals/heightmap").value).get_image() gave me this error: Attempt to call function 'get_image' in base 'null instance' on a null instance. does get_setting work differently now?
This is an amazing tutorial, thanks! When you say a HeightMapShape3D (at 6:48) sometimes behaves strange, do you mean that it misaligns with the terrain mesh? I'm running into that now using Godot 4 🙂
I was planning to start programming a similar solution, but you have already done it and solved important problems. Have you thought about turning the project into an add-on / base framework for creating large worlds in Godot? Can you specify the license of the released code? It would be nice to fork it and try to turn it into an add-on, don't you think?
Thanks! That comes from the Heightmap script created at 5:43. You then have to add that script under the Autoload tab in the Project settings which makes it accessible in any other script in your project. It's Godot's version of a singleton.
Great series, wanted to test complete project as demo for my game but it gives an error "Invalid get index 'global position'(on base: 'Nil'). What should i do start using the template?
@ditzyninja I have the same issue, seems to be a problem with func _physics_process(_delta): global_position = player_character.global_position.round() * Vector3(1,0,1); I'm new to Godot but it seems like the player_character isnt being instantiated properly
So I am still working on this. I am now being bottlenecked by having too many moving items with these collision shapes at once, and I think it is because we are updating the collision shape on the CPU. I guess we could write it as a GDExtension in C++