PDA

View Full Version : Is this the correct way to handle transformations in VBOs ?



Azokasion
07-14-2015, 07:32 PM
Hello, im a new user, and currently im learning opengl.

Ive made a mesh in Blender and loaded it with a .obj parser that i made, i can now display the 3d model.
Then i wanted to make transformations. As you cant use inmediate mode with VBO i struggled until i came with a solution.

To handle rotations i made functions in my Mesh class, and i apply math directly to the vertex that i have loaded.

This is what my shaders looks like:

Vertex Shader:


#version 130

in vec4 vertexPosition;


void main()
{
gl_Position.x = vertexPosition.x;
gl_Position.y = vertexPosition.y;
gl_Position.z = vertexPosition.z;
gl_Position.w = 1.0;
}


Fragment Shader(only for color):



#version 130

out vec3 color;

void main()
{
color = vec3(0.0,0.5,1.0);

}



This is how my functions look like:

(this is my calculateTranslation function)



void Modelo::calcularTraslado(float x, float y, float z)
{
glm::vec3 vectorTransf(x,y,z);

for(unsigned int i=0; i<vertices.size(); i++)
{
vertices[i] += vectorTransf;
}

glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); //GL buffer data takes position info?
glBindBuffer(GL_ARRAY_BUFFER, 0);
}



Then the only thing i have to do is use my function (like this: calcularTraslado(1.0,1.0,1.0)) and i can translate the mesh in the space.

The problem is, i dont know if this is the correct way to do this, ive noticed that if i have a very large number of vertices to draw, the calculations take a lot of time, so i dont really know what can i do.

Thanks for take the time to read, and for the help!
Sorry for my bad english, im still learning it lol

GClements
07-14-2015, 08:43 PM
The usual approach is to store the matrix in a uniform variable and have the vertex shader perform the transformation, e.g.


uniform mat4 transformation;
in vec4 vertexPosition;

void main()
{
gl_Position = transformation * vertexPosition;
}


If you're using the compatibility profile, you can still use the legacy OpenGL matrix functions (e.g. glTranslate()) and access the resulting matrices in the vertex shader, e.g either



gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vertexPosition;

or


gl_Position = gl_ModelViewProjectionMatrix * vertexPosition;


will transform the vertex position by the model-view and projection matrices, producing the same result as for legacy OpenGL.

Azokasion
07-14-2015, 10:25 PM
The usual approach is to store the matrix in a uniform variable and have the vertex shader perform the transformation, e.g.


uniform mat4 transformation;
in vec4 vertexPosition;

void main()
{
gl_Position = transformation * vertexPosition;
}




And what does exactly the 4x4 matrix stores?, and how can i give values to it from the source?.

Thank you for the answer! :biggrin-new:

GClements
07-14-2015, 11:29 PM
And what does exactly the 4x4 matrix stores?
The transformation to be applied to the vertices.

and how can i give values to it from the source?
With glUniformMatrix4fv().

Azokasion
07-15-2015, 01:25 PM
The transformation to be applied to the vertices.

With glUniformMatrix4fv().

Ive managed to make it run, but i cant see my mesh in the screen, i think i got something wrong, this is what i did:

I created a glm::mat4 transformation matrix(an identity matrix) in my Model class (private) and a function that returns that matrix ( ReturnMatrix();)


class Modelo
{
public:
Modelo(void);
~Modelo(void);


void init(const char * ModelPath);

void drawModel();

//void calcularTraslado(float x, float y, float z);
//void calcularEscala(float x, float y, float z);
//void calcularRotacion(float x, float y, float z, float angle);
glm::mat4 DevolverMatriz();
private:

std::vector< glm::vec3 > vertices;
std::vector< glm::vec2 > uvs;
std::vector< glm::vec3 > normals; // Won't be used at the moment.
GLuint _vboID;

glm::mat4 transformation;

};



Then i created a GLuint _MatrixID in my GLSLProgram and made a function "void recieveMatrix(glm::mat4 MyMatrix)":




class GLSLProgram
{
public:
GLSLProgram(void);
~GLSLProgram(void);

void compilarShaders(const std::string& VertexPath, const std::string& fragmentPath); //Funcion para compilar los txt cargados en opengl

void linkearShaders(); //Linkear, combinar en un solo programa

void agregarAtributo(const std::string& nombreAtributo); // Se bindean los atributos que hicimos en el shader a un index

void usar(); //PONEMOS EL SHADER PARA QUE SEA UTILIZADO
void quitar(); // REMOVEMOS UTILIZACION DEL SHADER

void recibirMatriz(glm::mat4 MiMatriz);

private:

int _numeroAtributos;
void compilarShader(const std::string& archivoPath, GLuint id); //Funcion para cargar los txt

GLuint _shaderEnteroID;//EL PROGRAMA
GLuint _vertexShaderID;// EL ID DEL SHADER VERTEX
GLuint _fragmentShaderID; // EL ID DEL FRAGMENT SHADER
GLuint _MatrixID;


};





void GLSLProgram::recibirMatriz(glm::mat4 MiMatriz)
{
_MatrixID = glGetUniformLocation(_shaderEnteroID, "transformation");
glUniformMatrix4fv(_MatrixID,1,GL_FALSE,&MiMatriz[0][0]);
}



then, in my main program, after linking the shaders i used recieveMatrix to give the vertexShader the values:



void JuegoPrincipal::initShaders()
{

_colorShader.compilarShaders("shaders/vertexShader.txt","shaders/transformShader.txt");
_colorShader.agregarAtributo("vertexPosition");
_colorShader.linkearShaders();
_colorShader.recibirMatriz(_Modelo.DevolverMatriz( ));
}


But when i draw, i can only see the background, i think im doing something wrong, and the multiplication" transformation* vertexPosition"(in the shader) is sending the model to somewhere else. Maybe the "uniform mat4 transformation" its not recieving the values?

If the source code is needed just ask me and i will post it
Thank you

mhagain
07-15-2015, 01:38 PM
You need to call glUseProgram before you can make a glUniformMatrix call. Modern OpenGL also has glProgramUniform calls that don't need the glUseProgram.

Azokasion
07-15-2015, 01:52 PM
You need to call glUseProgram before you can make a glUniformMatrix call. Modern OpenGL also has glProgramUniform calls that don't need the glUseProgram.

That did the trick!

Thank you guys so much!