How Do Games Render So Much Grass?

00:15:52
https://www.youtube.com/watch?v=Y0Ko0kvwfgA

Summary

TLDRIn diesem Video wird die Bedeutung von Gras in Videospielen und die Techniken zu dessen Rendering untersucht. Der Sprecher erläutert Billboarding und GPU-Instancing, um große Mengen Gras effizient zu erzeugen. Compute-Shader werden verwendet, um die Positionen des Grases direkt im GPU-Speicher zu berechnen, wodurch die CPU-Last reduziert wird. Zudem werden Variationen in der Höhe und Animation des Grases besprochen, um ein realistisches Aussehen zu erzielen. Schließlich werden Optimierungstechniken und die Herausforderungen von Billboard-Gras thematisiert, während auf zukünftige Video-Themen hingewiesen wird.

Takeaways

  • 🌱 Gras ist entscheidend für realistische Umgebungen in Spielen.
  • 💻 GPU-Instancing verbessert die Rendering-Leistung erheblich.
  • 📏 Billboarding nutzt Texturen zur Darstellung von Gras.
  • 🖼️ Texturvielfalt ist entscheidend für die visuelle Attraktivität.
  • 📊 Compute-Shader laden Graspositionen effizient auf die GPU.
  • 🌍 Höhenvariationen sorgen für ein natürlicheres Aussehen.
  • 💨 Animation des Grases erfolgt durch Trigonometrie im Vertex-Shader.
  • ⚙️ Optimierungen wie Level-of-Detail-Culling steigern die Effizienz.
  • 👉 Probleme der billboard-Technik werden angesprochen.
  • 🎨 Zukünftige Videos werden sich mit 3D-Modellierung und Post-Processing beschäftigen.

Timeline

  • 00:00:00 - 00:05:00

    Im ersten Abschnitt wird die Bedeutung von Gras in Videospielen besprochen. Es wird erklärt, dass zu wenig oder zu viel Gras die Atmosphäre eines Spiels beeinträchtigen kann. Eine der Lösungen ist die Verwendung effizienter Render-Techniken, die eine hohe Anzahl an Gras-Objekten ermöglichen, ohne die Leistung des Spiels zu beeinträchtigen. Es wird auf die Verwendung von Billboard-Gras hingewiesen, das aus zwei-Dimensionalen Objekten besteht, die mit einer Grastextur belegt sind. Die Technik zur Erstellung dieser Grasobjekte und deren Anordnung wird ebenfalls erläutert.

  • 00:05:00 - 00:10:00

    Im zweiten Abschnitt wird erläutert, wie die Positionen der Grasobjekte mithilfe eines Compute Shaders berechnet werden. Es wird erklärt, dass durch GPU Instancing die Daten auf der GPU bleiben können, was die Leistung erheblich verbessert. Die Berechnung und Anordnung der Grasobjekte sowie die Verwendung von verschiedenen Berechnungen zur Verdopplung der Dichte der Grasobjekte werden behandelt. Diese Techniken ermöglichen eine flüssige Rendering-Leistung von bis zu 500 fps bei einer großen Anzahl von Objekten.

  • 00:10:00 - 00:15:52

    Im letzten Abschnitt wird die Einführung von Variationen in die Grasanimation und -färbung angesprochen. Werden Größenvariationen definiert, um ein realistisches Aussehen zu erreichen und die allgemeine Vielfalt zu erhöhen. Zudem wird die Bedeutung von Optimierungstechniken wie Level of Detail und Reduzierung von Shader-Anweisungen hervorgehoben, um die Leistung zu verbessern. Es wird auch auf die Nachteile von Billboard-Gras hingewiesen und angekündigt, dass künftige Videos 3D-Modellierungstechniken zur Verbesserung der Qualität des Grases behandeln werden.

Mind Map

Video Q&A

  • Was ist Billboarding im Kontext des Gras-renderings?

    Billboarding ist eine Technik, bei der Gras aus zwei sich kreuzenden Quads besteht, die eine Textur verwenden.

  • Was bedeutet GPU-Instancing?

    GPU-Instancing ermöglicht es, viele Objekte (wie Gras) effizient zu rendern, indem Daten auf der GPU gespeichert werden und nicht bei jedem Frame vom CPU übertragen werden müssen.

  • Wie wird die Animation des Grases gestaltet?

    Die Animation wird im Vertex-Shader durchgeführt, indem trigonometrische Funktionen verwendet werden, um ein wogendes Verhalten zu simulieren.

  • Was sind die Herausforderungen beim Rendering von Gras?

    Eine der Herausforderungen ist die Optik von oben, da Billboard-Gras von oben betrachtet unnatürlich aussehen kann.

  • Welche Optimierungstechniken werden für das Gras-rendering vorgeschlagen?

    Optimierungen umfassen Level-of-Detail-Culling, Reduzierung der Tesselation des Geländes und Minimierung der Shader-Anweisungen.

  • Welche Rolle spielt die Textur im Gras-rendering?

    Die Textur ist entscheidend, da sie das Aussehen des Grases bestimmt und seine visuelle Vielfalt schafft.

  • Wie wird die Höhe des Grases variiert?

    Die Höhe wird mit Simplex Noise variiert, um eine natürliche Verteilung von hohen und niedrigen Grashalmen zu erreichen.

  • Was ist der Zweck des Videos?

    Das Video erklärt die Techniken und Herausforderungen beim Rendern von Gras in Videospielen und bietet Einblicke in optimierte Ansätze.

  • Wo kann ich den Quellcode des Projekts finden?

    Der Quellcode ist in der Beschreibung des Videos verlinkt.

  • Wann sind die Livestreams des Sprechers?

    Die Livestreams finden montags um 17 Uhr PST statt.

View more video summaries

