I'm writing a Vulkan Renderer for GWEN (GUI Without Extravagant Nonsense) and having issues getting texture coordinates to match up.
Here's what I should see:
And this is what is currently happening:
The texture displayed in the center is the image we're using for the GUI, I made sure to test render it to a quad to make sure I was loading it properly.
The structure of the GUI appears to be correct which leads me to believe the UV coordinates are incorrect. Specifically the Y coordinate since, from what I can tell, X appears okay.
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);
}
The library builds a vector of vertices then finally renders the vertex buffer each frame.
For reference, here is the same function from the OpenGL Sample Renderer:
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);
}
I understand Vulkan takes texture coordinates from 0.0 to 1.0 which is why I divide u
and v
by the size of the texture 512 x 512
. I also understand Vulkan uses the bottom left corner of the image as 0,0
which is why I flip the Y coordinate. Sadly I still get the incorrect output. I've tried many combinations for texCoord.x
and texCoord.y
but I can never get the correct output. Does anyone know what I might be doing wrong here?
EDIT Dividing the texture by 128 instead of 512 produced the correct results. I don't understand why this solved my issue though. The texture size is indeed 512x512 units so dividing by 512 should give me a 0.0-1.0 range? Instead I only divide by 128 which is 1/4th the size of the texture to get my 0.0-1.0 range?
vertices.back().texCoord.x = (u / 128);
vertices.back().texCoord.y = (v / 128);
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With