kitao / pyxel

A retro game engine for Python
MIT License
13.43k stars 812 forks source link

Non pixel perfect pixels on the right side of the screen #513

Closed ingobeans closed 2 months ago

ingobeans commented 5 months ago

I'm encountering a really strange problem, which seems to be consistent for all pyxels apps for me. The left side of the screen is perfectly pixel perfect, but the sprites and tiles to the right of the screen get all wobbly with non uniform pixel sizes.

Example from my project: example

It happens both when the game is windowed, but is even more noticeable in full screen. I downloaded an example (jump_game, where I also encountered the problem, but only when the re scaling the window, meanwhile in my own app the problem was always persistent.)

Here is a very stripped down version of my game: pyxel_test.zip

AwkwardSquid3 commented 5 months ago

I've also experienced problems with this lol

gomio commented 5 months ago

True, it happens from version 2.x.x, in my case for resolutions >720p and only in some machines. Very strange and annoying problem.

ingobeans commented 5 months ago

Do you mean it doesn't happen in previous versions? If so would using an older version of Pyxel be a viable option? Thanks!

gomio commented 5 months ago

Do you mean it doesn't happen in previous versions? If so would using an older version of Pyxel be a viable option? Thanks!

Yes, 1.9 don't have this issue (in my experience).

kitao commented 5 months ago

Starting from version 2, Pyxel has been utilizing OpenGL or OpenGL ES for rendering to improve performance and add drawing effects. During this process, the screen is managed as a texture in OpenGL and a polygon on which the texture is applied. It is believed that discrepancies caused by this management are the root cause of this issue.

However, I have not encountered this phenomenon in my operating environment, so it seems that it might be occurring in systems where the OpenGL (or OpenGL ES) drivers or GPU are outdated.

Could you please inform me about the type and version of the OS on which Pyxel is running?

By the way, you can check this occurs or not by the following code easily:

import pyxel
pyxel.init(160, 120)
for i in range(pyxel.height // 2 + 1):
    pyxel.line(0, i * 2, pyxel.width, i * 2, 8)
for i in range(pyxel.width // 2 + 1):
    pyxel.line(i * 2, 0, i * 2, pyxel.height, 13)
pyxel.show()
kitao commented 5 months ago

I've been conducting some experiments and my current hypothesis is that the OpenGL shader's built-in variable gl_FragCoord is supposed to be set with a +0.5 offset, meaning (0,0) should actually be represented as (0.5,0.5), according to the specification. However, I suspect that there might be some drivers with incorrect implementations that do not add this +0.5 offset.

In such cases, OpenGL would end up referencing the color at the boundary between pixels in the screen texture, causing a slight discrepancy in the coordinates being referenced due to this minor error.

To verify this, this code could be modified in the following way to see if the behavior changes. Unfortunately, I'm stuck because I don't have access to an environment where I can replicate the issue.

    screenTexCoord = (screenFragCoord + 0.1) / u_screenSize;
ingobeans commented 5 months ago

Hello! I'm on Windows 11 and I have a 3060ti GPU. I tried downloading Pyxel and changing the line you sent and building the project, but the problem still occurs for me. I think I built it right, but I can't really be sure, I just installed all the missing dependencies (rustup.rs,cmake,llvm), until I could do pip install --upgrade . in the Pyxel folder. (I also made sure to uninstall the normal pyxel first)

kitao commented 5 months ago

@ingobeans Thank you for your assistance. Your verification is incredibly helpful.

Running make install should build Pyxel and install the Python wheel as well. Also, if you are uncertain about the update, you might want to try changing the + 0.1 part to something like + 20.1 to see if the display position shifts by 20 pixels on the screen. This could be a convenient method to check the behavior.

ingobeans commented 5 months ago

image I turned up the value to + 80.1 here. You can see the pixels in the grid still not being pixel perfect to the right.

kitao commented 5 months ago

Could you try + 0.5 and + 0.6? I'd like to know the situation changes or not.

ingobeans commented 5 months ago

0.5: image 0.6: image

It seems that with 0.5 and 0.6 the entire game window is non pixel perfect, rather than just the right side.

kitao commented 5 months ago

Thank you. How large is this app's screen? And what happens if the screen size is changed into 256x256?

ingobeans commented 5 months ago

That project is running on 384x216. When running on 256x256 all pixels seem to be pixel perfect, However re-scaling the window, even though it adds borders, the far right pixels become non pixel perfect image

kitao commented 5 months ago

Thank you again. Now I'm doubting a high DPI setting. Could you try to add a flag to this line like this:

SDL_Init(SDL_WINDOW_ALLOW_HIGHDPI as Uint32 | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER)
kitao commented 5 months ago

I've already released Pyxel 2.0.6 which includes high DPI modification though I'm not sure it improves the situation. Anyway please try it.

gomio commented 5 months ago

I've already released Pyxel 2.0.6 which includes high DPI modification though I'm not sure it improves the situation. Anyway please try it.

Using your test still happens.

Clipboard01

kitao commented 5 months ago

@gomio Could try to change the OS's screen scale to an integer multiple of the scale like 200% or 400% once?

I want to isolate whether it's due to the OS's screen settings or not.

gomio commented 5 months ago

Windows 10 Pro 64, Intel HD Graphics 530.

gomio commented 5 months ago

Dou you mean set desktop at 1600x900 for example?

gomio commented 5 months ago

With desktop at 1600x900 the output is correct.

gomio commented 5 months ago

At 1366x768 seems also OK.

gomio commented 5 months ago

At 1920x1200 (my native resolution) bad.

ingobeans commented 5 months ago

I haven't had time to test but I have also been running on 1920x1080

kitao commented 5 months ago

I'd like to know the scale of the screen. Because if the screen resolution is the same as display's native size like 1920x1080, if it's displaying scale is 125%, there's no way to realize pixel perfect. On Windows, those are the different setting parameters.

ingobeans commented 5 months ago

My monitor is 1920x1080 100%

kitao commented 5 months ago

Thank you. I will continue the investigation.

nopid commented 3 months ago

Same issue here with Pyxel 2.0.9 on a Linux system (works fine on Mac M1).

bugB

pyxel.init(300, 16, display_scale=4)

The GPU is an NVIDIA GeForce GTX 1650 with NVIDIA-SMI 550.54.14. Resolution is 1920x1080.

Changing the precision of float for GLES shader fixed the problem on my system!

bugA

I replaced mediump with highp inside https://github.com/kitao/pyxel/blob/a3dc591ab1b881d780925a6e45a831f1fb827f2a/rust/pyxel-engine/src/shaders/gles_version.glsl#L2

kitao commented 3 months ago

@nopid Thank you. This is a really useful information. After trying highp, I'll include the change in the next release.

kitao commented 2 months ago

It seems that there's no update. Let me close this issue because I've already taken a measure for it. If the same issue occurs, re-open this issue.