NDC 坐标而非屏幕坐标 (2D) 中的 OpenGL 转换

OpenGL transformation in NDC coordinates instead of screen coordinates (2D)

我无法弄清楚如何使用屏幕坐标在我的场景中定位 2D 对象。目前我有一些工作(下面的代码)但它想要 NDC 坐标,这不容易使用。我不知道哪里出了问题。我想我已经按应有的方式使用了所有东西,所以我想我忘记了什么。

下面是处理场景中对象绘制的代码:

glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


// RENDERING HERE
colorProgram.bind();

for (size_t t = 0; t < objectsWithGraphicsComponentInThisScene.size(); ++t)
{
    // set texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, objectsWithGraphicsComponentInThisScene[t]->getComponent<GraphicsComponent>()->getTexture());

    GLint texLocation = colorProgram.getUniformLocation("texSampler");
    glUniform1i(texLocation, 0);

    glm::mat4 trans;
    trans = glm::translate(glm::mat4x4(1.0f), glm::vec3(objectsWithGraphicsComponentInThisScene[t]->getPosition().x, objectsWithGraphicsComponentInThisScene[t]->getPosition().y, 0));
    GLint transMatLocation = colorProgram.getUniformLocation("transformMatrix");
    glUniformMatrix4fv(transMatLocation, 1, GL_FALSE, glm::value_ptr(trans));

    // set camera Matrix
    GLint projMatLocation = colorProgram.getUniformLocation("projectionMatrix");
    glm::mat4 cameraMatrix = camera->getCameraMatrix();
    glUniformMatrix4fv(projMatLocation, 1, GL_FALSE, glm::value_ptr(cameraMatrix));

    objectsWithGraphicsComponentInThisScene[t]->getComponent<GraphicsComponent>()->getSprite()->draw();

    // unbind all
    glBindTexture(GL_TEXTURE_2D, 0);
}

colorProgram.unbind();

其中 colorProgram 是我的精灵使用的着色器,getPosition() 只是 return 我设置的值。 (其中 x y 和 z 值应作为屏幕坐标给出)。因此,例如,getPosition 可能 return [100, 50, 0] 但这会将对象呈现在屏幕之外(屏幕为 1280x720)。

现在是渲染精灵的代码 (objectsWithGraphicsComponentInThisScene[t]->getComponent()->getSprite()->draw();):

void Sprite::draw()
{
glBindBuffer(GL_ARRAY_BUFFER, vboID);

glEnableVertexAttribArray(0);

// position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));

//color
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));

// uv
glVertexAttribPointer(2, 2, GL_FLOAT, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, uv));

glDrawArrays(GL_TRIANGLES, 0, 6);

glDisableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

这是着色器 (colorProgram) 中的代码: 顶点着色器:

#version 130
// per vertex

// input data from VBO
in vec2 vertexPosition;
in vec4 vertexColor;
in vec2 vertexUV;

// output to fragment shader
out vec4 fragmentColor;
out vec2 fragmentUV;

uniform mat4 projectionMatrix;
uniform mat4 transformMatrix;

void main()
{
mat4 resultMatrix = transformMatrix * projectionMatrix;
gl_Position.xy = (resultMatrix * vec4(vertexPosition, 0.0, 1.0)).xy;
gl_Position.z = 0.0;

// Indicate that the coordinates are normalized
gl_Position.w = 1.0;

fragmentColor = vertexColor;
fragmentUV = vec2(vertexUV.x, 1.0 - vertexUV.y);
}

片段着色器

#version 130
// per pixel

// input from vertex shader
in vec4 fragmentColor;
in vec2 fragmentUV;

out vec4 color;

uniform sampler2D texSampler;

void main()
{
vec4 textureColor = texture(texSampler, fragmentUV);
if (textureColor.a < 0.5) discard;
color = fragmentColor * textureColor;
}

如果您需要更多代码,我很乐意添加更多代码,尽管我认为这就是所需的一切。

顶点着色器中的这个序列

mat4 resultMatrix = transformMatrix * projectionMatrix;
gl_Position.xy = (resultMatrix * vec4(vertexPosition, 0.0, 1.0)).xy;

不太可能是您真正想要的。由于您使用 matrix * vector 约定,因此您最终会得到

position = transform  *  projection * v
         = transform  * (projection * v)

换句话说:在 投影之后应用变换。由于在投影之后,观看体积在 [-1,1]^3 范围内(在透视划分之后的欧几里德 NDC space 中。实际上,我们在这里工作在剪辑 space 中,其中它是 [-w,w]^3,但这在这种情况下并不重要,),将对象平移 100 个单位肯定会将其移出平截头体。

您应该只颠倒矩阵乘法的顺序。