Sprite Batching In OpenGL (Uniform Buffer Objects) // OpenGL Tutorial #33

  Рет қаралды 8,468

OGLDEV

OGLDEV

Күн бұрын

In this video we take a break from 3D and explore 2D rendering using a sprite batching technique in OpenGL. This is also a great opportunity to get introduced to Uniform Buffer Objects which is a more efficient way of loading uniforms than the method that we've been using so far, especially when you have many of them. UBOs can be used for 3D as well so even if you don't plan on doing 2D rendering you should definitely learn about them.
The sprites that I used are from www.gameart2d.com
Free texture packing tool: www.codeandweb.com/tp-online
Timecodes
0:00 Intro
0:26 Sprite Batching
1:54 Calculating sprite size in texture space
2:34 Screen space to NDC
2:47 Sprite batching solution
4:09 The vertex shader
4:54 The fragment shader
5:52 Supporting multiple sprite sheets
6:03 The QuadArray class
6:37 The SpriteBatch class
8:22 Simple animation example
8:35 Efficiency of uniform variables
9:08 Uniform Buffer Objects
13:40 Conclusion
Make sure to watch all the previous tutorials in the "OpenGL For Beginners" playlist at • OpenGL for Beginners
Please visit ogldev.org to see more of my tutorials on modern OpenGL.
Link to source: github.com/emeiri/ogldev/blob...
OpenGL 4.6 specification: www.khronos.org/registry/Open...
Feel free to comment below.
Email: ogldev1@gmail.com
Github: github.com/emeiri/ogldev.git
Twitter: @ogldev
One time donations (Paypal): ogldev.org/donate.html
Patreon: / ogldev
Enjoy,
Etay Meiri
#opengl #ogldev #opengtutorials

