New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[textures] DrawTextureEx() is not sub-pixel precise #527
Comments
Antialiasing tends to produce blurry graphics and harm pixel art aesthetics, though. Maybe this feature should only be optional. IMO, jumping from one pixel to another is okay. For instance, check this for how in Towerfall, the characters move 1 pixel at a time. There's no sub-pixel movement. |
You are right it depends on the use case. And maybe it isn't even needed. I compared the movement of a sprite to the movement of a circle (with DrawCircleV), both use float coordinates. The movement of the circle is smoother. Now the only difference is that DrawCircleV directly calls rlVertex2f which takes float values whereas DrawTexturePro (which is called by all DrawTexture functions) expects a rectangle (int values). I think that the DrawTexture functions should skip rectangles in favor of Vector2s, so the float values are not touched before being passed to OpenGL. And for the record. This is the kind of jumpy movement I mean: It should be smooth. You can also observe similar problems in the core/camera2d example, especially when zooming out and moving the block continuously. |
Keep thinking but not sure how to fix this, there is no easy solution...
typedef struct Rectangle {
float x;
float y;
float width;
float height;
} Rectangle;
typedef struct Rectangle {
#if defined(SUPPORT_FLOAT_RECTANGLE)
float x;
float y;
float width;
float height;
#else
int x;
int y;
int width;
int height;
#endif
} Rectangle;
Functions affected by this change: void DrawRectangleRec(Rectangle rec, Color color);
void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color);
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4);
void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color);
bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2);
bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec);
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
bool CheckCollisionPointRec(Vector2 point, Rectangle rec);
void ImageCrop(Image *image, Rectangle crop);
void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);
void ImageDrawRectangle(Image *dst, Vector2 position, Rectangle rec, Color color);
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint);
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint);
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); Any other idea? |
I think 1 is probably the best among these. Those (like me) who want integer-precision can just make sure all their floats are integers. |
+1 for using floats in rectangle. Also add function Getting pixel-art aesthetic right would need some better solution anyways. Currently with high-resolution displays you need to change the snapping amount and adjust them to match image scaling. More likely you will need to snap every 4px or more to make the "pixel-art" look right. Also, don't forget about the problems moving Camera2D. |
I think the best way to support pixel art graphics is to have virtual canvases. That is, have a virtual screen of size (320, 180), where all the pixels are drawn. Then each pixel in this virtual buffer is drawn scaled up for 16:9 screens. This way, the physics code does not need to deal with anything other than a (320, 180) screen, but the display can do any 16:9 screen or even 16:10 with letterboxing. Currently, in raylib, I have to pass in a scale parameter to every DrawTexture call and multiply my position vectors as well, which imo is not very convenient. A virtual canvas would be a nice feature. But I understand if this is too complex for raylib. |
@sherjilozair @egonelbre thank you very much for your feedback! I think I'll go for 1. @sherjilozair virtual canvas has already been available in raylib for some time, it can be accomplished with a RenderTarget2D. You can see create a 320x180 target to render to and then use that texture to draw to fullscreen. Some reference could be found here, despite using same size for target and screen. Mouse input could be scaled with SetMouseScale(). One usage example could be found on my tool rFXGen, it has a button to scale window to double size... while internal render size keeps being original size. |
Implemented proposed solution 1. in commit 6324697 This change is more critical than I expected, it could break some things... let's see... |
Just note here that changing |
As you can see here:
raylib/src/textures.c
Line 2023 in c51203a
Some kind of sub-pixel rendering or anti-aliasing here would be good!
The text was updated successfully, but these errors were encountered: