Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Request for Advice - Optimizing My Drawing Calls...


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 12 June 2014 - 01:54 AM

Hello,

Folks here have given excellent advice before, I thought I would give this another try.

I have the code below which works but I believe I can do a better job of rendering.

Essentially I load my geometry in via a "for loop", find the duplicate geometry to set up instancing, load the goods into OpenGL, sort the loaded geometry by whether it has transparency or not, and then draw.

I have two areas below where I believe I can speed things up but I am not sure how.

The first is the way I load materials: Current I am using a uniform buffer object and loading it in based on the contents of the file. I want to use a standard buffer so that I can just have one call to glDrawElementsInstanced (or a better equivalent) but the offset for the material is by an arbitrary amount based on what the object is rather than an easy-to-define offset like the number of vertices. You will see this in code below.

The second way is my MVP and normal matrices. Currently I calculate all of the instances MVPs CPU side and then push the data down to the graphics card via a glBufferSubData but is there a smarter way of doing things?

If you see anything else, I am all ears.

Thank you all for any guidance you can provide.

First, how I load my geometry into OpenGL:

void HighSpeedMeshCache::LoadIntoOpenGL()
{
 
	glGenVertexArrays(1, &Pointer_VAO);
	glBindVertexArray(Pointer_VAO);
 
	glGenBuffers(1, &Vertex_VBO);
 
	glBindBuffer(GL_ARRAY_BUFFER, Vertex_VBO);
 
	glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_STATIC_DRAW);
 
	glBufferSubData(GL_ARRAY_BUFFER, NULL, VerticesBufferSize, Vertices);
 
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
 
	if (HasNormals) {
 
		glBufferSubData(GL_ARRAY_BUFFER, NormalOffset, NormalBufferSize, Normals);
 
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
 
	}
 
	if (HasUVs) {
		glBufferSubData(GL_ARRAY_BUFFER, UVOffset, UVBufferSize, UVs);
 
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(2);
 
	}
 
	glGenBuffers(1, &MVP_VBO);
	glBindBuffer(GL_ARRAY_BUFFER, MVP_VBO);
 
	glBufferData(GL_ARRAY_BUFFER, ModelMatrixIntances.size() * sizeof(glm::mat4), NULL, GL_DYNAMIC_DRAW);
 
	glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 0));
	glEnableVertexAttribArray(3);
	glVertexAttribDivisor(3, 1);
 
	glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 4));
	glEnableVertexAttribArray(4);
	glVertexAttribDivisor(4, 1);
 
	glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 8));
	glEnableVertexAttribArray(5);
	glVertexAttribDivisor(5, 1);
 
	glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 12));
	glEnableVertexAttribArray(6);
	glVertexAttribDivisor(6, 1);
 
	glGenBuffers(1, &NormalMatrix_VBO);
	glBindBuffer(GL_ARRAY_BUFFER, NormalMatrix_VBO);
 
	glBufferData(GL_ARRAY_BUFFER, ModelMatrixIntances.size() * sizeof(glm::mat3), NULL, GL_DYNAMIC_DRAW);
 
	glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 0));
	glEnableVertexAttribArray(7);
	glVertexAttribDivisor(7, 1);
 
	glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 3));
	glEnableVertexAttribArray(8);
	glVertexAttribDivisor(8, 1);
 
	glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 6));
	glEnableVertexAttribArray(9);
	glVertexAttribDivisor(9, 1);
 
	glGenBuffers(1, &Index_VBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Index_VBO);
 
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, TotalPolygonCount * 3 * sizeof(unsigned int), Indices, GL_STATIC_DRAW);
 
	glBindVertexArray(0);
}

And this is how I draw the geometry per mesh.

This function runs in a loop per mesh:

void HighSpeedMeshCache::DrawMe(GlMaintenance* CurrentOpenGLController)
{
	glBindVertexArray(Pointer_VAO);
 
	for (int i = 0; i < ModelMatrixIntances.size(); i++) {
		glm::mat4 ModelViewMatrix = CurrentOpenGLController->GetViewMatrix() * ModelMatrixIntances[i];
		glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(ModelViewMatrix)));
		glm::mat4 ModelViewProjectionMatrix = CurrentOpenGLController->GetProjectionViewMatrix() * ModelMatrixIntances[i];
		glBindBuffer(GL_ARRAY_BUFFER, MVP_VBO);
		glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat4))), sizeof(glm::mat4), glm::value_ptr(ModelViewProjectionMatrix));
		glBindBuffer(GL_ARRAY_BUFFER, NormalMatrix_VBO);
		glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat3))), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
	}
 
	for (int i = 0; i < Materials.size(); i++) {
		glBufferData(GL_UNIFORM_BUFFER, sizeof(Materials[i].ColorProperties), Materials[i].ColorProperties, GL_DYNAMIC_DRAW);
 
		glDrawElementsInstanced(GL_TRIANGLES, (Materials[i].TriangleCount * 3)
		               , GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(Materials[i].Offset * sizeof(unsigned int)), NumberOfChildItems + 1);
	}
}


Sponsor:



Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS