Grass and Shadows (Patreon)
Content
This post features more progress with plants and shadow improvements.
Shadow Acne
Shadow acne is a thorn in every graphics programmers side and is essentially strange shadow artifacts that occur at certain angles and positions. A close-up of yesterdays plants shows this messy grain pattern and bright outline around the leaves:
These artifacts were produced by an algorithm called Receiver Plane Depth Bias, which is used to improve the quality of shadows. I naively implemented this algorithm and it had the opposite effect. I'll need to go back a step and understand the maths properly before trying this again.
I removed this code and the shadows now look much nicer:
Self-Shadowing
Another problem to solve is to ensure objects correctly cast shadows on themselves.
In this previous post I talked about how shadows are computed by rendering the scene from the point of the sun. To convey this better, let's look at this work of art:
We have the sun in the top-right and a tree in front of us. From the sun's point of view, it can't see the ground behind the tree:
To us it's clear where the shadowed area is, but for a computer it doesn't have this information until it looks at the world from the point of view of the sun.
This means the first step is to render the scene from the sun's position, looking down at the world that's in front of the player. If we're looking at a fern in-game, the sun's point of view will look like this:
The reason it's black and white is because we only need to store how far away each pixel is from the sun. The brighter the pixel, the further away it is.
When we render the world from our point of view, every pixel we can see on the screen will map to a pixel in the black-and-white texture above. This means if a pixel is further away than what the sun saw in that black-and-white texture above (for example the ground beneath the fern), then it's shadowed.
However! Since these leaves have no thickness - they are flat rectangles - their top and bottom faces are the same distance to the sun. Does this mean it should always be in sunlight, or always be shadowed?
To solve this problem, I wrote extra shader code that figures out if we're looking at the same side of the fern that the sun can see. If we aren't, then this side of the fern is shadowed.
This works because the ferns are thin rectangles and we can only ever see one side of the same fern at any one time (if you look at it from the side, it's invisible).
Grass
In the first devlog I shared publicly on Patreon, I was rendering grass as individual blades - one triangle per blade. As much as I love Blade, this is not an efficient rendering method (more grass = more triangles = slower rendering).
To render more grass I used the same technique as the ferns - rendering big thin rectangles with a texture on it.
Step 1, big rectangles:
The texture on the ground is not ours - I'm using it as a placeholder
Step 2, flip the fern texture sideways and use it as a grass texture:
Step 3, render a lot of them!
Step 4, add trees back. They don't fit the style anymore, need to work on trees next!
I'm glad I'm starting to better understand the maths behind shadows, rather than just copying and pasting code and mashing it all together. I'm also excited to be trying these texture-styled geometry rendering methods, since they are a popular approach for rendering plants and produce great visuals with little cost.
Thanks for reading, more screenshots and videos are available here.