0
\$\begingroup\$

When I try to display an image that is 400 pixels wide and 800 pixels high, it is not displayed this way. Instead it is diplayed like this: Instead it is displayed like this

You can see at the bottom and a few pixels right to the phone some thin white lines, I did not add this manually and it is not part of the picture, the picture is perfectly cropped around the phone.

When in my fragment shader I add + vec4(1, 1, 1, .5) it shows the area that the phone should have covered. Image

Code for creation of an object that holds info about the image:

GuiTexture phone = new GuiTexture(loader.loadTexture("phone_cropped"), Display.getWidth() / 2, Display.getHeight() / 2, 2, 400, 800);

The loadTexture method:

public int loadTexture(String fileName) {
    Texture texture = null;
    try {
        texture = TextureLoader.getTexture("PNG", new FileInputStream("res/" + fileName + ".png"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    int textureID = texture.getTextureID();
    textures.add(textureID);
    return textureID;
}

The line that calls the render class to render the image

guiRenderer.render(guis);

The transformation matrices that the image is multiplied by:

float width = gui.getWidth() / 2;
        float height = gui.getHeight() / 2;

        Matrix4f modelMatrix = new Matrix4f();
        modelMatrix.m00 = 2.0f / (float) Display.getWidth();
        modelMatrix.m11 = 2.0f / (float) Display.getHeight();
        modelMatrix.m30 = -1;
        modelMatrix.m31 = 1;

        shader.loadModel(modelMatrix);

        Matrix4f transformationMatrix = Maths.createTransformationMatrix(
                new Vector2f(
                           gui.getxPos(),
                        - (gui.getyPos())
                ), gui.getRotation()
                ,new Vector2f(
                        width,
                        height
                )
        );

        shader.loadTransformation(transformationMatrix);

Vertex shader code:

gl_Position = modelMatrix * transformationMatrix * vec4(position, 0.0, 1.0);
textureCoords = vec2((position.x+1.0)/2.0, 1 - (position.y+1.0)/2.0);

This does not happen to all images, when I load in an image that is square and I try to display it with width 400 and height 800 it works perfectly. Image

With different images it yields different extra space.

All images are .png. The phone image is 1009x2057 pixels. I also tried to use a phone that was 2048 pixels high (1006x2048) since this is a power of 2, that still yields a white line on the side but does look better: image

The square (3rd image) that was elongated to look like a rectangle and does display correctly is 256 x 256 pixels.

All displayed images have a slight rotation because without rotation the little white thin lines don't always show up, the rotation did not change anything about the images.

To load images I use slick utils TextureLoader class.

\$\endgroup\$
3
\$\begingroup\$

You load your images like this:

texture = TextureLoader.getTexture("PNG", new FileInputStream("res/" + fileName + ".png"));

However if you read through the source code of slick you'll see that internally it is represented as TextureImpl which was the following documentation.

A texture to be bound within JOGL. This object is responsible for keeping track of a given OpenGL texture and for calculating the texturing mapping coordinates of the full image. Since textures need to be powers of 2 the actual texture may be considerably bigged that the source image and hence the texture mapping coordinates need to be adjusted to matchup drawing the sprite against the texture.

So since neither the height nor the width is a power of two slick will scale up the texture to the closes power of two. So if the image is 400x800, the resulting texture will be 512x1024 where the created space will be filled with a transparent black color. It also seems that slick loads the texture slightly incorrectly where some of the right wraps around to the left side of the textures creating that "line". That same happens at the top of the texture where it will wrap to the bottom. So the "line" is actually the volume and power buttons on the iPhone.

To avoid this you have at least three options:

  • Always load images that have sides that are power of two.
  • Use Slick's calculated texture coordinates, e.g. texture.getHeight().
  • Load the images yourself and avoid the power of two limitation.
\$\endgroup\$
  • \$\begingroup\$ Regarding the last option, he could use the jgli lib I did \$\endgroup\$ – elect Jan 21 '16 at 8:25
  • \$\begingroup\$ Thanks a lot, I decided to use the last option, if I have an image that is not square, I simply make it square. In game it will then be transformed to not be square anymore. \$\endgroup\$ – The Coding Wombat Jan 21 '16 at 19:53
  • \$\begingroup\$ @Christer I have also tried the 2nd method and that also works, I think it's better since I do not have to manually make images square. \$\endgroup\$ – The Coding Wombat Jan 21 '16 at 20:30
  • \$\begingroup\$ @TheCodingWombat Just remember that some of the left and top hand side of the texture gets cut off. \$\endgroup\$ – Christer Jan 21 '16 at 20:42
  • 1
    \$\begingroup\$ @TheCodingWombat I'm sorry, I was wrong. It doesn't actually seem to cut off any of the sides, only duplicate them. Also the duplication seems to be one pixel wide/tall and only happen sometimes. So ignore what I said. Here is an example image: imgur.com/J1lASKG \$\endgroup\$ – Christer Jan 21 '16 at 21:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.