OpenGLNoob
OpenGLNoob

Reputation: 45

Why vertex transformation outside GPU is not the same vertex transformation inside GPU?

As we know if we want to draw something in World space we need multiply our data by view and projection matrices. Now I need for my task to make vertex transformation outside shaders and sent transformated vertex directly. Like this:

Initialization matrix

glm::mat4 view, projection;
view = glm::lookAt(this->cameraPos, this->cameraPivot, this->Up);
projection = glm::perspective(glm::radians(60.0f), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);

Code

vector<glm::vec3> data;
glm::mat4 projection, view;
...
data.push_back(glm::vec3(projection * view * glm::vec4(0.0, 0.0, 0.5, 0.0)));
data.push_back(glm::vec3(projection * view * glm::vec4(0.0, 0.5, 0.5, 0.0)));
data.push_back(glm::vec3(projection * view * glm::vec4(0.5, 0.5, 0.5, 0.0)));
data.push_back(glm::vec3(projection * view * glm::vec4(0.5, 0.0, 0.5, 0.0)));
...
shader.set();
GLuint VAO,VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &wVBO);
glBindVertexArray(wVAO);
glBindBuffer(GL_ARRAY_BUFFER, wVBO);
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(vector<glm::vec3>), &data.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
...
glBindVertexArray(wVAO);
glDrawArrays(GL_LINE_LOOP, 0, data.size());
glBindVertexArray(0);

Shader

#version 330 core
layout (location = 0) in vec3 position;

void main()
{
    gl_Position = vec4(position, 1.0f);
}

But I get wrong view transformation - it looks like my data doesn't take into account the projection matrix, only the view matrix. But if I change it as usual:

Code

 ...
 data.push_back(glm::vec3(glm::vec4(0.0, 0.0, 0.5, 0.0)));
 ...
 shader.set();
 glUniformMatrix4fv(glGetUniformLocation(shader.Program, "matrices"), 1,
 GL_FALSE, glm::value_ptr(projection * view));

Shader

#version 330 core
layout (location = 0) in vec3 position;

uniform mat4 matrices;

void main()
{
    gl_Position = matrices * vec4(position, 1.0f);
}

it's works as expected. What is my mistake? In my task needs to know position all of vertex in World-space before it will sended in shader. How can I do that?

Upvotes: 0

Views: 171

Answers (3)

user7906463
user7906463

Reputation:

glm::vec4 as bytes is smth + 4 floats when shader expects 4 floats. At least size is wrong(and I suspect data too).That's said about all : question ,answer and comments.

Upvotes: 0

DanielCollier
DanielCollier

Reputation: 765

The homogeneous coorinate "w" for your vertices should be 1.0f or else no transform will be applied to the vertex.

Upvotes: 5

OpenGLNoob
OpenGLNoob

Reputation: 45

I got it! Thanks Daniel for idea!!! In my case no matters "w" is in inicialization of vertices. This is important in another. Looks on a shader code in example #2:

#version 330 core
layout (location = 0) in --->vec3<--- position;

uniform mat4 matrices;

void main()
{
    gl_Position = matrices * vec4(position, --->1.0f<---);
}

In input shader I send vec3 and it's wrong! We need to save "w" component which produced from matrix multiplication:

Shader

layout (location = 0) in vec4 position;
...
void main()
{
    gl_Position = matrices * position;
}

Code

vector<glm::vec4> data;
glm::mat4 projection, view;
...
data.push_back(projection * view * glm::vec4(0.0, 0.0, 0.5, 1.0));
...
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(glm::vec4), &data.data(), GL_STATIC_DRAW);
....
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

That's it! Thanks everyone!

Upvotes: 1

Related Questions