LaurentGomila/SFML — Issue #154: Wrong texture coordinates on sf::Sprite
Author: Leonhart
Created: 2012-01-06 17:14:39+00:00
State: open

Hello,

After trying to use vertex shaders (thx for the new graphics API btw), I realized that there is a problem with the texture coordinates on sf::Sprite. Here is a minimal code that should work :

```c++
#include
#include

int main() {

/////////////////// Init stuffs /////////////////////////

sf::RenderWindow win(
sf::VideoMode(1920, 1080),
"Test SFML shader window",
sf::Style::Fullscreen);

sf::Texture tex;
if (!tex.LoadFromFile("shrTest.png")) {
std::cout << "unable to load the texture" << std::endl;
return 1;
}

sf::Sprite spr(tex);
spr.SetTextureRect(sf::IntRect(0.0, 0.0, 250.0, 250.0));

sf::Shader shr;
if (!shr.LoadFromFile("testShr.vert", "testShr.frag")) {
std::cout << "unable to load the shader" << std::endl;
return 1;
}

/////////////////// Render loop /////////////////////////

while (win.IsOpened()) {

sf::Event evt;
while (win.PollEvent(evt)) {
if (evt.Type == sf::Event::KeyPressed) {
if (evt.Key.Code == sf::Keyboard::Q) {
win.Close();
}
}
}

win.Clear();
win.Draw(spr, &shr);
win.Display();
}

return 0;
}
```

With the following shader files. They only display what a basic sf::Sprite should display :

```glsl
#version 150 compatibility

void main(void) {
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
```
```glsl
#version 150 compatibility

uniform sampler2D tex;

void main() {
vec4 color = texture2D(tex, gl_TexCoord[0].st);
gl_FragColor = color;
}
```

The result is a sprite that appears totally black, or green depending on the machine. So after some digging I found that the problem comes from the way the texture coordinates are computed in sf::Sprite. And more precisely the **UpdateTexCoords** function.

Here is the current one :

```c++
void Sprite::UpdateTexCoords()
{
float left = static_cast(myTextureRect.Left);
float right = left + myTextureRect.Width;
float top = static_cast(myTextureRect.Top);
float bottom = top + myTextureRect.Height;

myVertices[0].TexCoords = Vector2f(left, top);
myVertices[1].TexCoords = Vector2f(left, bottom);
myVertices[2].TexCoords = Vector2f(right, bottom);
myVertices[3].TexCoords = Vector2f(right, top);
}
```

And here is a modified version that fixes the problem. It simply computes the tex coords inside the range [0,1] instead of passing pixels values. It works well so far, though it might not be the most optimal way of doing things (?).

```c++
void Sprite::UpdateTexCoords()
{
float width = 1.0;
float height = 1.0;

if (myTexture) {
width = static_cast(myTexture->GetWidth());
height = static_cast(myTexture->GetHeight());
}

float left = static_cast(myTextureRect.Left) / width;
float right = left + myTextureRect.Width / width;
float top = static_cast(myTextureRect.Top) / height;
float bottom = top + myTextureRect.Height / height;

myVertices[0].TexCoords = Vector2f(left, top);
myVertices[1].TexCoords = Vector2f(left, bottom);
myVertices[2].TexCoords = Vector2f(right, bottom);
myVertices[3].TexCoords = Vector2f(right, top);
}
```