Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic shader tools for easy disabled clipping on viewmodels (ViewmodelSpace) #119

Merged
merged 5 commits into from
Mar 18, 2024

Conversation

FailSpy
Copy link
Contributor

@FailSpy FailSpy commented Mar 14, 2024

I've been wanting to implement 2nafish117's viewmodel shader for a while now
https://www.youtube.com/watch?v=NF-U5J92ivk

However I didn't love the fact that it required all materials to be reconfigured with a not-exactly 1-to-1 version of the StandardMaterial3D.
Well, inspired by #116, where @Phazorknight shows a 4.0+ compatible version of the Viewmodel shader, I decided to see what it would take to dynamically create a "ShaderSpace" for viewmodel versions of wieldables. This is the result of that experiment.

Basically, I now have a Prefab 'ViewmodelBasePrefab.tscn' that if you make a parent of your mesh holder, it will go through all the materials available as its children (or children of children of children of children....) and configure it to be as close to the original StandardMaterial3D as possible.

This, I acknowledge, is most definitely not performant, however it only does it once per load of a wieldable's viewmodel. So as long as you're not trying to have hundreds of individual wieldables, this seems acceptable. I will probably see about making it into an editor tool later down the line so you can instead "bake" the materials and thusly ship it without the on-runtime generation

This all works via the ShaderSpace script I've written. If you choose to use that manually, you can set any shader you like, and if your property names share that of StandardMaterial3D names, it will automatically port a shader to that -- though right now the viewmodel concept is fairly hardcoded.

You can also change ShaderSpace's shader_override_enabled flag in code which will toggle the no-clipping feature for that specific wieldable on demand. Not sure if this actually has a use for anyone, but it's there!

Right now the ShaderMaterial conversion is very basic. It does not do Godot's dynamic conversion to ShaderMaterial so it doesn't include all the possibilities. I'm working on a better way to do this, but right now this works with all view model features used by Cogito's included wieldables.

EDIT:
Turns out, there's no way to access Godot's internal Shader Conversion directly thanks to _get_shader_rid being entirely internal usage, BUT, the code that is used to actually convert shaders from StandardMaterial3D to ShaderMaterial is all readily available... in C++. Simple stuff: the code is legitimately just an appended string based on a whole bunch of conditionals. So convert that, and you have a GDScript implementation of it.

I'm sure it's still not perfect, but it's 95% of the way there. Again, not performant, but probably still fine for a couple of wieldables.

So I now have 'Material3DConversion' as well, which allows you to run Material3DConversion.create_shader_code(mat,variables,vertex) to inject variable code and vertex code into whatever ShaderMaterial would have been generated if you'd done it via the Editor. (Though this does not currently support anything but StandardMaterial3D -- this excludes ORM based materials)

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Okay, I'm pretty happy with this experiment now. Opening the PR for review

@FailSpy FailSpy marked this pull request as ready for review March 14, 2024 14:50
@FailSpy FailSpy force-pushed the viewmodel-clipping-experiment branch from e66c26f to 27a88c4 Compare March 14, 2024 15:23
@Phazorknight
Copy link
Owner

Just checking in if this is ready for review now? @FailSpy

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Yep! @Phazorknight

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Worth noting I'm very open to any requests/extensions on this, this is a large feature.
Want to make sure it's solid.

@Phazorknight
Copy link
Owner

Overall the setup seems pretty straight foward and the results are great.
I took the LaserRifle into the Lobby scene and had correct shadows from the big windows on the weapon model.

I think this will work for most use cases. Though I definitely noticed the performance spikes when first equipping wieldables. I'd definitely welcome the option to either A) convert the materials in the editor - or B) convert them during scene load, though I'd prefer option A as it would give more control to the developer while reducing load times.

Additionally, if you could provide a documentation paragraph that explains on how to set up a mesh inside a Wieldable to work with this, I'd say this would be ready to merge into main.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Though I definitely noticed the performance spikes when first equipping wieldable

Hm, equipping wieldables should not be causing a performance spike from this. It should be doing Option B pretty much as you stated: The materials are created when the scene loads the nodes, after that they should just have the new materials and the ShaderSpace code basically stays idle after.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

@Phazorknight Give it a shot now. There's documentation directly in the scripts. If you want more, just ask!

You can now check (or un-check) 'Bake' on ShaderSpace and it will do the conversions in editor. Please note it stores the old version of the Material into a new folder .prebake so that way there's somewhere on disk that you can "un-bake" your material and get back the original.

