Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


noodleBowl

Member Since 08 Sep 2013
Offline Last Active Today, 05:08 PM

Topics I've Started

Using glBufferSubData

01 July 2015 - 11:44 AM

I'm working with OpenGL ES 2.0 and have some questions when it comes to glBufferSubData

 

1. Does this command lock down my VBO, even when only using a limited section of the buffer? I heard that if I were to draw half of my buffer and then write to the other half of the buffer. The GPU will stall until the draw command is finished. Is this true?

 

2. When orphaning should I be orphaning every frame? I feel like I should only orphan when my buffer is full, but if the above is true I feel like it is a little counter productive to orphan. Since I still am getting locked down / stalling the gpu from the glBufferSubData call

 

 


Me and the gameloop are not friends

25 June 2015 - 08:22 AM

Me and my gameloop are not friends...
Ok, on a more serious note I have a ton of trouble when it comes to the gameloop and would appreciate some help in this matter.

I have read the infamous http://gafferongames.com/game-physics/fix-your-timestep/ article and the equally http://www.koonsolo.com/news/dewitters-gameloop/ article, but for some reason I can't ever implement a fixed timestep gameloop correctly sad.png

I chose to go with the Gafferon Games approach as it seems to be the article that is referred to the most. I understand the article (what the article is saying), but there seems to be something wrong with my implementation all the time.

No matter what, I seem to always have a constant hiccup or stutter. It is like my app is trying to play catch up all the time? Maybe it comes down to the interpolation calculation being off? Can someone please tell me what I am doing wrong, at this point I'm not really sure what I should do.
 
 
I am trying to target 60 FPS just as a FYI, I have tried to target 30 FPS as well but that seems to make it worse (hiccups / stutter).

