Hello everyone,
Currently working on a robot simulation project, I come to you after many days of work to get into OpenGL, build my environment and optimize render time. My aim is to get several objects (spheres, cubes, tubes, perhaps some simple VRML models displays in special cases) displayed and updated quickly. Most of them would be static and I would never get more than around 50~100 of them so it should be simple, right ?
Here is how I processed : for reasons unrelated to OpenGL integration to my project, my classes are structured as shown in the following figure. I simplified it and isolated the visual / OpenGL-related classes for this help request.
[ATTACH=CONFIG]1206[/ATTACH]
For now, my objects are generated from a config file with the following format :
OBSTACLE = >SPHERE
POSITION = 1,1,0
ROTATION = 90,90,0
TRANSPARENCY = 1.0
COLOR = 0,60,100
DRAWTYPE = >STREAM
RADIUS = 0.1
OBSTACLE = >SPHERE
POSITION = 0.0,0,1
ROTATION = 10,20,40
TRANSPARENCY = 1.0
COLOR = 255,0,0
DRAWTYPE = >STREAM
RADIUS = 0.1
OBSTACLE = >PATH
POSITION = 0,0,1
ROTATION = 20,0,0
TRANSPARENCY = 0.6
COLOR = 0,120,220
DRAWTYPE = >STATIC
RADIUS = 0.05
From this, I instanciate my classes, generate the vertices, colors, normal vectors, etc. An example (screenshot while I set a movement trajectory for both spheres) looks like this :
[ATTACH=CONFIG]1207[/ATTACH]
First, I displayed around 10 shapes like this following the simplest tutorials, with simple diffuse + ambient lighting. The uniforms I would then send would approximately take 100ms per frame (CPU clock) … But I feel it isn’t a surprise to start like that since I’m a beginner.
Now, I implemented VBOs, VAOs and UBOs to get better results and it did work. I’m not satisfied yet though since it takes between 20 and 50ms to render a single frame (CPU clock) with the previous config (3 objects : 1 tube & 2 spheres).
I feel I am doing at least a few things wrong which lead to this unsatisfying computing time.
Here are some initialization stuff and the main loop I use to render the scene :
/************************************/
/******** INITIALIZING STUFF ********/
/************************************/
bool loop = true;
/* Sunlight parameters */
sunlight.fAmbientIntensity = glm::vec4(0.25);
sunlight.vColor = glm::vec4(1.0f, 1.0f, 1.0f, 0.0f);
glm::vec3 sunlightPos(10.0f,11.0f,12.0f);
glm::vec3 sunlightTmp = -glm::normalize(sunlightPos);
sunlight.vDirection = glm::vec4(sunlightTmp.x, sunlightTmp.y, sunlightTmp.z, 0.0f);
glm::mat4 projection;
glm::mat4 modelview;
glm::mat4 normalMatrix;
glm::mat4 camera;
projection = glm::perspective(70.0, (double) getWindowWidth()/getWindowHeight(), 1.0, 100.0);
modelview = glm::mat4(1.0);
camera = glm::lookAt(glm::vec3(2, 2, 2), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
initUbos();
glBindBuffer(GL_UNIFORM_BUFFER, lightUboId);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Light), &sunlight);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBuffer(GL_UNIFORM_BUFFER, staticMatricesUboId);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), &projection);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
/****************************/
/******** MAIN LOOP *********/
/****************************/
while(loop){
/* Cleaning window */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for(int i=0;i<env.getNObstacles();i++){
modelview = glm::mat4(1.0);
glUseProgram(env.getObstacle(i).getShape()->getGraph().getShader().getProgramId());
/* Translate element*/
modelview = glm::translate(modelview,glm::vec3(env.getObstacle(i).getShape()->getPosition(0),env.getObstacle(i).getShape()->getPosition(1),env.getObstacle(i).getShape()->getPosition(2)));
/* Rotate element */
modelview = glm::rotate(modelview,(float) env.getObstacle(i).getShape()->getRotation(2), glm::vec3(0.0,0.0,1.0)); // Z axis
modelview = glm::rotate(modelview,(float) env.getObstacle(i).getShape()->getRotation(1), glm::vec3(0.0,1.0,0.0)); // Y axis
modelview = glm::rotate(modelview,(float) env.getObstacle(i).getShape()->getRotation(0), glm::vec3(1.0,0.0,0.0)); // X axis
/* Normal matrix - for lighting purposes */
normalMatrix = glm::transpose(glm::inverse(modelview));
modelview = camera*modelview;
glBindVertexArray(env.getObstacle(i).getShape()->getGraph().getVaoId());
glBindBuffer(GL_UNIFORM_BUFFER, streamingMatricesUboId);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), &modelview);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), &normalMatrix);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, env.getObstacle(i).getShape()->getGraph().getN());
glBindVertexArray(0);
glUseProgram(0);
}
// Refreshing window
SDL_GL_SwapWindow(window);
}
Just in case, here is my vertex shader :
#version 150
in vec3 in_Vertex;
in vec4 in_Color;
in vec3 in_Normal;
layout(std140) uniform StaticMatrices
{
mat4 projection;
};
layout(std140) uniform StreamingMatrices
{
mat4 modelview;
mat4 normalMatrix;
};
out vec4 color;
smooth out vec3 vNormal;
void main() {
gl_Position = projection * modelview * vec4(in_Vertex, 1.0);
color = in_Color;
vec4 vTemp = normalMatrix * vec4(in_Normal,0.0);
vNormal = vTemp.xyz;
}
And my fragment shader :
#version 150
in vec4 color;
smooth in vec3 vNormal;
out vec4 out_Color;
layout(std140) uniform Light
{
vec3 vColor;
vec3 vDirection;
float fAmbientIntensity;
};
void main() {
float fDiffuseIntensity = max(0.0, dot(normalize(vNormal), -vDirection));
out_Color = color*vec4(vColor*(fAmbientIntensity+fDiffuseIntensity), 1.0);
}
Here is my computer’s configuration in case I am being too optimistic about my render resources :
[ul]
[li]CPU : Intel Core 2 Duo CPU E6750 2.66GHz[/li][li]RAM : 4Go[/li][li]GPU : NVIDIA GeForce GT 630[/li][li]OS : Windows 7 SP1 32bits[/li][li]IDE : Visual Studio Express 2012[/li][/ul]
What do you think I do wrong that causes useless resources consumption ?
Many thanks for your time. I hope I have been concise and provided all the necessary data and if not, I shall answer quickly to complete my post.
Silver