I believe even without baking, the stutter that occurred on equip should be improved if not gone now as I've added seven ways to Sunday to stop any "rematerializing" code from running if it's not necessary.

@Phazorknight
Copy link
Owner

@FailSpy thanks so much for this!

So, after baking, Godot crashed twice for me, each time when switching to a different scene (once from switching from the Wieldable scene to the Player scene, and then after a restart, again when switching to a level scene).
I've restarted it again, and everything was fine until I baked another wieldable, then the crash occured again on scene switching.

I was also not able to get a wieldable to not clip without baking the materials. Just checking/unchecking the Disable Viewmodel Clipping had no effect on my end on either the Pickaxe or the Toy Pistol.

A note on the stuttering: I think know this might've been caused by something else. I did get it again when I first equipped the laser rifle when loading this PR, but haven't gotten it since.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Yikes, any chance you managed to catch what crashed it? Haven't personally had my Godot editor crash in all my testing

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Actually hmm, I may have a theory

@Phazorknight
Copy link
Owner

@FailSpy
this is what the shell caught when it crashed, though it might not help you that much:
image

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

Whaaaaaat. I wonder if that's your Godot editor trying to do an HTTPS connection for submitting the error??

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 14, 2024

godotengine/godot#84966

Hmm, wonder if this has anything to do with it?

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

@Phazorknight aaactually, try this latest run. Should fix bakeless shaders, and I'm hoping it avoids whatever issue is causing your crash (which I suspect may be filesystem related)

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

Ready for review again. Curious to know if editor crashes still occur, as I've been completely unable to reproduce on my machine.

@ksjfhor
Copy link
Contributor

ksjfhor commented Mar 15, 2024

So I tryed this PR out, and this is strange:
When I first picked up the flashlight there was a little lag, same on the toypistol, but not much, only like a 0,3sec delay, but it was noticeable and never happened again after that.
and
I cannot place any wieldable for some reason, the ones that were already there work:
https://github.com/Phazorknight/Cogito/assets/87974401/a62df8a3-d71b-48aa-b9d4-43443966bdac

You may need to pause to see them in the editor.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

@ksjfhor Are you trying to place one in the world? If so, you need to place the pickup version of the asset e.g. Pickup_LaserRifle, not the wieldable laser_rifle.

Later down the line I might see about making a PR to unify this to make implementing wieldables easier, but for now that's how things are setup.

@ksjfhor
Copy link
Contributor

ksjfhor commented Mar 15, 2024

@FailSpy not only do you implement this in a godlike speed, you also know what i did wrong.
The light influence and the shadows on the models is great and the pickupable doesn't cast a shadow, I think that's good too, otherwise it looks weird because we don't have a player shadow.
I get a little lagspike and delayed showing when I first equip a pickupable, but after that it seems that the shader is cached, not sure if godot or my amd driver. I can rerun the scene and the lag does not happen again.

This could be due to godotengine/godot#61233 ?

shader.mp4

So maybe the shader could e.g. get loaded in the main menu behind the visible menu to avoid those lagspike ?

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

That issue you mentioned sounds like a perfect fit. Will investigate the potential solutions later.

@Phazorknight
Copy link
Owner

I get a little lagspike and delayed showing when I first equip a pickupable

I think thats the same spikes I experienced. Re-equipping in the same or in a different level scene didn't cause the same spikes, so it seems very much like a caching hiccup.

Ready for review again. Curious to know if editor crashes still occur, as I've been completely unable to reproduce on my machine.

Gave it a try just now and had no crashes. Though it seems like the ability to "bake" in the editor has been removed, so that might've helped. Results seem great so far!
Let me know if you have any more changes planned or if we should try merging this in.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

@Phazorknight Hm, bake should not be removed! Is the checkbox not there?

What I changed about baking is that it no longer attempts to save the resource files to disk, and instead expects the dev to save any original materials that they might want to convert back.
Did this because I suspected that automated filesystem access may be causing issues, so instead it gets stored into the ConvertedMaterial's memory.
My concern is I'm not sure how Godot handles unaccessed attributes like that, so it very well might increase RAM usage, but shouldn't do it by much as the StandardMaterial3D resource itself is fairly small.

I'm currently investigating ways to do shader precompilation to stop the lagspike on equip. Once the shader is in the cache, it should be fine.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

Out of curiosity to @ksjfhor and @Phazorknight: equipping a wieldable, lagspike, then equipping a different wieldable... lagspike or no lagspike?