Also I am developing for Android using OpenGL ES 2.0, My testing hardware is a Kyocera Hydro Edge [ http://www.boostmobile.com/shop/phones/kyocera-hydro-edge/ ].

I have tested on other android phones too, but I still have the same issues

 

If you have question please ask, I would really like to solve this problem once and for all. Thanks smile.png
 
 

Update game logic method and render method

public void Update(float deltatime)
{
        //Update the position of the 1st scrolling background
	prevBack1X = back1X;
	back1X -= 120.0f * deltatime;
	if(back1X + space1.getWidth() <= 0.0f) //Warp the background to the start position because it has gone offscreen
	{
		back1X = 0.0f;
		prevBack1X = 0.0f;
	}

	//Update the position of the 2nd scrolling background
	prevBack2X = back2X;
	back2X -= 360.0f * deltatime;
	if(back2X + space2.getWidth() <= 0.0f) //Warp the background to the start position because it has gone offscreen
	{
		back2X = 0.0f;
		prevBack2X = 0.0f;
	}
}

public void Render(float alpha)
{
	//Interpolation (LERP) to get render position
	pos = prevBack1X + (back1X - prevBack1X) * alpha;
	pos2 = prevBack2X + (back2X - prevBack2X) * alpha;
	
	batch.Begin(projectionMatrix);
	
	//Draw the first background and the background that follows
	//to complete the scrolling background illusion 
	batch.Draw(background1, pos, 0.0f);
	batch.Draw(background1, pos + background1.getWidth(), 0.0f);
	
	//Draw the second background and the background that follows
	//to complete the scrolling background illusion 
	batch.Draw(background2, pos2, 0.0f);
	batch.Draw(background2, pos + background1.getWidth(), 0.0f);
	
	batch.End();
}

 
The Gameloop! And frame time calculation

private long nowTime = System.nanoTime();
private long lastTime = nowTime;
private float accum = 0.0f;
private float frameTime = 0.0f;
private float fixedDT = 1.0f / 60.0f; //Target 60 FPS for game update speed

public void onDrawFrame(GL10 gl)
{
    CalculateFrameTime(); //Calc the frametime in secs

    accum += frameTime;
    while(accum >= fixedDT)
    {
        Update(fixedDT);
        accum -= fixedDT;
    }
    alpha = accum / fixedDT;

    //System.out.println("FrameTime: " + frameTime + " | Accum: " + accum + " | Alpha: " + alpha);

    Render(alpha);
}

private void CalculateFrameTime()
{
    //Calc the frame time in seconds
    nowTime = System.nanoTime();
    frameTime = (nowTime - lastTime) / 1000000000.0f;
    lastTime = nowTime;
}

Sample of FrameTime (in secs), Accum value, and alpha (println statement above)

FrameTime: 0.015107584 | Accum: 0.001972055 | Alpha: 0.1183233
FrameTime: 0.013520525 | Accum: 0.01549258 | Alpha: 0.92955476
FrameTime: 0.016633602 | Accum: 0.015459513 | Alpha: 0.92757076
FrameTime: 0.018495347 | Accum: 6.215237E-4 | Alpha: 0.03729142
FrameTime: 0.016633604 | Accum: 5.884599E-4 | Alpha: 0.035307594
FrameTime: 0.019990845 | Accum: 0.003912637 | Alpha: 0.23475821
FrameTime: 0.014893942 | Accum: 0.002139911 | Alpha: 0.12839466
FrameTime: 0.013428963 | Accum: 0.015568874 | Alpha: 0.9341324
FrameTime: 0.016664123 | Accum: 0.015566329 | Alpha: 0.9339797
FrameTime: 0.018495345 | Accum: 7.2833896E-4 | Alpha: 0.043700334
FrameTime: 0.016603082 | Accum: 6.6475384E-4 | Alpha: 0.039885227
FrameTime: 0.020021364 | Accum: 0.0040194504 | Alpha: 0.24116701
FrameTime: 0.014863421 | Accum: 0.0022162031 | Alpha: 0.13297218
FrameTime: 0.014130932 | Accum: 0.016347136 | Alpha: 0.9808281
FrameTime: 0.015931634 | Accum: 0.015612101 | Alpha: 0.93672603
FrameTime: 0.018525865 | Accum: 8.046292E-4 | Alpha: 0.048277747
FrameTime: 0.016603084 | Accum: 7.410459E-4 | Alpha: 0.04446275
FrameTime: 0.021577904 | Accum: 0.0056522824 | Alpha: 0.33913693
FrameTime: 0.039188158 | Accum: 0.011507105 | Alpha: 0.6904263
FrameTime: 0.005829391 | Accum: 6.698277E-4 | Alpha: 0.040189657
FrameTime: 0.007019686 | Accum: 0.0076895137 | Alpha: 0.4613708
FrameTime: 0.007874256 | Accum: 0.015563769 | Alpha: 0.9338261
FrameTime: 0.016816728 | Accum: 0.015713831 | Alpha: 0.94282985
FrameTime: 0.02145582 | Accum: 0.0038363151 | Alpha: 0.2301789
FrameTime: 0.031435985 | Accum: 0.0019389652 | Alpha: 0.1163379
FrameTime: 0.001800702 | Accum: 0.0037396671 | Alpha: 0.22438002
FrameTime: 0.014985503 | Accum: 0.0020585023 | Alpha: 0.12351013
FrameTime: 0.017366093 | Accum: 0.0027579274 | Alpha: 0.16547564
FrameTime: 0.012574393 | Accum: 0.015332321 | Alpha: 0.9199392
FrameTime: 0.016572561 | Accum: 0.015238216 | Alpha: 0.91429293
FrameTime: 0.0179765 | Accum: 0.01654805 | Alpha: 0.99288297
FrameTime: 0.015321227 | Accum: 0.01520261 | Alpha: 0.9121565
FrameTime: 0.016694643 | Accum: 0.015230587 | Alpha: 0.91383517
FrameTime: 0.019136272 | Accum: 0.0010335259 | Alpha: 0.06201155
FrameTime: 0.016572561 | Accum: 9.394195E-4 | Alpha: 0.056365166
FrameTime: 0.017823897 | Accum: 0.0020966493 | Alpha: 0.12579896
FrameTime: 0.015595911 | Accum: 0.0010258928 | Alpha: 0.061553564
FrameTime: 0.014222493 | Accum: 0.015248386 | Alpha: 0.9149031
FrameTime: 0.016694643 | Accum: 0.015276363 | Alpha: 0.91658175
FrameTime: 0.016908286 | Accum: 0.015517982 | Alpha: 0.93107885
FrameTime: 0.016603084 | Accum: 0.0154543985 | Alpha: 0.92726386
FrameTime: 0.016694644 | Accum: 0.015482375 | Alpha: 0.9289425
FrameTime: 0.018983671 | Accum: 0.0011327118 | Alpha: 0.067962706
FrameTime: 0.014222493 | Accum: 0.015355205 | Alpha: 0.9213123
FrameTime: 0.016633604 | Accum: 0.0153221395 | Alpha: 0.91932833
FrameTime: 0.016938806 | Accum: 0.015594279 | Alpha: 0.9356567
FrameTime: 0.016603082 | Accum: 0.015530696 | Alpha: 0.93184173
FrameTime: 0.016664123 | Accum: 0.015528152 | Alpha: 0.9316891
FrameTime: 0.019044712 | Accum: 0.001239527 | Alpha: 0.07437161


Android: OpenGL ES 2.0 slight stutter?

24 June 2015 - 01:39 PM

I just started working on a project in Android using OpenGL ES 2.0 and I have a few questions

In my application I draw 3 full screen backgrounds. The first one is static non moving, the second one moves slowly, and the third one moves fast.
The issue I am seeing is that the moving backgrounds (specifically the fast one) seem to hiccup and I'm kind of lost as to why this is happening.
 
I have a feeling its something to do with my delta times. Usually it hovers around 0.016666***, but occasionally I some outliers where the delta time is 0.020*** something. So my question is are my delta times being calculated poorly?
 
I calculating my delta time like so. Am I missing something / doing something wrong?:

long nowTime;
long lastTime;
float deltatime;

public void calcDT()
{
	nowTime = System.nanotime();
	deltatime = (float)(nowTime - lastTime) / 1000000000.0f;
	lastTime = nowTime;
}

//onDrawFrame method. Calc the delta time, then update the game logic and render the graphics
public void onDrawFrame(GL10 gl)
{
	calcDT();
	Update(deltatime); //Updates to game logic/physics 
	Render(); //OpenGL ES 2.0 render commands
}

 
Also, just in case, here is how the backgrounds are being handled as this could possibly be the reason:


float backgroundPos1 = 0.0f;
float backgroundPos2 = 0.0f;
public void Update(float deltatime)
{
	/* Other update code */
	
	backgroundPos1 -= 120.0f * deltatime;
	backgroundPos1 = backgroundPos1 % (int)background1Texture.getWidth(); //getWidth calls return a float value
	
	backgroundPos2 -= 360.0f * deltatime;
	backgroundPos2 = backgroundPos2 % (int)background2Texture.getWidth();

	/* Other update code */
}


public void Render()
{

	/* Other render code */
	
	batch.Draw(background1Texture, backgroundPos1, 0.0f);
	batch.Draw(background1Texture, backgroundPos1 + background1Texture.getWidth(), 0.0f);
	
	batch.Draw(background2Texture, backgroundPos2, 0.0f);
	batch.Draw(background2Texture, backgroundPos2 + background2Texture.getWidth(), 0.0f);

	/* Other render code */
}


glDrawArrays significantly better than glDrawElements

11 June 2015 - 09:27 AM

I'm having a very strange issue occurring in my app that uses OpenGL ES 2. I am trying to draw a simple scene using glDrawElements and I noticed the performance I was getting is horrible. I went back and changed it to use glDrawArrays and it was significantly better. Not understanding why, I would think it would be the other way around, I opened up the profiler in Android Studio and snagged the OpenGL timings
 
glDrawArrays VS glDrawElements Timings (in nanoseconds):

glDrawArrays (Wall Time || Thread Time) :
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 6)   183,122 || 183,123
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 12) 30250 || 30521
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 12) 30250 || 30521
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 450) 366,245 || 366245
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 6) 61040 ||61040
glDrawArrays(mode = GL_MAP_INVALIDATE_RANGE_BIT, first = 0, count = 180) 488326 || 91561
 
