Monday, February 13, 2012

Virtual Texturing. Rage.

    Id Software and John Carmack have created a really new way in using unlimited textures in CG, but they hasted for year or two because current generation of graphics hardware have not enough on chip memory to make use VT approach well. Stop! Why we need lots of on chip video memory? The main idea of VT is to minimize requirements for video memory by providing ability to use a magnitude more textures than before. Lets try understand why it's so.
    In theory VT always consumes constant memory footprint, more over ideally when other sub-systems parameters like hard drive and memory latency and bandwidth will be very well, VT needs only additional texture with dimension equal to the back buffer size. But current (and future also) generation of hardware is not ideal and has limitations, so VT needs overcome them by using page (tile) of pixels instead of single pixel to minimize latency and using indirection table to access the right page. VT is very similar in base idea to the virtual memory system for operating systems. That all makes VT using much more bigger texture (even textures) which is usually 4-16 times bigger than the initial theoretical assumption.
    I'm lucky to have Nvidia 590 GTX graphics card (with 3Gb of video memory) on my work and as a real passion graphics programmer the first thing what I did was run Rage and change size of the page table from 4k to 16k. And guess what? the bothering texture popping has gone. Now I don't see any texture loading and switching between fallback texture to needed LOD at all. That is why I said that Carmack  hasted  for year or two. Currently 590 GTX is high-end graphics card with the price about 800$, but over the year it'll be usual middle-end video card.
     P.S. Anyone who is interesting in virtual texturing technique (theory and implementation) I'm very recommending this blog http://sandervanrossen.blogspot.com/

Friday, February 3, 2012

Grass coloring(tinting).

    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.