为什么GPU外的顶点变换与GPU内部的顶点变换不一样?

时间:2017-04-16 13:25:09

标签: c++ opengl matrix shader

正如我们所知,如果我们想要在世界空间中绘制某些东西,我们需要通过视图和投影矩阵来乘以我们的数据。现在我需要我的任务是在着色器外部进行顶点变换并直接发送转换后的顶点。像这样:

初始化矩阵

>> % --- Setup inputs
B = randi(100000,150000,2);
B = unique(B,'rows');
A = B(randperm(size(B,1),3072),:);
>> out1 = intersect_index(A,B);       % Proposed in this post
>> out2 = find(ismember(B,A,'rows')); % @user2999345's soln
>> all(out1 == out2)
ans =
     1
>> tic,find(ismember(B,A,'rows')); toc % @user2999345's soln
Elapsed time is 0.066226 seconds.
>> tic, intersect_index(A,B); toc      % Proposed in this post
Elapsed time is 0.010360 seconds.

代码

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);

着色

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);

但是我得到错误的视图转换 - 看起来我的数据没有考虑投影矩阵,只考虑视图矩阵。但如果我像往常一样改变它:

代码

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

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

着色

 ...
 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));

它按预期工作。我的错是什么?在我的任务中,需要知道在着色器中发送之前在世界空间中定位所有顶点的位置。我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:5)

同质的coorinate&#34; w&#34;对于你的顶点应该是1.0f,否则不会对顶点应用变换。

答案 1 :(得分:1)

我明白了!谢谢丹尼尔的想法! 就我而言,没有问题&#34; w&#34;是在顶点的专业化。这对另一个很重要。 查看示例#2中的着色器代码:

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

uniform mat4 matrices;

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

在输入着色器中,我发送vec3,这是错误的!我们需要保存&#34; w&#34;由矩阵乘法产生的分量:

<强>着色

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

<强>代码

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);

那就是它!谢谢大家!

答案 2 :(得分:0)

glm :: vec4,当shader需要4个浮点数时,字节为smth + 4个浮点数。至少大小是错误的(我怀疑数据也是如此)。关于所有问题:问题,答案和评论。