glDrawElements (Wall Time || Thread Time) :
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 6, type = GL_UNSIGNED_SHORT, indices = 0x0) 274,683 || 274,684
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 12, type = GL_UNSIGNED_SHORT, indices = 0x0) 7,721,654 || 7,630,093
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 12, type = GL_UNSIGNED_SHORT, indices = 0x0) 4,669,617 || 4,486,495
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 450, type = GL_UNSIGNED_SHORT, indices = 0x0) 6,043,034 || 4,791,698
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 6, type = GL_UNSIGNED_SHORT, indices = 0x0) 4,700,137 || 4,608,577
glDrawElements(mode = GL_MAP_INVALIDATE_RANGE_BIT, count = 180, type = GL_UNSIGNED_SHORT, indices = 0x0) 4,669,617 || 4,608,576

The only thing that is different between the runs is the use of glDrawArrays vs glDrawElements. Anybody got any ideas why this could be happening? What am I doing wrong?
 

  

VBO / IBO Creation Code:

private void CreateVboIboObjects()
{
	//=== VBO Stuff ===
	vbo = new int[1];
	glGenBuffers(1, vbo, 0);

	//In glDrawArrays VERTEX_PER_QUAD is 6; In glDrawElements VERTEX_PER_QUAD is 4
	//FLOAT_COMPONENTS_PER_VERTEX is always 10 (XYZW, RGBA, UV)
	//MAX_QUADS_PER_BATCH is set to 5K
	//BYTES_PER_FLOAT is 4
	int vboByteSize = FLOAT_COMPONENTS_PER_VERTEX * MAX_QUADS_PER_BATCH * VERTEX_PER_QUAD * BYTES_PER_FLOAT

	//Java based buffer allocation
	vboBuffer = ByteBuffer.allocateDirect(vboByteSize).order(ByteOrder.nativeOrder()).asFloatBuffer();
	vboBuffer.position(0);

	//The intermediate array that holds the vertex data, before it is actual placed in the buffer using glBufferSubData 
	vertexDataContainer = new float[vboBuffer.limit()];

	//Where we are in the above buffer (how many float components we have gone through)
	vboIndex = 0;

	//Create the OpenGL Buffer with no initial data; Data will placed in on every frame
	glBindBuffer(vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, vboByteSize, null, GL_DYNAMIC_DRAW);

	//=== IBO Stuff ===
	ibo = new int[1];
	glGenBuffers(1, ibo, 0);

	//INDICES_PER_QUAD is always 6; When using the glDrawArrays call this (the ibo) is not used
	//MAX_QUADS_PER_BATCH is set to 5K
	//BYTES_PER_SHORT is 2
	int iboByteSize = MAX_QUADS_PER_BATCH * INDICES_PER_QUAD * BYTES_PER_SHORT

	//Java based buffer allocation
	ShortBuffer iboBuffer = ByteBuffer.allocateDirect(vboByteSize).order(ByteOrder.nativeOrder()).asShortBuffer();

	for(int i = 0, j = 0; i < MAX_QUADS_PER_BATCH * INDICES_PER_QUAD; i+= INDICES_PER_QUAD; j+= VERTICES_PER_QUAD)
	{
		iboBuffer.put((short) j);
		iboBuffer.put((short) j + 1);
		iboBuffer.put((short) j + 2);
		iboBuffer.put((short) j + 3);
		iboBuffer.put((short) j);
		iboBuffer.put((short) j + 2);
	}
	iboBuffer.Flip();

	//Give the iboBuffer as the initial data; This buffer's data does not change
	glBindBuffer(ibo[0]);
	glBufferData(GL_ELEMENTS_ARRAY_BUFFER, iboByteSize, iboBuffer, GL_STATIC_DRAW);
}