Get instant access to free YouTube video summaries powered by AI!
Subtitles
en
Auto Scroll:
  • 00:00:03
    fellas welcome to a new video or not a
  • 00:00:06
    new video if you're watching this in the
  • 00:00:08
    future today we're talking about grass
  • 00:00:11
    and video games grass is pretty
  • 00:00:13
    important when it's present in a scene
  • 00:00:16
    you might not notice it but when it's
  • 00:00:18
    not present the environment just doesn't
  • 00:00:20
    feel right the catch here though is that
  • 00:00:22
    when there's not enough grass it feels
  • 00:00:25
    just as weird and the grass stands out
  • 00:00:28
    the solution to this of course though
  • 00:00:30
    is to just put more grass in
  • 00:00:33
    as we've discussed in previous videos
  • 00:00:35
    though having a lot of one thing can be
  • 00:00:37
    quite expensive and heavily affect the
  • 00:00:39
    performance of our video game so how do
  • 00:00:42
    games render so much grass while still
  • 00:00:45
    having more than one frame per second
  • 00:00:47
    there's plenty of techniques for grass
  • 00:00:49
    rendering several of which we can just
  • 00:00:51
    throw into the trash as they are
  • 00:00:53
    unacceptably bad one of these techniques
  • 00:00:56
    in particular though has been tried and
  • 00:00:58
    true for decades
  • 00:01:00
    which i use to turn this vacant plane
  • 00:01:03
    into a dense field of grass you may not
  • 00:01:05
    believe me right now but this is 1.2
  • 00:01:08
    million animated grass meshes rendered
  • 00:01:11
    at 500 frames per second and now you may
  • 00:01:14
    be asking yourself what's the technique
  • 00:01:17
    acerola well stay tuned to find out
  • 00:01:37
    to set the scene i have here in unity a
  • 00:01:39
    silly little 300 by 300 meter plane that
  • 00:01:42
    has its vertices displaced by a height
  • 00:01:45
    map this is the plane that we'll be
  • 00:01:47
    placing our grass on i also have a
  • 00:01:50
    little cube that functions as a player
  • 00:01:52
    model reference
  • 00:01:54
    usually when you're getting started on a
  • 00:01:56
    project it's hard to find a good
  • 00:01:58
    starting point but with this it's pretty
  • 00:02:00
    obvious in order to render grass you
  • 00:02:03
    need grass to render the different grass
  • 00:02:05
    rendering techniques i mentioned earlier
  • 00:02:08
    are what determines what our grass model
  • 00:02:10
    will look like let's start with an
  • 00:02:12
    example
  • 00:02:13
    take a look at this screenshot from
  • 00:02:15
    final fantasy 14 specifically the grass
  • 00:02:19
    here now if you look closely if you
  • 00:02:21
    really really analyze it you may notice
  • 00:02:25
    that it's not a 3d model at all and is
  • 00:02:28
    actually just an image
  • 00:02:36
    that's right this grass is in fact two
  • 00:02:39
    triangles that form a quad that samples
  • 00:02:42
    a grass texture
  • 00:02:43
    this general technique is called
  • 00:02:45
    billboarding and billboard grass is the
  • 00:02:48
    technique i'll be going over billboard
  • 00:02:51
    grass is commonly composed of multiple
  • 00:02:53
    intersecting quads for my project i
  • 00:02:56
    decided to use three
  • 00:02:58
    now with this technique the texture does
  • 00:03:01
    all the work so you need a good grass
  • 00:03:03
    image texture i decided to paint my own
  • 00:03:06
    but i've never made a texture before
  • 00:03:08
    like this so please don't laugh at me it
  • 00:03:10
    looks like this and when we apply it to
  • 00:03:13
    our billboard grass model the grass
  • 00:03:15
    really comes together
  • 00:03:17
    with our grass model complete we need to
  • 00:03:19
    actually place it all over the plane so
  • 00:03:22
    to simplify this let's flatten our plane
  • 00:03:24
    first it's going to take a lot of grass
  • 00:03:27
    to cover this entire plane much more
  • 00:03:30
    grass than the cpu can actually handle
  • 00:03:33
    so we're going to use a very handy dandy
  • 00:03:35
    method called
  • 00:03:39
    normally in a given scene the cpu takes
  • 00:03:43
    all the object mesh data that exists and
  • 00:03:45
    shoves it into this big old funnel that
  • 00:03:47
    gets processed by the gpu this mesh data
  • 00:03:51
    gets copied from the cpu to the gpu
  • 00:03:54
    every single frame
  • 00:03:56
    this is the biggest bottleneck of all
  • 00:03:58
    graphics programming because
  • 00:03:59
    communicating data is really costly we
  • 00:04:03
    want to render hundreds of thousands of
  • 00:04:05
    grass objects so obviously pushing
  • 00:04:08
    millions of vertices into that gpu
  • 00:04:10
    funnel is going to clog it up
  • 00:04:12
    what if we could conveniently
  • 00:04:15
    keep that data on the gpu so we don't
  • 00:04:17
    need to copy it over every single frame
  • 00:04:21
    we could create this massive buffer of
  • 00:04:23
    grass positions and then ask the gpu to
  • 00:04:26
    use that buffer to find the proper grass
  • 00:04:28
    position each frame rather than having
  • 00:04:31
    the cpu copy each individual grass's
  • 00:04:34
    position over
  • 00:04:36
    this technique is called gpu instancing
  • 00:04:39
    and it's perfect for stuff like grass as
  • 00:04:41
    it doesn't need to exist on the cpu side
  • 00:04:44
    which is the biggest downside of gpu
  • 00:04:46
    instancing anything instantiated by the
  • 00:04:49
    gpu itself doesn't technically exist as
  • 00:04:53
    far as the cpu is aware
  • 00:04:55
    before we do any gpu instancing though
  • 00:04:57
    we need to calculate some grass
  • 00:04:59
    positions we are going to calculate the
  • 00:05:01
    positions with a compute shader so that
  • 00:05:04
    the positions of the grass will go
  • 00:05:05
    directly into the gpu buffer and the cpu
  • 00:05:09
    doesn't need to do any copying at all
  • 00:05:12
    the positions we are creating will fill
  • 00:05:14
    a square space of whatever size we'd
  • 00:05:16
    like for example 300 for our 300 by 300
  • 00:05:20
    meter plane
  • 00:05:22
    we take the thread id of our compute
  • 00:05:24
    shader thread which will be in the range
  • 00:05:26
    0 to 300 for both axes then we subtract
  • 00:05:30
    150 so it centers it over the origin and
  • 00:05:34
    that's about it with these positions
  • 00:05:36
    generated we can tell the gpu to
  • 00:05:38
    instantiate our grass our billboard
  • 00:05:41
    grass we made earlier is composed of
  • 00:05:43
    three meshes so this will result in
  • 00:05:46
    three separate instancing calls taking a
  • 00:05:48
    look back at our plane there's now one
  • 00:05:51
    grass object every meter which is great
  • 00:05:54
    unfortunately it doesn't look quite
  • 00:05:56
    dense enough so let's double the amount
  • 00:05:58
    of grass objects this is attainable by
  • 00:06:01
    multiplying that position we calculated
  • 00:06:03
    earlier by 1 over whatever density we
  • 00:06:06
    want currently that's two so we multiply
  • 00:06:09
    the position by one half
  • 00:06:11
    this grass density looks nice to me so i
  • 00:06:14
    won't make my gpu suffer any more than
  • 00:06:16
    it already is
  • 00:06:18
    to put this all into perspective we are
  • 00:06:20
    rendering two grass objects per meter
  • 00:06:23
    each grass object is three quads which
  • 00:06:26
    is 12 vertices and six triangles per
  • 00:06:29
    grass object and there's 300 meters
  • 00:06:32
    squared this means that we are drawing
  • 00:06:35
    um
  • 00:06:37
    2 million 160 000 triangles every frame
  • 00:06:41
    just for the grass and currently we have
  • 00:06:44
    an average frame rate of 500 fps this
  • 00:06:47
    would not be possible at all without the
  • 00:06:50
    gpu instancing
  • 00:06:54
    alright cool we have grass it all looks
  • 00:06:57
    the same though and that's boring also
  • 00:07:00
    unrealistic but that matters to me less
  • 00:07:03
    this is the part of the video where i
  • 00:07:04
    remind everyone that i am a technical
  • 00:07:07
    artist
  • 00:07:15
    [Music]
  • 00:07:19
    the first thing i did was add some
  • 00:07:21
    variance to the positions of the grass
  • 00:07:23
    it's hard to see but it removes the
  • 00:07:25
    uniformity of the positions next i added
  • 00:07:28
    variance to the height of the grass with
  • 00:07:30
    simplex noise so that height variance is
  • 00:07:33
    clumped together meaning that higher
  • 00:07:36
    grass will be grouped with higher grass
  • 00:07:38
    and so on like in real life
  • 00:07:43
    that's about all for variants of the
  • 00:07:45
    grass model there's not much else to do
  • 00:07:47
    and i think it already improves the
  • 00:07:49
    visual is a good deal
  • 00:07:52
    [Music]
  • 00:07:55
    now comes the hard part and that's
  • 00:07:57
    animation grass is long and thin thus it
  • 00:08:01
    is susceptible to wind and it flows back
  • 00:08:04
    and forth with it
  • 00:08:05
    obviously we aren't going to simulate
  • 00:08:07
    wind we're just going to fake it
  • 00:08:10
    animation in this context is going to
  • 00:08:12
    happen in the vertex shader this is the
  • 00:08:15
    stage of the rendering pipeline that
  • 00:08:17
    finalizes vertex positions so i can have
  • 00:08:20
    the gpu modify vertices positions of a
  • 00:08:22
    model however i please we have a bit of
  • 00:08:26
    a problem though and that's that this
  • 00:08:28
    grass model only has four vertices to
  • 00:08:30
    work with that's not a lot even worse we
  • 00:08:34
    don't even have four to work with since
  • 00:08:36
    the bottom two remain stationary and
  • 00:08:39
    only the top two are gonna move the
  • 00:08:41
    basic idea here is that we're going to
  • 00:08:43
    skew the grass back and forth to make it
  • 00:08:46
    look like it's being blown around
  • 00:08:48
    luckily math provides us with
  • 00:08:50
    oscillators in the form of trig
  • 00:08:52
    functions so by using a mess of trig
  • 00:08:54
    values and random numbers we end up with
  • 00:08:57
    an animation that looks like so
  • 00:09:12
    how cool and calming i'm quite proud of
  • 00:09:15
    it wait what's that you actually want to
  • 00:09:18
    know how the animation works
  • 00:09:21
    okay
  • 00:09:22
    to begin we hash the instance id of the
  • 00:09:24
    grass object to get a random number
  • 00:09:25
    unique to an individual object then if
  • 00:09:27
    that hash value is above a certain
  • 00:09:28
    threshold we compute the cosine value
  • 00:09:30
    with a slightly faster frequency
  • 00:09:31
    otherwise we compute the default cosine
  • 00:09:32
    value with a parameterized frequency
  • 00:09:34
    this frequency on grass that is taller
  • 00:09:36
    since taller grass would realistically
  • 00:09:37
    take longer to swing back and forth next
  • 00:09:38
    we square the cosine wave reduce its
  • 00:09:40
    amplitude then subtract from it based on
  • 00:09:41
    the id hash to add local variance to the
  • 00:09:43
    cosine value and then we reduce the
  • 00:09:45
    amplitude even further amplitude in this
  • 00:09:46
    context refers to the distance that the
  • 00:09:48
    grass object will sway from its original
  • 00:09:49
    position finally we add this value to
  • 00:09:51
    the local position of our top side
  • 00:09:52
    vertices scaled by the hash id for
  • 00:09:53
    further localized variants and also the
  • 00:09:55
    height variance of the grass since
  • 00:09:56
    taller grass will sway further than the
  • 00:09:57
    shorter grass this animation obviously
  • 00:09:59
    isn't perfect but it is much cheaper
  • 00:10:00
    computationally than a full-on physics
  • 00:10:02
    simulation of wind also that simulation
  • 00:10:03
    isn't even realistically possible since
  • 00:10:04
    none of this grass data exists on the
  • 00:10:06
    cpu
  • 00:10:09
    if you recall from the beginning this
  • 00:10:11
    plane that we're rendering the grass on
  • 00:10:13
    top of has its vertices displaced the
  • 00:10:16
    grass doesn't move with it yet which is
  • 00:10:18
    a problem
  • 00:10:20
    this involves converting the world space
  • 00:10:22
    coordinates of our grass to uv
  • 00:10:24
    coordinates such that they can sample
  • 00:10:26
    the same height map as the terrain mesh
  • 00:10:28
    and now our grass properly displaces
  • 00:10:32
    along with the terrain our grass looks
  • 00:10:34
    more natural now and is largely complete
  • 00:10:37
    as an asset but i had one last idea the
  • 00:10:41
    color of our grass is uncomfortably
  • 00:10:43
    homogeneous it's boring to look at i
  • 00:10:46
    thought about this for a good while and
  • 00:10:48
    i came up with several different ideas
  • 00:10:50
    most of which i streamed live on twitch
  • 00:10:52
    at twitch.tv forward slash acerola
  • 00:10:55
    underscore t
  • 00:10:56
    link in the description streams on
  • 00:10:58
    monday at 5 pm pst
  • 00:11:01
    the dilemma though is that i wanted to
  • 00:11:03
    visualize both old and young grass the
  • 00:11:06
    older grass is more yellow while the
  • 00:11:08
    younger grass is more green or in our
  • 00:11:11
    case it's closer to the default color of
  • 00:11:14
    our texture how do we know though if
  • 00:11:16
    grass is old or not
  • 00:11:18
    taller grass is older than younger grass
  • 00:11:21
    so we can use our height modifier we
  • 00:11:23
    were using to cause height variance to
  • 00:11:25
    also calculate a new value that will
  • 00:11:27
    control how yellow the grass turns
  • 00:11:30
    with this value we also use the vertical
  • 00:11:33
    uv coordinates to interpolate the
  • 00:11:35
    strength of this value as the grass
  • 00:11:38
    pixels increase in height which will
  • 00:11:40
    cause only the tips of the grass to
  • 00:11:42
    become very yellow
  • 00:11:44
    with this effect applied i think it all
  • 00:11:46
    comes together in terms of visuals so
  • 00:11:49
    please let me know what you think about
  • 00:11:50
    it
  • 00:11:53
    alright
  • 00:11:54
    the performance of our grass is already
  • 00:11:56
    pretty good and in the real world you
  • 00:11:58
    would never instantiate this much grass
  • 00:12:01
    across such a large area anyways so the
  • 00:12:03
    grass would be even faster in that real
  • 00:12:06
    world scenario this is nerd so if
  • 00:12:09
    you don't care please skip ahead to the
  • 00:12:11
    conclusion uh oh disclaimer i'm about to
  • 00:12:15
    talk about something i've explained in
  • 00:12:17
    depth in my previous video dynamic
  • 00:12:20
    detail in video games please go watch it
  • 00:12:23
    now before continuing
  • 00:12:25
    wait what's that you don't want to watch
  • 00:12:27
    it okay well here's a quick recap
  • 00:12:36
    the easiest optimizations to be made
  • 00:12:38
    involve level of detail we can cull
  • 00:12:41
    grass in the vertex shader in the same
  • 00:12:43
    way we call triangles in the geometry
  • 00:12:46
    shader in that level of detail video by
  • 00:12:49
    checking if a grass vertex is outside
  • 00:12:51
    the view of the camera or is a certain
  • 00:12:54
    distance from the camera
  • 00:12:56
    this improves our performance a great
  • 00:12:58
    deal when we are looking away from all
  • 00:13:00
    the grass
  • 00:13:03
    as well as allowing custom distance
  • 00:13:05
    based level of detail cooling as
  • 00:13:07
    demonstrated here
  • 00:13:09
    another optimization involves reducing
  • 00:13:12
    the amount of tessellation that is
  • 00:13:14
    happening on our terrain in fact it
  • 00:13:16
    doesn't need to be tessellated at all
  • 00:13:18
    since the grass completely obscures it
  • 00:13:21
    this increases our fps a great deal
  • 00:13:24
    the last optimization that i can
  • 00:13:26
    confidently talk about is reducing the
  • 00:13:29
    amount of instructions in our vertex and
  • 00:13:31
    fragment shaders when we are
  • 00:13:33
    instantiating this many meshes even just
  • 00:13:36
    one instruction can scale considerably
  • 00:13:39
    in cost using numbers from earlier we
  • 00:13:42
    are rendering two million one hundred
  • 00:13:44
    and sixty thousand triangles which is
  • 00:13:47
    four million three hundred and twenty
  • 00:13:48
    thousand vertices meaning our vertex
  • 00:13:51
    shader executes that many times per
  • 00:13:53
    frame our fragment shader executes even
  • 00:13:56
    more than that by reducing the
  • 00:13:58
    complexity of our vertex shader
  • 00:14:00
    animation we can improve the performance
  • 00:14:03
    of the grass little by little
  • 00:14:07
    overall billboard grass is an incredibly
  • 00:14:10
    performant and fast option for rendering
  • 00:14:12
    foliage there's a reason it shows up
  • 00:14:14
    literally everywhere and i promise that
  • 00:14:17
    if you look for it you'll see it in
  • 00:14:18
    nearly every game that you play
  • 00:14:21
    but it has one major problem and that's
  • 00:14:23
    if you look down on the grass from above
  • 00:14:26
    it looks like
  • 00:14:27
    this isn't actually a problem if your
  • 00:14:29
    game has a fixed camera angle like age
  • 00:14:32
    of empires 4 that's a recent example
  • 00:14:34
    that uses this technique i'm pretty sure
  • 00:14:37
    but anyways this is a problem that
  • 00:14:40
    modern foliage rendering techniques seek
  • 00:14:42
    to solve with more geometry at the
  • 00:14:45
    expense of performance in my next video
  • 00:14:48
    i'll be trying my hand at 3d modeling
  • 00:14:50
    some foliage to improve the overall
  • 00:14:52
    appearance of this grass and remove this
  • 00:14:55
    issue that my billboard grass has the
  • 00:14:58
    appearance of the grass could also be
  • 00:15:00
    significantly improved with simple
  • 00:15:02
    post-processing effects so please look
  • 00:15:04
    forward to videos on that as well
  • 00:15:07
    if you'd like to check out the code for
  • 00:15:08
    this project there's a link in the
  • 00:15:10
    description and if you liked this video
  • 00:15:12
    i'd appreciate if you subscribed and
  • 00:15:14
    left a comment it means a lot but i've
  • 00:15:17
    got to go now have a great rest of your
  • 00:15:19
    day and i'll see you next time
  • 00:15:51
    you
Tags
  • Videospiele
  • Grafikdesign
  • Rendering-Techniken
  • Billboarding
  • GPU-Instancing
  • Optimierungen
  • Animation
  • Texturen
  • Computerspiele
  • Entwicklung