Пікірлер: 46
@miumpre2839
@miumpre2839 Ай бұрын
Very good info and explanation! thanks
@OGLDEV
@OGLDEV Ай бұрын
You're welcome :-)
@noobheeecker4211
@noobheeecker4211 2 жыл бұрын
Awesome, great video!
@OGLDEV
@OGLDEV 2 жыл бұрын
Thanks!
@SB-pq8dp
@SB-pq8dp Жыл бұрын
You are awesome! I am very grateful for your work! I was wondering, is it worth doing batching in a 3D renderer? Or maybe it will turn out to be a useless feature (especially with different assimp optimizations)... It seems to me that this would be useful in a game with low-poly like graphics, but certainly not in a physically based renderer or something like that, am I right?
@OGLDEV
@OGLDEV Жыл бұрын
Thanks! Batching in 3D is usually beneficial because the GPU is (depending on your $$$) very fast and you don't want it to sit idle. You need to always feed it with work so you want to minimize the CPU-to-GPU interaction and batching is one way to do it.
@andreagenor
@andreagenor 2 жыл бұрын
Awesome videos!
@OGLDEV
@OGLDEV 2 жыл бұрын
Thanks!
@grengren6421
@grengren6421 Жыл бұрын
You hero among men.
@OGLDEV
@OGLDEV Жыл бұрын
LOL! Thanks!
@pal_7
@pal_7 2 жыл бұрын
Keep the hard work chief
@OGLDEV
@OGLDEV 2 жыл бұрын
Sure thing Boss ;-)
@laurentbedief2199
@laurentbedief2199 2 жыл бұрын
You're the best !!!!! thanks
@OGLDEV
@OGLDEV 2 жыл бұрын
Thank you so much!
@mourirsilfaut6769
@mourirsilfaut6769 2 жыл бұрын
Thanks a lot. Btw have you ever consider making a video about OIT ?
@OGLDEV
@OGLDEV 2 жыл бұрын
Yes, but will require some research because I'm not very familiar with the topic. Will add it to the todo list.
@firstow
@firstow Жыл бұрын
many thanks!
@OGLDEV
@OGLDEV Жыл бұрын
You're welcome!
@gokalpates1567
@gokalpates1567 2 жыл бұрын
Awesome.
@OGLDEV
@OGLDEV 2 жыл бұрын
Thanks :-)
@oddstonegames
@oddstonegames 2 жыл бұрын
thanks a lot
@OGLDEV
@OGLDEV 2 жыл бұрын
Your'e welcome :-)
@thomasnguyen1150
@thomasnguyen1150 5 ай бұрын
Slightly unrelated, instead of using 6 vertices to draw the quad you could also use only 4 vertices with an element buffer object right? Does this make performance better?
@OGLDEV
@OGLDEV 5 ай бұрын
Sure, but I doubt whether it will perform better due to the low number of vertices. So I usually skip the element buffer in such cases. btw, you can achieve 4 vertices without an element buffer using GL_TRIANGLE_STRIP.
@pastasawce
@pastasawce Жыл бұрын
Is there a simple way to add a uniform to the frag shader so that we can determine the offset of the spritesheet? Your set up is quite different from the opengl tutorial I'm following, so I'm curious if it's a simple task or not.
@OGLDEV
@OGLDEV Жыл бұрын
What do you mean 'offset of the spritesheet'? An offset inside it? In general, any value that you can calculate before the draw call can be set into the fragment shader as a regular uniform.
@pastasawce
@pastasawce Жыл бұрын
@@OGLDEV I define the vertices in an array with values being 1.0 and 0.0, I want to begin rendering at a specific part of the atlas, like we do with tilemaps, but the only solution I've gotten to work (which isn't a solution) was to call in c++ glPixelStorei(GL_UNPACK_ROW_LENGTH, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, currentFrameX); glPixelStorei(GL_UNPACK_SKIP_ROWS, currentFrameY); and then after calling glTexImage2D, calling those same functions, and passing in 0 as an argument. This is definitely not ideal lol
@OGLDEV
@OGLDEV Жыл бұрын
If I understand this correctly you are using glPixelStorei to point to the correct sprite. My intuition is that using the uniforms and not touching the texture itself is better but I can't prove it or anything.
@pastasawce
@pastasawce Жыл бұрын
@@OGLDEV I actually just figured out that in the vertex array, the texture coord values just needed to be changed from 0 to like 0.3 etc to begin the coords at a different spot. Now I need to figure out how to calculate screen coords to these decimals. It was confusing how the text coords and positions essentially alternate in the array.
@OGLDEV
@OGLDEV Жыл бұрын
That's what I do in the tutorial. 'screen coords' - you mean where to finally render the sprite? I translate screen position to NDC and provide it to the vs.
@developerdeveloper67
@developerdeveloper67 2 жыл бұрын
I'm still trying to figure out the vertex buffer, index buffer, and the vao thing. How do I draw multiple different models? Do I have to declare a different vertice and indice buffer for each object or do I declare all models in one vertex buffer and one index buffer? And the vao: what the f is this? I'm still confused...
@OGLDEV
@OGLDEV 2 жыл бұрын
You can manage your models in different ways and you basically mentioned the two main strategies. Option #1 is to use a dedicated VB/IB for each model. This seems more straightforward and I guess many people will go with that option because it makes sense to wrap the model in a C++ class and keep the buffers as private attributes. Option #2 is to load all the vertices and indices of all the models into a single VB or VB/IB pair and draw a specific model using glDrawElementsBaseVertex or any similar draw call that allows you to draw from the middle of the buffer. Whatever works better for you. The idea behind the VAO is to minimize the amount of state changes that you need to take care of before a draw call - you need to enable all the active vertex attributes and set the layout for each one. You can setup all this state once inside the VAO so that every time you bind the VAO you don't need to worry about all this state changes.
@developerdeveloper67
@developerdeveloper67 2 жыл бұрын
@@OGLDEV Thank you!
@OGLDEV
@OGLDEV 2 жыл бұрын
Did you write another comment? Seems like youtube deleted it.
@jw200
@jw200 2 жыл бұрын
@@OGLDEV KZbin sadly deletes lots of comments
@OGLDEV
@OGLDEV 2 жыл бұрын
Very true unfortunately.
@MrFabrizioV
@MrFabrizioV Жыл бұрын
Can't you create a struct containing the releavant quad info (base pos etc.) and then create an array of struct with size MAX_QUADS? struct T { vec2 BasePos; vec2 WidthHeight; ... }; uniform T QuadInfo[MAX_QUADS];
@OGLDEV
@OGLDEV Жыл бұрын
I haven't tried that but it should work. We are getting the offset of each element in T using glGetActiveUniformBlockiv. If you do this my way (structure of arrays) this gives you the offset to the corresponding array within T so all you need to do is to access the specific element using the offset as a base pointer: T.BasePos[i]. If you do this your way (array of structures) then you should get the offset inside a single struct. You then need to access the specific T element and use the offset to find the attribute inside it. The assumption is that the size of T is the sum of its attributes and that everything is packed together. It makes sense but I haven't studied the spec enough to verify it.
@razcodes
@razcodes 11 ай бұрын
How would you handle rotation of each individual sprite in this scenario?
@OGLDEV
@OGLDEV 11 ай бұрын
Excellent question! I haven't tried that but I guess that in general you need to apply a 2D rotation matrix in the vertex shader. The trick is that if you just apply it on the existing code the sprites will rotate around the center of the screen instead of around their center (which is what I guess you want to do). You need to translate them to the center of the screen, apply the rotation and then translate back and continue. The vertex buffer provides us with corners of the quad: (0,0), (0,1), (1,0) and (1,1). When we multiply it by the WidthHeight vector which is in NDC we get the location in NDC of each corner. You need to translate each corner by half the width and height (in the negative). This moves the sprite to the center. Next you need to apply the 2D rotation matrix which will be a new uniform. And then translate back using the positive half of WidthHeight. From there you can continue as usual.
@razcodes
@razcodes 11 ай бұрын
@@OGLDEV That is a very clever take, but wouldn't that rotate all vertices (from all sprites)?
@OGLDEV
@OGLDEV 11 ай бұрын
@@razcodes The rotation angle needs to be a per sprite uniform, similar to position, etc. You will construct a different matrix for each sprite.
@orocimarosay1447
@orocimarosay1447 2 жыл бұрын
Multiple identical quads is a simple sollution tho you can also use only one with very simple modifications
@OGLDEV
@OGLDEV 2 жыл бұрын
You mean with instancing?
@orocimarosay1447
@orocimarosay1447 2 жыл бұрын
@@OGLDEV yes
@OGLDEV
@OGLDEV 2 жыл бұрын
The main advantage with instancing comes when you have a very large model that you want to render multiple times while changing small bits and pieces such as matrices, etc. In the case of a single quad it seems a bit redundant but I have to admit that I haven't measured the two options so I can't say which will perform better.
Toon Shading & Rim Lighting // OpenGL Tutorial #34
5:16
100😭🎉 #thankyou
00:28
はじめしゃちょー(hajime)
Рет қаралды 54 МЛН
1🥺🎉 #thankyou
00:29
はじめしゃちょー(hajime)
Рет қаралды 78 МЛН
How many pencils can hold me up?
00:40
A4
Рет қаралды 19 МЛН
Basic Shadow Mapping // OpenGL Tutorial #35
16:54
OGLDEV
Рет қаралды 19 М.
How do games render their scenes? | Bitwise
13:12
DigiDigger
Рет қаралды 561 М.
I made my game engine
5:28
Benjamin Blodgett
Рет қаралды 29 М.
An introduction to Shader Art Coding
22:40
kishimisu
Рет қаралды 908 М.
GRASS RENDERING in OpenGL // Code Review
47:23
The Cherno
Рет қаралды 112 М.
Debugging Your OpenGL Code // OpenGL Tutorial #30
19:46
OGLDEV
Рет қаралды 7 М.
How Ray Tracing (Modern CGI) Works And How To Do It 600x Faster
32:06
Josh's Channel
Рет қаралды 556 М.
Basic Texture Mapping // OpenGL Tutorial #16
22:01
OGLDEV
Рет қаралды 32 М.
I tried coding my own graphics engine
4:23
Garbaj
Рет қаралды 184 М.
All OpenGL Effects!
30:21
Low Level Game Dev
Рет қаралды 55 М.
100😭🎉 #thankyou
00:28
はじめしゃちょー(hajime)
Рет қаралды 54 МЛН