Code that flushes the buffer (issues the draw call)

private void Render()
{
	//If there is nothing to draw back out
	if(vboIndex == 0)
		return;
	
	//Setup the shader program for the draw
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, batchTextureID);
	shader.UseProgram();
	shader.UseUniform("projectionMatrix", batchProjectionMatrix.data);
	shader.UseUniform("textureSampler", 0);
	shader.EnableAttribute("vertexPos", shader.AttributesTotalByteSize(), 0);
	shader.EnableAttribute("color", shader.AttributesTotalByteSize(), shader.Attribute("vertexPos").byteSize);
	shader.EnableAttribute("texCoords", shader.AttributesTotalByteSize(), shader.Attribute("vertexPos").byteSize + shader.Attribute("color").byteSize);

	//Place all the data that is in the intermediate data are into the Java Float buffer
	//Prepares it for the OpenGL Buffer call
	vboBuffer.put(vertexDataContainer, 0, vboIndex);
	vboBuffer.position(0);

	//Bind the VBO buffer and place data into it (data comes from the Java Float Buffer above)
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferSubData(GL_ARRAY_BUFFER, 0, vboIndex * BYTES_PER_FLOAT, vboBuffer);

	//===================== CODE BELOW IS USED ONLY IN THE glDrawElements Version =======================
	//Bind the IBO and draw our quads
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
	
	//vboIndex increases its value by 40 every time a quad is drawn
	//One quad is 40 float components. EG 40 * .15 = 6 indices to draw
	glDrawElements(GL_TRIANGLES, (int)(vboIndex * 0.15f), GL_UNSIGNED_SHORT, 0);
	
	//Reset where we are in the vbo buffer
	vboIndex = 0;
	
	//===================== CODE BELOW IS USED  ONLY IN THE glDrawArrays Version =======================
	
	//vboIndex increases its value by 60 every time a quad is drawn
	//One quad is 60 float components. EG 60 * .1 = 6 indices to draw; 
	glDrawArrays(GL_TRIANGLES, 0, (int)(vboIndex * 0.1f));
	
	//Reset where we are in the vbo buffer
	vboIndex = 0;
}

