Simple, cheap stylized tree shader
I was trying to recreate a simplified version of a stylized tree shader someone made in Unity:
Aafter trying to use a rotation matrix based on rodrigues rotation formula based on the vertex’s UV coordinates, I realised some of my code was creating issues. I took it out and the shader was still working, and realising that the rotation matrix was taking in values that were basically 0.0’s I took the matrix out and it still worked. Discovered that I was taking UV coordinates as if they were viewspace values and converting them to model space.
I doubt I was the first person to realise you could do this, but for my first shader that I programmed myself, I’m very happy with the results. I hope you may find some use of this technique/shader as well.
I have uploaded the texture I used as a ‘screenshot’ if you would like to use it. I dont know how uploading might change the image, but it was just a 256*256 PNG. the effect would probably work a lot better with a cleaner image with no anti-aliasing.
I plan to expand the shader to make use of a normal map to give the leaves depth, and to change that normalmap and rotate the ‘billboards’ in accordance with a wind system compute shader I’m working on.
Make sure the mesh youre applying this to is made of quads, and what the UV is unwrapped so that each of those quads use the entirety of UV space (so each vertex has a UV coordinate of both X and Y equal to either 0 or 1)
Shader code
shader_type spatial ;
render_mode depth_draw_always, alpha_to_coverage ;
uniform sampler2D foliage_texture ;
uniform vec3 foliage_colour : source_color = vec3(0.13, 0.33, 0.25) ;
void vertex()
{
NORMAL = -NORMAL ;
// Generate the 'billboard' 2D coordinates from UV coordinates, shift it to center over UV 0,0.
vec2 viewspace_offset = UV.xy - vec2(0.5) ;
//pretend the coordinates are in viewspace and pass them into inverse(MODELVIEW_MATRIX) to cheat our way into a billboard effect
vec4 modelspace_offset = inverse(MODELVIEW_MATRIX) * vec4(viewspace_offset.xy, 0.0, 0.0) ;
VERTEX += modelspace_offset.xyz ;
}
void fragment()
{
ALBEDO = foliage_colour ;
ALPHA = texture(foliage_texture, UV).g ;
}
hey!
Could you upload a super simple demo project? I tried the shader out, with the setup described, and it gives me very different results on Godot 4.1.1
I uploaded a barebones project to github of how I had it setup, the assets I used, and the results.
Would be cool to get the results in your screenshots with so few GPU calculations!
https://github.com/niceandgoodonline/simple-cheap-stylized-tree-shader-issue-demo/tree/main
Hello!
I’ve reuploaded your demo project with a few solutions. It took me a while to realize, but I didnt test the shader with a wide enough variety of meshes. As it turns out, if the vertices are too far away from each other in model space, the illusion breaks as the UV coordinates don’t scale along with them.
https://github.com/h3lly3r/Stylized-tee-shader-solutions
the three solutions I have come up with are as follows:
By the way I love the texture you were using in your example! I hope this works for you, please let me know if there are any other issues!
Cheers on the quick turn around!
Having a scale uniform is how I’ve seen other implementations of this handle varying base mesh sizes, and also resizing the mesh in editor.
Additionally, with default alpha settings and this technique as the camera gets further away from the model/shader it becomes less and less visible. You can counteract this by setting ALPHA_SCISSOR_THRESHOLD to a value lower than 0.5 (or use ALPHA_HASH_SCALE, if your game has post-effects or an aesthetic that’s ok with how this looks).
With the scissor threshold, the closer to 0 the more “fluffy” the leaves look up close, and the further away you can see them.
Not sure if you’ve seen it, but there is a pretty complex version of this technique available here
https://github.com/FaRu85/Godot-Foliage
it’s what I use for my LOD0 trees and bushes currently