Often in game engines is used an
approach when grass type (geometry or texture type) is chosen based on the
landscape type. For example on the road we don’t want any grass at all because
they can’t grow there, but for meadow we want a lot of very dense grass. This
can be achieved with grass masking, but often we need not only binary value
about need we grass or not but some variations. Another example grass with
different textures to make grass and landscape belong each other. For this case
we also need grass masking texture with values which indicate the kind of grass.
This technique is not a new and it has been widely used for a long time in
industry, but often we can see intersection between grass geometry and
landscape geometry (look at the images below) even when we implemented this
technique. This may happen when grass masking texture is not big enough or when
grass geometry is relatively big (for choosing flora type we use only central
point of this geometry, but geometry may be big enough to overlap neighborhoods
areas with different materials) or when we have landscape with very rapid
environment type transition. This issue happens always but in one games this is
not a big issue and in another may make the final picture unbalanced.
Here I try to explain how we can
achieve this picture with relatively small performance overhead.
As always the main idea is very
simple. To make grass and landscape belong each other what we need to do is tint
grass with the landscape color in the bottom-up direction. There are different
methods for doing this (I know at least three) but the common stuff in all of
them is access a texture which represents a color of the ground under the grass.
Means we have to prepare this specific texture before we start grass rendering.
Ok let’s imagine that we have
this texture before grass drawing. What we need to do with it.
Look at the image here on the
left I drew typical flora geometry (a quad) which consist of two triangles (front
view). Red points represent bottom vertices of the flora, blue points up
vertices. On the right is flora geometry (side view) with the different slope
against the landscape. For each vertex of the grass geometry we need to add an
additional attribute with represents tint position (in object space) and the
blend factor for doing right tinting (in the simplest case for bottom vertices
it will be 1.0f and for the up vertices 0.0f).
Now I shortly explain each of
these three techniques:
- For each grass chunk you have to find landscape textures under it. If you landscape uses blend textures for correct blending different layer’s textures you have to do the same calculation of the final color in the grass pixels shader. Yes, this may be expensive task. So think twice before doing it.
- Render landscape and all needed for grass coloring stuff into the texture with camera looking top-down and with orthogonal projection. Then use this texture in the grass pixel shader. This may me less expensive on the CPU side, but may introduce some artifacts. (of course it very depends on the engine capabilities)
- Do grass rendering as the last part of the rendering. Make copy of the already filled back-buffer. Then use this back-buffer copy as a texture for coloring in the grass pixel shader.
I prefer the third method because
of its simplicity and efficiency on both CPU and GPU sides. In the vertex
shader we calculate clips space position of the tint position and in the pixels
shader we just sample back buffer with these calculated coordinates then we
blend grass color with this sampled color by the tint blend factor. It’s very
simple and efficient. And we don't have any additional work on the CPU side except that we need to send into the pixel shader back-buffer copy.
Someone may ask why not just
blend grass color with the back-buffer color with standard hardware blending.
The answer is simple because it’s not right if you will try to look through the
flora you will notice that we blend bottom part of the grass with incorrect
color because it may be located far away from the bottom part of the grass
itself.
No comments:
Post a Comment