Hello, everyone! Not sure if this is the right place for the discussion, so sorry for the inconvenience if it isn’t.
I recently got into reading about and coding shaders, specifically geometry shaders. I wanted to do some complex fur for a project I wanted to do, and I actually managed to make something work for once! But, I’m pretty bad at shader code, so I’m getting stuck a lot.
What I achieved so far, is some strands with a square base and pyramid tip, with controllable width and length with some randomness thrown in. But, everything is kinna hard coded right now, and I would like to be able to control things like bending and curling of the strands, probably through a texture input at the end.
Here are some images for what I got right now and my process so far:
Linking the code file with the post, its a bit too big to be pasting it in wholesale.
And yes, I know IF statements in a shader are very bad, but right now, I just wanna see it working.
What I’m basically asking for is any tips, ideas for better or more streamlined solutions, or recommendations for good tutorials/articles that go beyond rendering some grass that could help me move along with the project.
Thank you very much for your time!
If statements in shaders aren’t bad per se, just that it does 32-64 threads at once, and if any one of those threads takes a branch, every single one will take that branch (meaning it often evaluates both sides of an if). But branching on constants like you’re doing is not a problem at all, and if most of the verts will take only one path, then the branch is good.
For your use case, I think* you probably should look into using tesselation and not geometry shaders, since it does 80% of the work for you at the hardware level (generating the subdivisions/verts; you can it can base subdivision level on how far the input vertex is from the camera instead of the whole object, etc). Also supposably geometry shaders are poorly implemented by many GPUs and not supported on some APIs (Metal). Best tutorial on tessellation I found: Tessellation . In the hull and patch shaders, you do the subdivision into verts, and once you get to the domain shader, you make the verts actually look furry. Compute shaders are another option.
But fur effects (at least for reasonably short fur) are usually done by rendering multiple “shells” each slightly bigger than the previous with a custom fragment shader. Doing individual hairs is going to be much slower and potentially overkill. If you want to get really fancy, there’s also raymarching-based approaches: Shader - Shadertoy BETA or Shader - Shadertoy BETA
Oooh, interesting, I didn’t know tesselation could be used that way! Definitely something worth reading into, tho I should have probably mentioned, I really want the fur to have some thickness on it and be more “clumpy”, kinna stylized.
I don’t mind that geometry shaders have problems on some GPUs, this isn’t a commercial product that needs to run bug free on 1000s of pcs x3
I will have to look up stuff on compute shaders, my attempts at implementing them in the past have not been very successful, but I would really like to learn!
And yeah, I know there is assets out there that do similar stuff xD
But, I enjoy the challenge, and I wanna know what goes on in there and be able to modify it. Modifying ready made stuff usually just breaks it for me
Solved some of my problems with a couple of lerps and adding more data to the quad creating part. Still not sure whats going on with the UVs, this felt straight forward to me, stretch every quad from left to right, and across the proportional height of the current segment, but for some reason, it only works like that on one subdivision.
Hello again!
I took a little break from writing shaders to work on some gameplay, but I’m back at it today!
Trying to learn some compute shaders after reading about what they can do, did a couple of tutorials, which went alright, but now I’m trying to write something from scratch and running into all sorts of problems.
All I’m trying to do right now is for it to generate one triangle per given point, and everything generates fine, all indices and vertices are there, but for some reason, all vertices have the same value? What am I doing wrong?
I think I’m calculating it like you are supposed to, taking each float value of the struct, its just one vector for now, so I don’t see how that could be wrong…
I fixed the threading too, since I was definitely doing that wrong, and that solved some problems, like vertices past index 4 having 0 values, but still, no mater how many triangles I try to do, they all have the same vertex value…
I’m uploading the whole code, if you wanna have a closer look
also, just in case there are doubts, i rechecked the function i use to generate the corners of a triangle in c#, and it works perfectly there, as it did when I was doing it in Geometry shader
This is where the corners should be when I’m generating them so I dunno…
Maybe it would be easier to just use a quad as a base with some variable offsets on width and thickness, but its really annoying that it just refuses to work xD
Yeah, I reordered this particular bit a bunch of times to no effect…
This is actually how it was in the tutorials I was reading, which seemed odd to me, so I put it in front at first too.
SO, I went over the whole code with a friend, stripped down everything to check what was working and we finally found the culprit…
its this guy here:
For some reason, everything done with this little guy returned 1, no matter what. We were both stunned, but the moment I replaced it with this:
Everything worked perfectly! (the triangles are upside down but thats easy to fix)
So yeah, hope that helps anyone else having troubles with PI in their code, I have no idea what the difference is between the two, but just use #define going forward xD
The magic part is the SV_VertexID which gives you the index into your StructuredBuffer. This way, you never have to send any data back to the CPU; you just generate it and access it all on the GPU.
Well, SRPs (URP/HDRP) are the “future” of Unity so are getting new features, while builtin hasn’t had any new features since like 2016. Also, they are starting to be more performant, although it depends on what you’re trying to do. They are more complex, though.
For what you’re doing, HDRP might be a good fit. HDRP also has a ton more features than URP. URP is more for targeting low-mid end hardware, eg phones and Switch