I would test it myself but I don't seem to get the same shader compilation lagspike.

@ksjfhor
Copy link
Contributor

ksjfhor commented Mar 15, 2024

No lagspike on other wieldable, just the first.
A 4.x shader pre render is mentioned as the last comment in the godot issue from earlier.
May this lag be an amd thing ?

@Phazorknight
Copy link
Owner

Hm, bake should not be removed! Is the checkbox not there?

Nevermind, I think I haven't properly pulled the PR on my end. It's there. Everything seems to work great!

Lag spike

The spike on my end is only the first time I equip a wieldable, and it doesn't seem consistent, but I haven't tested this extensively. I'm not really considering this a major issue at the moment.

I might see about making a PR to unify this to make implementing wieldables easier

Please let me know what kind of changes you're considering (maybe in a Discussion thread).

Otherwise I feel like this PR is about ready to merge into main, unless there are more objections.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

I think I successfully implemented shader precompilation. Fairly hacky, but from looking at the various threads about shader precompilation, the way I'm doing it may actually be the cleanest way without recompiling the whole of the Godot engine, and Vulkan...
When precompilation is enabled, you'll probably face some stutters at the start of the scene, but hopefully this means the rest of it is smooth.

If this works on @ksjfhor or @Phazorknight's system to get rid of the lagspike-on-equip, I'm happy to have this be merged!

EDIT: Two minor changes below to fix two minor derps, actually happy good now! :P

@FailSpy FailSpy force-pushed the viewmodel-clipping-experiment branch from 6ea2b33 to 92ba7fe Compare March 15, 2024 19:18
@FailSpy FailSpy changed the title Viewmodel clipping experiment Automatic shader tools for easy disabled clipping on viewmodels (ViewmodelSpace) Mar 15, 2024
@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 15, 2024

A 4.x shader pre render is mentioned as the last comment in the godot issue from earlier.

Oh bugger, I completely missed that. I'm quite happy with my version though, it's fairly similar, but it doesn't require any nodes to be added to the scene manually. If you choose to precompile a shader in ShaderSpace/ViewmodelSpace, it will do the magic itself, and reliably keep it off screen.

As well, other scripts can hook into it the same way. I also have a queue system implemented in mine to make it so the game only tries to compile one shader per frame, allowing the game to not go too long between frames and thusly the game can keep up.

FailSpy added 4 commits March 15, 2024 21:05
Configure existing wieldables as Viewmodels
Remove auto-saving scene and saving mats to disks to avoid issues, fixed no-bake
Ensure freeing of resources
@FailSpy FailSpy force-pushed the viewmodel-clipping-experiment branch from f86c0f4 to 7618f2f Compare March 16, 2024 01:09
@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 16, 2024

Big ol' commit fixup/squash done. So long as its given the okay by you @Phazorknight, I'm very happy with this PR.

@ksjfhor
Copy link
Contributor

ksjfhor commented Mar 16, 2024

So with the newest fetched up, godot starts the project with:

scene/main/viewport.cpp:137 - Viewport Texture must be set to use it.
scene/main/viewport.cpp:127 - Viewport Texture must be set to use it.
scene/resources/resource_format_text.cpp:284 - res://COGITO/Assets/Shader/ShaderLoader.tscn:21 - Parse Error:
Failed loading resource: res://COGITO/Assets/Shader/ShaderLoader.tscn. Make sure resources have been imported by opening the project in the editor at least once.

So I wanted to open the ShaderLoader.tscn and:
grafik

But as you can see in the screenshot, when I run the project the messages are gone, and also the lagspike, but I am not sure if this is due to some caching on my end ....
"It just works" - Todd ?

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 16, 2024

It just works.

Anyways, that's weird that it got invalidated/corrupted. I've modified the script now because I realized there's a way to do it without a scene, and I think the shader precompiler is even more reliable now after remembering custom_aabb

Give it a shot now.

@FailSpy
Copy link
Contributor Author

FailSpy commented Mar 16, 2024

Fun tidbit, you can apply ViewmodelSpace to anything, and you get wallhacks!
image

@ksjfhor
Copy link
Contributor

ksjfhor commented Mar 16, 2024

It just works sing
Without a doubt, no more errors or lagspikes or anything.
Well done !

Copy link
Owner

@Phazorknight Phazorknight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!
Thank you!

@Phazorknight Phazorknight merged commit 918805a into Phazorknight:main Mar 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants