首页 > 解决方案 > 将 OpenGL 到 Vulkan 的 UV 坐标归一化

问题描述

我正在为GWEN(没有奢侈废话的 GUI)编写 Vulkan 渲染器,并且在获取纹理坐标以匹配时遇到问题。

这是我应该看到的: 正确输出

这就是目前正在发生的事情: 输出不正确

中心显示的纹理是我们用于 GUI 的图像,我确保将其测试渲染为四边形以确保正确加载它。

GUI 的结构似乎是正确的,这让我相信 UV 坐标不正确。特别是 Y 坐标,因为据我所知,X 看起来不错。

void Vulkan::AddVert(int x, int y, float u, float v)
{
    vertices.emplace_back();

    vertices.back().pos.x = ((float)x / 400) - 1.f;
    vertices.back().pos.y = ((float)y / 300) - 1.f;
    //  Our image is 512x512 px
    vertices.back().texCoord.x = (u / 512.0f);
    vertices.back().texCoord.y = 1.0f - (v / 512.0f);
}

void Vulkan::DrawTexturedRect(Gwen::Texture* pTexture, Gwen::Rect rect, float u1, float v1, float u2, float v2)
{
    //  ToDo: Implement textures through GWEN
    //  The GUI texture is hardcoded for now
    //  Once we're rendering properly i'll expand this function to handle textures
    Translate(rect);

    AddVert(rect.x, rect.y, u1, v1);
    AddVert(rect.x + rect.w, rect.y, u2, v1);
    AddVert(rect.x, rect.y + rect.h, u1, v2);
    AddVert(rect.x + rect.w, rect.y, u2, v1);
    AddVert(rect.x + rect.w, rect.y + rect.h, u2, v2);
    AddVert(rect.x, rect.y + rect.h, u1, v2);
}

该库构建一个顶点向量,然后最终每帧渲染顶点缓冲区。

作为参考,这里是来自 OpenGL 示例渲染器的相同函数:

void OpenGL::AddVert( int x, int y, float u, float v )
{
    m_Vertices[ m_iVertNum ].x = ( float ) x;
    m_Vertices[ m_iVertNum ].y = ( float ) y;
    m_Vertices[ m_iVertNum ].u = u;
    m_Vertices[ m_iVertNum ].v = v;
    m_Vertices[ m_iVertNum ].r = m_Color.r;
    m_Vertices[ m_iVertNum ].g = m_Color.g;
    m_Vertices[ m_iVertNum ].b = m_Color.b;
    m_Vertices[ m_iVertNum ].a = m_Color.a;
    m_iVertNum++;
}

void OpenGL::DrawTexturedRect(Gwen::Texture* pTexture, Gwen::Rect rect, float u1, float v1, float u2, float v2)
{
    GLuint* tex = ( GLuint* ) pTexture->data;

    // Missing image, not loaded properly?
    if ( !tex )
    {
        return DrawMissingImage( rect );
    }

    Translate(rect);
    GLuint boundtex;
    GLboolean texturesOn;
    glGetBooleanv( GL_TEXTURE_2D, &texturesOn );
    glGetIntegerv( GL_TEXTURE_BINDING_2D, ( GLint* ) &boundtex );

    if ( !texturesOn || *tex != boundtex )
    {
        Flush();
        glBindTexture( GL_TEXTURE_2D, *tex );
        glEnable( GL_TEXTURE_2D );
    }

    AddVert(rect.x, rect.y, u1, v1);
    AddVert(rect.x + rect.w, rect.y, u2, v1);
    AddVert(rect.x, rect.y + rect.h, u1, v2);
    AddVert(rect.x + rect.w, rect.y, u2, v1);
    AddVert(rect.x + rect.w, rect.y + rect.h, u2, v2);
    AddVert(rect.x, rect.y + rect.h, u1, v2);
}

u我知道 Vulkan 将纹理坐标从 0.0 带到 1.0 ,这就是我除以v纹理大小的原因512 x 512。我也知道 Vulkan 使用图像的左下角,0,0这就是我翻转 Y 坐标的原因。可悲的是,我仍然得到不正确的输出。我尝试了很多组合texCoord.xtexCoord.y但我永远无法获得正确的输出。有谁知道我在这里可能做错了什么?

编辑 将纹理除以 128 而不是 512 产生了正确的结果。我不明白为什么这解决了我的问题。纹理大小确实是 512x512 单位,所以除以 512 应该给我一个 0.0-1.0 的范围?相反,我只除以纹理大小的 1/4 的 128 来得到我的 0.0-1.0 范围?

vertices.back().texCoord.x = (u / 128);
vertices.back().texCoord.y = (v / 128);

标签: c++openglvulkannormalizeuv-mapping

解决方案


As it turns out Vulkan and OpenGL share the same physical 0,0 position when it comes to UV coordinates. Flipping the y value was unnecessary. Finally what gave me the correct output was to divide the size of the texture by 1/4th or 128 instead of 512. For some reason this produced the correct output and all the UV's lined up properly.

correct formulas:

vertices.back().texCoord.x = (u / 128);
vertices.back().texCoord.y = (v / 128);

推荐阅读