Batch Rendering in LWJGL3 | Coding a 2D Game Engine in Java #11

Поділитися
Вставка
  • Опубліковано 28 тра 2024
  • Join the Discord: / discord
    I apologize in advance for this lengthy tutorial, unfortunately there is no easy way to create a batched renderer in 20 mintues, so this one is a bit long :)
    In this tutorial, I go over how to create a 2D batched renderer, that is able to render thousands of sprites at 60 FPS. This will increase framerates from 1 FPS, to 60 FPS. What I go over, is how to use the game objects transform to create a set of vertices for every single quad inside the batch renderer, and then upload that vertex buffer to the GPU every frame.
    Then, I go over how to create a Renderer class that finds a RenderBatch that has room for a quad, or creates a new RenderBatch if there is none, and then adds the quad to that RenderBatch. The renderer will also sort the batches and render them to the screen.
    Source Code: github.com/codingminecraft/Ma...
    Supplemental videos
    ===================
    * • Batch Rendering - An I...
    * • Batch Rendering - Colors
    * • Batch Rendering - Text...
    ---------------------------------------------------------------------
    Website: ambrosiogabe.github.io/
    Github: github.com/ambrosiogabe
    Here are some books I recommend if you want to learn about game engine development more thoroughly. I do not profit off any of these sales, these are just some books that have helped me out :)
    My Recommended Game Engine Books:
    Game Engine Architecture: www.gameenginebook.com/
    Game Physics Cookbook (Read this before the next physics book): www.amazon.com/Game-Physics-C...
    Game Physics (Ian Millington): www.amazon.com/Game-Physics-E...
    Game Programming Patterns (Free): gameprogrammingpatterns.com/
    My Recommended Beginning Game Programming Books:
    JavaScript Game Design: www.apress.com/gp/book/978143...
    My Recommended Java Books:
    Data Structures/Algorithms: www.amazon.com/Data-Structure...
    LWJGL (Free, but I haven't read this thoroughly): lwjglgamedev.gitbooks.io/3d-g...
    Outro Music: www.bensound.com/royalty-free...

КОМЕНТАРІ • 100

  • @truemajner
    @truemajner Місяць тому +3

    *For those whose framerate jumps from infinity to 30*
    I had the same problem and I fixed it a day ago. In Time.java, make timeStarted type long not a float. I have a 240 hertz monitor and, probably, the precision of floating point calculations in this case is not enough. You don't need to change others usages of float in your code.

  • @RabeetFatmi
    @RabeetFatmi 4 роки тому +17

    Liked/subbed. Please continue this great series! It complements very well with ThinMatrix series as well.

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +1

      Awesome, thanks Rabeet! And ThinMatrix is a huge inspiration to me, and helped teach me in the beginning. So I'm really glad that these are a good complement to his videos :D

  • @kasperdb
    @kasperdb 3 роки тому +3

    Finished 12 episode in two days, this series is amazing! Thanks man! love

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      That's impressive haha. I'm glad you're liking the series though kappie :D

  • @celinedrules
    @celinedrules 9 місяців тому

    This is crazy awesome. I had to pause the video 1000 times to keep up with you but it's all good. I am converting everything you are doing into C# and surprisingly, this worked on the first try. No errors and no crashes.

  • @Filipkasic
    @Filipkasic 2 роки тому +2

    Previous tutorials clear, this one, no idea whats going on :'D

  • @asherhaun
    @asherhaun 3 роки тому +2

    Thanks for the great tutorial!
    I had a few typos here and there, so I just spent quite some time debugging that, but it finally works!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Nice! I saw your other comment about the progress with the "immediate" mode style graphics API. I'll be checking out your repo again soon to take a look. I'm glad the tutorials are helping you out and you're making some progress :D

    • @asherhaun
      @asherhaun 3 роки тому +1

      Thanks for making them! they were just what I was looking for. I will update the repo soon

  • @hyperocket3279
    @hyperocket3279 3 роки тому +2

    Woah, this gave me a headache. Finally got it working in the end. Was trying to understand everything I could. The one part that left me wondering was the *loadVertextProperties* function in RenderBatch class...more specifically the *xAdd* and *yAdd* variables. I understand what you are trying to do with the variables I just don't get how to it works. Also for anyone who runs in to the dreaded *EXCEPTION_ACCESS_VIOLATION * error, checkout the *start* and *render* functions in RenderBatch class; that was where my problem lied.... took me a hot minute to spot it.

    • @hyperocket3279
      @hyperocket3279 3 роки тому

      Learned a lot!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +3

      Thanks for the comment Hype Rocket! Looking back on this, it probably would have been better to do this in two videos, but what's done is done haha. In terms of the xAdd and yAdd variables, the way those work is basically like this. We are creating a quad, which contains 4 vertices, in the loop it looks like this:
      Iteration 0
      xAdd = 1.0
      yAdd = 1.0
      Iteration 1
      xAdd = 1.0
      yAdd = 0.0
      Iteration 2
      xAdd = 0.0
      yAdd = 0.0
      Iteration 3
      xAdd = 0.0
      yAdd = 1.0
      So what ends up happening is those basically define the 4 corners of the square. I hope that clears things up a bit, if not let me know :)

  • @adrianobonzanigo9253
    @adrianobonzanigo9253 4 роки тому +4

    Damn man, I just finished implementing my batch renderer today ahaha. Nonetheless, this series is literally what I needed, these tutorials are amazing! Good job :D
    By the way, do you have a Discord? =)

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +2

      Nice! I'm glad I got it out in time haha, and thanks for the comment :D Unfortunately I don't have a discord for the channel yet, I still want to wait until it gets a bit bigger before I start adding social media accounts and stuff (which will hopefully be soon) :)

    • @adrianobonzanigo9253
      @adrianobonzanigo9253 4 роки тому +1

      @@GamesWithGabe heyo! Sorry for the late response =). Sure, that's completely understandable. Don't worry, with this kind of video you'll grow in a blink of an eye hehe ;)

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +1

      Haha thanks man!

  • @MajorTom1313
    @MajorTom1313 3 роки тому +4

    I sat myself the goal of following along with 1-2 videos a day. This is the fifth one of today. And i only have one monitor! What a champ i am. Absolutely mental. I am basically Neo taking in 4 martial arts at the same time. I am coming for you Gabe. I'm coming for you!! ;)

  • @immanuelc885
    @immanuelc885 3 роки тому +5

    Oh wow was this hard. I had a bug that would not let me draw anything and I couldn't figure what it what was wrong then I checked my Transform class and I realized I was being an idiot in the init function I was setting position and scale to a Vector2f() instead of the position and scale parameters. I love ur vids and you should have more subs.

    • @immanuelc885
      @immanuelc885 3 роки тому +1

      I got to re watch the video cause the explanation is really fast. I think that you should of made more than one vid on this topic as it takes a long time to make and it is very important.

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@immanuelc885 yea I agree. It's really hard to do videos like this though because you can't really do half of a batched renderer in one episode haha. I tried my best, and hopefully I'll make a better explanation with a future series :)

    • @immanuelc885
      @immanuelc885 3 роки тому

      GamesWithGabe yeas your right I would be weird to make half a batch renderer in one vid

    • @benonardo
      @benonardo 2 роки тому

      Ohhhhhhh, i spent hours on the Transform thing!
      Thanks for the suggestion, i missed it too because it's such a minor thing

    • @waffdev
      @waffdev Рік тому

      thank you SO much, i made the same mistake

  • @voxelrifts
    @voxelrifts 4 роки тому +1

    This is something I was searching for, forever. Thanks! :)
    Edit: Here's a Question, Why do you use Index Buffers? For Rendering Quads, it takes the same amt of memory with and without Index Buffers

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +2

      No problem Nikhil! And I didn't even think about not using index buffers (just because I've always used them), but now that you mention it there really is no reason to use them lol.

    • @voxelrifts
      @voxelrifts 4 роки тому +1

      @@GamesWithGabe That answer was Quick.... :)

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +2

      Haha yea, my response times just depend on when I'm on UA-cam :)

  • @goophermaijenburg370
    @goophermaijenburg370 4 роки тому

    Hi Gabe, awesome series! Could you try to indicate what topic you will cover next? So we/I can read up about the topic in advance?

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey Goopher, thanks for the comment! And I can definitely start to mention what we are going to go over. I will probably try to draw up some sort of roadmap for a few weeks in advance too so that you guys know what's coming. As for the next tutorial, I am planning on releasing one about resource management, specifically about making sure you only ever have one reference to objects like textures and shaders (which you typically don't want to duplicate). I released a video on it for my last series called Asset Pools, but I definitely don't think that's the right term for it lol

  • @oftenyoutuber4348
    @oftenyoutuber4348 Рік тому +2

    There's one difference with my code: I'm using pretty much the same version of IntelliJ IDEA, but I get all these horizontal and vertical lines across MY beautiful rectangle.

    • @ParalyticAngel
      @ParalyticAngel 10 місяців тому

      same here. I've got the latest edition of IntelliJ IDEA instead, but I think it could be because of newer editions of GL. My code generated by the site differs a bit from Gabe's code 3 years ago.^^ Maybe this is the reason. But I think later we will got just same pictures as in the video. Can't believe OpenGL would done a so bad mistake.^^ Let's keep on going and see.^^ And if it is so, we can present Mario with some jail stripes look.^^ xDDDD

    • @marce3893
      @marce3893 4 місяці тому

      same issue here. I've compiled and run Gabe's solution without making any changes to the code.
      I'm using the latest versions of IntelliJ and the libraries.
      will try to figure out what's going on if I got some spare time

    • @marce3893
      @marce3893 4 місяці тому

      ok like somebody else down in the comments wrote, it's the padding attribute for LevelEditorScene causing that.
      I don't understand why Gabe put it there, but either set it to 0 or remove it altogether and the rectangle will display exactly like at the end of the video.

  • @Shadowblitz16
    @Shadowblitz16 3 роки тому +2

    I had to watch this twice because I was setting position and scale to a new vec4f in Transform.init, which made it not draw anything. lol

  • @gower1973
    @gower1973 2 роки тому +1

    My code runs but its at a terrible frame rate 1fps, any idea whats going on?

  • @cirogarcia8958
    @cirogarcia8958 2 роки тому

    This was an amazing video! It helped me understand how stuff is actually rendered onto the screen and how to do so efficiently. I am following this series so I can do simulations with neural networks and so far I love it!
    You explain everything very well and even the hard parts are sort of easy to understand and follow along.
    Apart from that, I have a question. When I run my code, which is practically identical to yours, the FPS count always shows either "Infinity" or 14.9something, even though I set the swapInterval to 1 like in the video. I know that my monitor refreshes 75 times per second, so I would expect something like 35, 75 or 150, but it doesn't come close to it.
    What could be causing that?
    Edit: Nevermind! You answered that question on episode 13! It was the Time.getTime() thing. Everything works now! Thank you!

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому +1

      Hey Ciro, I'm glad you're liking the tutorials so far! And I'm glad you got the bug fixed. I tried to do a visualization with some neural networks I was playing around with a couple of years ago and it was really cool to see the results. Hopefully you'll come up with a cool visualization tool and build some nice AI :)

  • @RileyNiko
    @RileyNiko 2 роки тому

    It looks like a lot more abstraction was added in this episode, its starting to feel like a somewhat understandable engine!
    somewhat. -w-"

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Haha this was definitely a big episode. Once I get batched rendering into any framework that I'm writing it makes life a lot easier :)

  • @matthewe3813
    @matthewe3813 Рік тому +1

    I accidentally left out the single line of code in the Transfrom.init() function and led me to ~1 hour of debugging trying to figure out what happened. This stuff is hard.

  • @Spotyaner
    @Spotyaner 2 роки тому

    I have a very odd mistake that I cant find the root. Whenever I start the programm, only the top left triangle is beeing drawn, BUT if i choose a MAX_BATCH_SIZE of 1 (instead of 1000 or anything else), it works perfectly. I can seem to find my mistake, maybe u have an Idea where it could be?

  • @marioguy119
    @marioguy119 2 роки тому

    Thanks for the tutorials, been learning and enjoying a ton so far! As an aside, on my M1 MacBook Air, setting the render batch to 1 still needed me 13-14 FPS lol, which is pretty impressive all things considered

  • @avinashgupta8955
    @avinashgupta8955 2 місяці тому

    What if my computer's screen resolution is too small and the 600 x 300 quad looks too big on my screen

  • @denvercox7675
    @denvercox7675 3 роки тому

    How would I remove gameobjects?
    when trying to clear a renderbatch, it leaves behind a lot of stuff in the RAM, and over time it gets really hard on the memory, so how would I clear a renderbatch, or remove gameobjects?

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Hey Denver, I go over removing game objects in a later episode, but if you want to completely clear the game object from memory, there's no real easy way to do that in Java since it's garbage collected. You could clear all references to a game object by removing it from the batched renderer and the game objects list (and whatever other systems have a reference to it), then try to force Java's garbage collection to run, but the way the garbage collection works is that it doesn't necessarily run immediately when you tell it to.

    • @denvercox7675
      @denvercox7675 3 роки тому

      @@GamesWithGabe thank you! keep up the great work!

  • @boristheantarcticunicorn8307

    I'm getting a bug where every even number of render batches dont render so I end up getting multiple rectangles instead of the one. Changing the max batch size to 1 makes it so it doesn't render every other sprite which ends up looking like several lines of sprites. Anyone know what can cause an issue like this and how to fix it?

    • @boristheantarcticunicorn8307
      @boristheantarcticunicorn8307 Рік тому

      Found the issue, accidentally typed vaoID instead of vboID inside glBindBuffer inside of render() in the RenderBatch class. Everything seams to work fine now.

  • @anangelsdiaries
    @anangelsdiaries 7 місяців тому

    I honestly didn't understand a thing at the explanation of offsets. Also I am having a weird bug, where instead of displaying one big square, it shows me multiple squares along the diagonal of a bigger square (that bigger square is same color as the background).
    edit: Nvm, I got the offset thing. The bug is still there though.

  • @Killarexe
    @Killarexe 3 роки тому

    You deserve so much sub!
    But I have an issue and my window is totaly blank.
    May be because my screen size is 1680 1050?

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Hey Killar.exe, thanks for the comment! And this could be because of a lot of different things haha. I have a feeling your window size is fine, but I made a couple videos on debugging issues like this, and the best way to solve it is by stepping through your code with a debugger and making sure all the values are correct and everything. You can also reply with a Github link to your code if you want me to take a look :)

    • @Killarexe
      @Killarexe 3 роки тому

      @@GamesWithGabe Hey I finaly found the issue! but thanks for the responce!

    • @Amitkumar-dv1kk
      @Amitkumar-dv1kk 2 роки тому +1

      @@Killarexe what was the issue man, my window is totally blank just like my future.

  • @mwbgeometrydashpcaccount6372
    @mwbgeometrydashpcaccount6372 2 роки тому

    LOL the importing errors in RenderBatch made me like "WHAT THA FRICK IS GOIN ON?"

  • @VoylinsLife
    @VoylinsLife 2 роки тому +2

    When I press play, nothing gets displayed on my screen accept for the background color. Any idea why this may happen?
    Edit: Nevermind I didn't put the correctindex when enabling the vertex attribute array ^^"

    • @kishank593
      @kishank593 2 роки тому

      hi, i'm having the same issue and my indices are correct; any ideas?

    • @VoylinsLife
      @VoylinsLife 2 роки тому

      @@kishank593 Be sure you are enabling the correct arrays and that id's are not overlapping

    • @kishank593
      @kishank593 2 роки тому +1

      @@VoylinsLife I found out what I did wrong: i put the if (!added) condition inside the for loop in the Renderer class. Thanks for your suggestion as well :)

    • @VoylinsLife
      @VoylinsLife 2 роки тому

      @@kishank593 hahah welcome to the world of programming where 10% is programming and 90% is troubleshooting haha
      I'm happy you found what was wrong 😉

    • @kishank593
      @kishank593 2 роки тому +1

      @@VoylinsLife haha thanks :D

  • @Destroyer19941995
    @Destroyer19941995 2 роки тому

    The shorter version of GenerateIndices:
    //6 indices per quad (3 per triangle)
    int[] elements = new int[6 * maxBatchSize];
    int offset = 0;
    for(int i = 0; i < maxBatchSize; i += 6){
    elements[i] = offset;
    elements[i + 1] = offset + 1;
    elements[i + 2] = offset + 2;
    elements[i + 3] = offset + 2;
    elements[i + 4] = offset + 3;
    elements[i + 5] = offset;
    offset += 4;
    }
    return elements;

  • @oktavianofahdisyaputra1593
    @oktavianofahdisyaputra1593 3 роки тому +4

    i have followed exactly but the result only showing white screen

    • @prodigylock422
      @prodigylock422 2 роки тому

      Found any fixes yet
      I have the same problem

    • @kishank593
      @kishank593 2 роки тому

      yep same problem as well. any solutions yet?

    • @prodigylock422
      @prodigylock422 2 роки тому

      @@kishank593 i doubt you’ll have this but maybe someone has some use for this
      I was uploading a “uProjections” matrix but in the shader was using a “uProjection” matrix
      So it was null so it made evey pixel null
      Hope this helps someone

    • @kishank593
      @kishank593 2 роки тому

      @@prodigylock422 I found out what I did wrong: i put the if (!added) condition inside the for loop in the Renderer class. Thanks for your suggestion as well :)

  • @lastyhopper2792
    @lastyhopper2792 Рік тому

    I manage to separate that square into lines by mistyping "+" as "*" lol

  • @ShyneeYT
    @ShyneeYT Рік тому +1

    My FPS switches betwwen 29 and Infinity. Like it literally just says the word infinity. Is this normal?

    • @TheBritishBoyle
      @TheBritishBoyle Рік тому

      Did you ever figure out why this was happening?

    • @celinedrules
      @celinedrules 9 місяців тому

      I had this problem too. I solved it by replacing any calls to Time.getTime() with glfwGetTime()

    • @sosscs
      @sosscs 6 місяців тому

      same problem, any idea how to fix it?

    • @bencollier3758
      @bencollier3758 4 місяці тому

      @@sosscs Same here - I tried increasing the precision of the variable to no avail, but my guess is that it's got something to do with the precision of the machine's clock. I'm using a MacBook Pro, in case that's true for you too. Essentially it's working, but on half of those loops, the clock can't even tell that time has passed, so you get a divide by zero error.

    • @truemajner
      @truemajner Місяць тому

      Maybe I am later but I had the same issue and fixed it a day ago. In Time.java make timeStarted long, not float. I have a 240 hertz monitor and, probably, the accuracy of float calculations is not enough in this case. You don't have to change the rest of the float

  • @atlasua2021
    @atlasua2021 3 роки тому

    What is the music?

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +1

      Hey Atlas, it's called 'After All' by Geographer. It's in UA-cam Studio's Music Library, but I can't seem to find it on the channel they have a link to

    • @atlasua2021
      @atlasua2021 3 роки тому

      @@GamesWithGabe Hi, thanks!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@atlasua2021 No problem!

  • @calvinwithun6512
    @calvinwithun6512 3 місяці тому

    Aw geez, I am getting 1FPS with the 1000 max batch size at the veryt end of the video... welp, time to go through to see where I missed something... wish me luck haha

    • @calvinwithun6512
      @calvinwithun6512 3 місяці тому

      Aha fixed it. I was flat-out missing two lines of code... one of which being the Renderer.add() method's "added" variable being set to true... which is sort of the whole point of this video... the other being the last line in the RenderBatch.loadVertexProperties method which increments the "offset" variable in the for loop.

  • @ronantremoureux3743
    @ronantremoureux3743 Рік тому

    ahah, was runing at 1 fps because of prints in the console spamming.. i searched my error in the whole project

  • @1pseudocidal
    @1pseudocidal 3 роки тому

    My batch image looks like a field of dots with a lot of white space between each dot. The color gradient is present, and it's a rectangle at the bottom left of a white field, like yours, but it's more akin to the background in your intro to this video than the example shown at the end. Any idea what might be causing this? I'm beginning to think it might be a hardware issue for me. I'm going to try running it on a different machine to see if it's the same there, but that will take me a few days since my other machine is not set up right now. here's a link to my repo if you wanted to take a look: gitlab.com/GRobinson3/wheel-of-fate

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Hey @1pseudocidal, I'm not sure if this might be the problem, but it looks like in your render batch you define position as being two floats, but in your shader default.glsl you define position as a vec3. So that could make it render something really weird, try changing the shader to a vec2 and let me know if this helps at all :)

    • @1pseudocidal
      @1pseudocidal 3 роки тому

      @@GamesWithGabe using a vec3 seems to enable line 14 in default.glsl. It's also what's shown in your video around the 42 minute mark

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@1pseudocidal You are right and that was an error on my part, I can't believe I didn't even notice that til now haha.
      I think I fix this bug on accident in a future video, but you can see that it's wrong in my video because the square should be a reddish-yellow color and instead my square is a bluish-pink color. And if you change that line it will raise an error on line 14 because you're trying to make a vec4 using a vec2 and 1 other number. So if you changed line 14 to vec4(aPos, 1.0, 1.0) you should be good. I have a feeling this won't solve your problem though. I'll try and download your repository a bit later tonight and see if I can replicate what you're getting, and then I'll respond to this and let you know what I find

    • @1pseudocidal
      @1pseudocidal 3 роки тому

      @@GamesWithGabe After making this change and completing part #13, I now have no box :( I pushed my latest up. I'll look at it in the meantime and see if I can retrace my steps.

    • @1pseudocidal
      @1pseudocidal 3 роки тому

      @@GamesWithGabe So, it looks like it doesn't like something about my fragment shader. I did some debugging and found that it fails to compile the fragment from default.glsl in the Shader class, then fails to link (presumably because it couldn't compile in the previous step). This is the error: "ERROR: Fragment shader compile failed
      0:8(19): error: syntax error, unexpected NEW_IDENTIFIER, expecting '{'
      ERROR: Shader linking failed
      error: linking with uncompiled/unspecialized shader"

  • @luandkg
    @luandkg 4 роки тому +1

    It's very hard ! 😞😞😞

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +1

      Haha yea, I know. This one is a hard topic to cover. I was thinking about doing it in several parts (which probably would have been smarter), I have some reference tutorials in the description. The first link in particular gives a great explanation from TheCherno. Hopefully I can clear it up a little more in future tutorials as well though :)

    • @luandkg
      @luandkg 4 роки тому

      @@GamesWithGabe It's hard but i loved !

  • @fsgrggr5943
    @fsgrggr5943 7 місяців тому

    This one was a little fast...

  • @Live4G4ming
    @Live4G4ming 3 роки тому

    hey hows it going Gabe, I just finished doing the batch rendering and I got this imgur.com/a/wCs8dfl I'm not sure if its wrong or if I missed something

    • @Live4G4ming
      @Live4G4ming 3 роки тому

      never mind i fixed it, I had my float padding = 3; when it shoulda been 0

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@Live4G4ming awesome I'm glad you got it solved! I was going to say it looked right too haha

  • @Ihavetoreturnsomevideotapes
    @Ihavetoreturnsomevideotapes 10 місяців тому

    Am having a headache 🤕

  • @liamandersson5462
    @liamandersson5462 2 роки тому

    DO NOT USE A METHOD IN TRANSFORM! This is not OOP standard! You should use this() command instead.