Jump to content
  • Advertisement
Sign in to follow this  
Phil15

OpenGL Opengles 2.0 multiple vertex buffers vs one buffer.

This topic is 1061 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys I wanted to get your opinion on this.

I currently thought of making multiple classes each one will have a prepare and draw method. To prepare and render staff to screen. 
The draw method has multiple glDraw() calls as it binds a texture and draws a part of the object binds next texture draw another part etc.. (I am aware this is quiet expensive but I maximum have 3 textures) 
the draw method will be used by some base class which will call the corresponding draw method on every object.
(The code should make more sense than this sentence :) ) 

Now the problem is that when I start creating multiple objects should If I just concatenate them into one big buffer 
which should increase performance I will end up with restricted number of vertices because of 
"glDrawElements(GL_TRIANGLES, Index, GL_UNSIGNED_SHORT, 0);"  GL_UNSIGNED_SHORT -> only 65,535 vertices  for all objects.... If however I keep the multiple draw calls I can have max 65,535  per object or am I being optimistic and the phone will just crash ?? 

RenderShip.cpp(some object with methods Draw and PrepareGraphics)


void RenderShip::PrepareGraphics(std::string textureFilename, std::string modelFilename)
{
	GLuint textureHandle;

	std::vector<GLfloat> rawData;

	objMtlLoader meshLoader;
	data = meshLoader.LoadFromFile(modelFilename);

     GLfloat * RawGraphicsData = data->GetRawArrayofValues(true, false);

	 IndexPerTexture = data->IndxsPrTxtHndl(programId);

	std::vector<unsigned short> Indexes; // cannot be more than 15 textures any way

	std::vector<glm::vec3> * Vertices = data->GetVertices();

	CenterMatrix = ModelPositioning::CenterModel(*Vertices);

	indexes = data->getIndexes();

	indexSize = data->GetIndexSize();


	GLint FragmentShaderTextureId;
	GLint VertexId;
	VertexId = glGetAttribLocation(programId, "position");

	FragmentShaderTextureId = glGetAttribLocation(programId, "vertexUV");
	glEnable(GL_DEPTH_TEST);

	GLuint myBuffId = 0;

	glGenBuffers(1, &myBuffId);

	glEnableVertexAttribArray(VertexId);

	glBindBuffer(GL_ARRAY_BUFFER, myBuffId);

	glBufferData(GL_ARRAY_BUFFER, indexSize * 5 * sizeof(float), RawGraphicsData, GL_STATIC_DRAW);

	glVertexAttribPointer(VertexId, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);

	GLuint IndexBuffId = 0;
	glGenBuffers(1, &IndexBuffId);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffId);

	glEnableVertexAttribArray(FragmentShaderTextureId);

	glVertexAttribPointer(FragmentShaderTextureId, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (char *)(sizeof(float) * 3));  // stride of 5 floats describing my colors starting at position 2

}


void RenderShip::DrawShip()
{
	glm::mat4 ModelViewProject(1.0f);
	glm::mat4 View(1.0f);
	glm::mat4 Model(1.0f);


	glm::mat4 Projection = glm::perspective(45.0f, 1024.0f / 768.0f, 0.1f, 15.0f);

	Model = CenterMatrix;

	ModelViewProject = Projection * camera->getWorldToViewMatrix() *  Model;

	GLint transform = glGetUniformLocation(programId, "ModelViewProject");

	glUniformMatrix4fv(transform, 1, false, glm::value_ptr(ModelViewProject));;

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	GLuint IndexBuffId = 0;
	glGenBuffers(1, &IndexBuffId);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffId);

	GLuint textureHandle;

	for (std::map<GLuint, size_t>::iterator it = IndexPerTexture.begin(); it != IndexPerTexture.end(); it++)
	{
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, it->second * sizeof(GLfloat), indexes, GL_DYNAMIC_DRAW);
		glBindTexture(GL_TEXTURE_2D, it->first); // Bind that texture temporarily
		glActiveTexture(it->first);

		glDrawElements(GL_TRIANGLES, it->second, GL_UNSIGNED_SHORT, 0);
	}


}


Renderer.cpp (Base class which will call draw on all objects)

#include "Renderer.h"
#include "RenderShip.h"
#pragma once

GLuint programId;

int program;


RenderShip * ship;


void Renderer::Prepare()
{
	 programId = InstallShaders();

	SendDataToOpenGL();
}

void Renderer::Render()
{
	ship->DrawShip();
}

void Renderer::SetCamera(Camera& cam)
{
	camera = &cam;
}


void Renderer::SendDataToOpenGL()
{
	ship = new RenderShip(programId, (*camera));

	ship->PrepareGraphics("textureWood.bmp", "untitled.obj");

}

int Renderer::InstallShaders()
{
	return  ShaderHandler::InstallShaders();
}

Share this post


Link to post
Share on other sites
Advertisement
I can't speak from experience, but I wouldn't expect much of a performance gain by combining multiple objects into a single vertex buffer. Plus, I would only start looking for ways to optimize code once you know you have a performance problem and have identified the bottleneck.

Share this post


Link to post
Share on other sites

Having less draw calls is faster , but this approach is very inflexable , hard to manage and scale.

Share this post


Link to post
Share on other sites

I can't speak from experience, but I wouldn't expect much of a performance gain by combining multiple objects into a single vertex buffer. Plus, I would only start looking for ways to optimize code once you know you have a performance problem and have identified the bottleneck.

I agree yet that means restructuring all the classes and the design of the engine which will take a considerate amount of time.

Share this post


Link to post
Share on other sites

Having less draw calls is faster , but this approach is very inflexable , hard to manage and scale.

Do you know how much faster, and is it worth it? If it`s 5% faster than yeh I probably would not bother but if it`s a good 20%-30% performance increase than something should be done.

Share this post


Link to post
Share on other sites

 

Having less draw calls is faster , but this approach is very inflexable , hard to manage and scale.

Do you know how much faster, and is it worth it? If it`s 5% faster than yeh I probably would not bother but if it`s a good 20%-30% performance increase than something should be done.

 

It's all about trades , if you can live with messy code do it like that.

Share this post


Link to post
Share on other sites


Having less draw calls is faster , but this approach is very inflexable , hard to manage and scale.



Having 1 vertex buffer vs multi-buffer does not imply 1 drawcall. The only thing derivation from that is 1 buffer binding. Since, if the op is not using a single render state ( texture, material, GL state or whatnot ), then multiple draw call will still be required.

II would profile to see how much if any gains would be achieved from doing so like others have already mentioned.

Share this post


Link to post
Share on other sites

 


Having less draw calls is faster , but this approach is very inflexable , hard to manage and scale.
 


Having 1 vertex buffer vs multi-buffer does not imply 1 drawcall. The only thing derivation from that is 1 buffer binding. Since, if the op is not using a single render state ( texture, material, GL state or whatnot ), then multiple draw call will still be required.

II would profile to see how much if any gains would be achieved from doing so like others have already mentioned.

 

I said less not one :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!