VBO Confusion

09 June 2015 - 02:34 AM

I'm developing in OpenGL ES 2 on Android (my dev device uses Jelly Bean) and I created a scene with 3 full screen backgrounds (two scroll horizontally), 2 particle emitters, a sprite, and some other things dealing with audio and controls. After starting up my app I see the FPS is pretty sad, averaging around 19 FPS.
 
Based on my other app tests I was pretty sure it was the graphics, so as a blind shot in the dark I changed the max quads that my sprite batcher could handle before it needed to flush the buffer from 5000 to 1000. Started it back up and bang! I instantly hit 55+ FPS, change the max quads again to 500 and I'm back at 60 FPS
 
Could someone tell me why this worked?
 
I mean its awesome, but I really have no idea how this actually made my FPS skyrocket.
The max quads constant in my batcher does effect how big the the VBO/IBO are, but I would think that does not matter as my call to glBufferSubData only fills the VBO with what it needs and my call to glDrawElements only draws the number of vertices required for the quads.
 
Here is my flush method which is responsible for actually doing the draw call

    private void FlushBatch()
    {
        //Back out if there is nothing to draw
        if(vboIndex == 0)
            return;
        
        //Set up everything for the Shader Program to run
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, batchTextureID);
        currentShaderProgram.UseProgram();
        currentShaderProgram.UseUniform("projectionMatrix", batchProjectionMatrix.data);
        currentShaderProgram.UseUniform("textureSampler", 0);
        currentShaderProgram.EnableAttribute("vertexPos", currentShaderProgram.AttributesTotalByteSize(), 0);
        currentShaderProgram.EnableAttribute("color", currentShaderProgram.AttributesTotalByteSize(), currentShaderProgram.Attribute("vertexPos").byteSize);
        currentShaderProgram.EnableAttribute("texCoords", currentShaderProgram.AttributesTotalByteSize(), currentShaderProgram.Attribute("vertexPos").byteSize + currentShaderProgram.Attribute("color").byteSize);


        //Prepare the vbo buffer that will be used by OpenGL
        vboBuffer.put(vertexData, 0, vboIndex);
        vboBuffer.position(0);

        //Bind the buffer and fill the GPU buffer 
        glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
        glBufferSubData(GL_ARRAY_BUFFER, 0, vboIndex * BYTES_PER_FLOAT, vboBuffer);

        //Bind the IBO and draw our quads
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[0]);
        glDrawElements(GL_TRIANGLES, (int)(INDICES_PER_QUAD * vboIndex * vboFloatsPerQuadRatio), GL_UNSIGNED_SHORT, 0);
        
        //Reset where we are in the vbo buffer
        vboIndex = 0;
    }

Here is my VBO/IBO creation

    private void CreateVboObjects()
    {
        //Gen the vbo names
        vboCount = 1;
        vbos = new int[vboCount];
        glGenBuffers(vboCount, vbos, 0);

        //setup vbo buffer (the java buffer) to be used by opengl
        //MAX_QUADS_PER_BATCH was changed from 5000 to 500 and the FPS skyrocketed. Why?
        vboBuffer = ByteBuffer.allocateDirect(MAX_QUADS_PER_BATCH * VERTEX_PER_QUAD * FLOAT_COMPONENTS_PER_VERTEX * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vboBuffer.position(0);
        vboIndex = 0;
        vboFloatComponentsPerQuad = FLOAT_COMPONENTS_PER_VERTEX * VERTEX_PER_QUAD;
        vboFloatsPerQuadRatio = 1.0f / (float)vboFloatComponentsPerQuad;
        vboCurrentBuffer = 0;

        //Create the intermediate container for the vbo data (used because Put for java buffers is super slow :( )
        vertexData = new float[vboBuffer.limit()];

        //Create the VBO for opengl
        for(int i = 0; i < vbos.length; ++i)
        {
            glBindBuffer(GL_ARRAY_BUFFER, vbos[i]);
            glBufferData(GL_ARRAY_BUFFER, vboBuffer.limit() * BYTES_PER_FLOAT, null, GL_DYNAMIC_DRAW);
        }
    }

    private void CreateIboObject()
    {
        //Gen the ibo name
        ibos = new int[1];
        glGenBuffers(1, ibos, 0);

        //Create the java buffer for the ibo
        ShortBuffer iboData = ByteBuffer.allocateDirect(MAX_QUADS_PER_BATCH * INDICES_PER_QUAD * BYTES_PER_SHORT).order(ByteOrder.nativeOrder()).asShortBuffer();
        iboData.position(0);

        //Generate the ibo data to use
        for(int i = 0, j = 0; i < MAX_QUADS_PER_BATCH * INDICES_PER_QUAD; i += INDICES_PER_QUAD, j += VERTEX_PER_QUAD)
        {
            iboData.put((short) j);
            iboData.put((short)(j + 1));
            iboData.put((short)(j + 2));
            iboData.put((short)(j + 3));
            iboData.put((short) j);
            iboData.put((short)(j + 2));
        }
        iboData.flip();

        //Create the IBO buffer for opengl
        for(int i = 0; i < ibos.length; ++i)
        {
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibos[i]);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, iboData.limit() * BYTES_PER_SHORT, iboData, GL_STATIC_DRAW);
        }
    }

PARTNERS