It's not that difficult or weird actually.
Rectangles and lines drawn at 0,0 will be blurry and should be placed at .5,.5 instead because that's how the coordinate system works.
Images and text drawn at .5,.5 will be blurry and should be placed at 0,0 instead because that's how the coordinate system works.
Meshes drawn at 0,0 will not be blurry. Meshes drawn at .5,.5 won't be blurry either, but will look a little bit weird. Unless they have a texture, then you gotta add .5. Or not. I can't remember. Because that's how the coordinate system works.
There are perfectly good explanations for why things are this way. It apparently all boils down to the fact that that's the way the coordinate system works and the best APIs are those with leaky abstractions.
Coordinates for lines vs points (and pixel grid alignment for points)
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
Filled rectangles drawn at 0,0 will have no problem, no blurriness and no ambiguity hazards.grump wrote: ↑Mon May 03, 2021 12:39 pm It's not that difficult or weird actually.
Rectangles and lines drawn at 0,0 will be blurry and should be placed at .5,.5 instead because that's how the coordinate system works.
Images and text drawn at .5,.5 will be blurry and should be placed at 0,0 instead because that's how the coordinate system works.
In my post above, when I talked about rectangles I meant filled rectangles. Rectangles and circles drawn in line mode use the line algorithm and are subject to the same treatment as lines. I forgot to specify that.
Anyway, stingund's concerns are not about blurring. The OP's purpose is to obtain crisp pixels, and the complaint is about what happens when you request "rough" line style, precisely in the situations where it would be blurry if you didn't. I'm trying to explain why the result is not clear-cut, why the unexpected result in the OP should actually be expected, and why the API is consistent (in fact, "too" consistent, in that rough mode lines are treated the same way as smooth mode lines, which is somewhat unexpected for someone like stingund who has expectations based on purely integer coordinate systems).
My point here is that such a mesh may or may not cover the top left pixel row, depending on how the hardware rounds. Moreover, the texture's pixels, if drawn with filter "none", may similarly be rounded up or down, even within the texture, and cause distortion. I initially was among the people who thought that this problem was preventable and was therefore a bug, even reported it, and the answer left clear that it was a driver problem and that there was nothing Löve can do if it wants to take advantage of hardware acceleration.
Exactly that.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
There is no "pixel [2,2]". At coordinate [2,2] is the upper left corner of the square region covering [[2,2],[3,3]]. The exact center of this square is at [2.5,2.5]. There exists no integer index directly referring to this "pixel"; it is an area on a continuous surface.
LÖVE is not PICO-8. As love.graphics clearly indicates:stingund wrote: ↑Mon May 03, 2021 12:43 am Love2D is a 2D platform, like pico-8. If you specify you want a point or a line at (3,3), that's where it should be. This is the API contract that should be presented to the user. And from reading the description of the various functions in the API, this is what seems to be implied.
(emphasis mine)LÖVE's coordinate system is rooted in the upper-left corner of the screen, which is at location (0, 0) [...] the location (0, 0) aligns with the upper-left corner of the pixel as well, meaning that for some functions you may encounter off-by-one problems in the render output when drawing 1 pixel wide lines. You can try aligning the coordinate system with the center of pixels rather than their upper-left corner. Do this by passing x+0.5 and y+0.5
PICO-8 is a retro environment, reflecting the days back when computers only did integer numbers. There was no 2.5, so pixels could be "referred to" by their integer coordinates. LÖVE is a modern environment. The canvas you draw on is a continuous 2-dimensional surface, its coordinates are floating point numbers with approximate, fractal precision. In this model, there is no 2! The exact number 2 might not actually exist! In Lua floating point, there are only three exact quantities: 0, 1, and NaN. All other numbers are approximations.
Lua does also have integers, where the exact number 2 does indeed exist. But if you peruse the LÖVE docs, you'll see that the drawing function arguments are typed as "number":
So there's no 2.Number represents real (double-precision floating-point) numbers.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
Xii, I generally agree with your post, but this part:
Floating-point numbers can exactly represent many integers, and many fractions as long as the denominator of the simplified fraction is a power of two.
In particular, double-precision floating-point numbers can exactly represent all integers from -9007199254740992 to 9007199254740992 inclusive. The first integer they can't exactly represent is 9007199254740993 = 2^53 + 1.
Numbers like 0.2 = 1/5, however, can't be exactly represented, because the denominator is not a power of 2, and they need to be approximated. The closest approximation is the fraction 3602879701896397/18014398509481984 = 0.200000000000000011102230246251565404236316680908203125 and that's the actual number stored in a float when we tell it to store 0.2. In that sense, 0.2 does not "exist" as a double-precision floating-point number; but 2 does, because it can be exactly represented, and 0.200000000000000011102230246251565404236316680908203125 is also representable as a double-precision floating-point number. Other simpler examples: 0.75, 3.125; 0.8642578125.
is wrong.Xii wrote: ↑Mon May 03, 2021 4:36 pm The canvas you draw on is a continuous 2-dimensional surface, its coordinates are floating point numbers with approximate, fractal precision. In this model, there is no 2! The exact number 2 might not actually exist! In Lua floating point, there are only three exact quantities: 0, 1, and NaN. All other numbers are approximations.
Lua does also have integers, where the exact number 2 does indeed exist. But if you peruse the LÖVE docs, you'll see that the drawing function arguments are typed as "number":
So there's no 2.Number represents real (double-precision floating-point) numbers.
Floating-point numbers can exactly represent many integers, and many fractions as long as the denominator of the simplified fraction is a power of two.
In particular, double-precision floating-point numbers can exactly represent all integers from -9007199254740992 to 9007199254740992 inclusive. The first integer they can't exactly represent is 9007199254740993 = 2^53 + 1.
Numbers like 0.2 = 1/5, however, can't be exactly represented, because the denominator is not a power of 2, and they need to be approximated. The closest approximation is the fraction 3602879701896397/18014398509481984 = 0.200000000000000011102230246251565404236316680908203125 and that's the actual number stored in a float when we tell it to store 0.2. In that sense, 0.2 does not "exist" as a double-precision floating-point number; but 2 does, because it can be exactly represented, and 0.200000000000000011102230246251565404236316680908203125 is also representable as a double-precision floating-point number. Other simpler examples: 0.75, 3.125; 0.8642578125.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
Oh, ok. I've been taught to never assume floating point is exact, ever.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
It's interesting, that Lua has no integer data type, but there is small different:
Somehow 10.0 will be same as 10, but it prints it in other way.
Code: Select all
a = 10
b = 100/10 -- looks like 10
print(a) -- prints 10
print(b) -- prints 10.0
print(tostring(a==b)) -- prints true
Re: Coordinates for lines vs points (and pixel grid alignment for points)
See what Gump said, he understood exactly what I meant.
To be clear, this wasn't to say that how the underlying hardware doesn't matter to ANYONE, it absolutely matters to someone writing a cross-platform graphic API. But once an abstraction layer has been drawn, the design of the API should be such that you should not have to care how the underlying hardware works. Sure, sooner or later, you will have to debug an issue that requires that knowledge, but if the code you write above the abstraction layer frequently has to take underying details into account, then the cross-platform API is not proving useful.
As for Vulkan, I don't know what you consider a hit, but it is a fairly painful API to program against compared to Metal, Dx12, gnm (ps4), etc. And Vulkan, as other APIs, does its best to create hardware independent constructs and concepts (even though those are modelled after modern hardware) so that you, the application programmer, can write user code and shaders without having to do unique work per platform. In practice, you often have to specialize bits of code and shader code per platform, either for bugs or to get more performance. But compute and 3D graphics are complex things that eventually require specialization. Love2D is a 2D graphic API. We're not talking about the same level of complexity here. I hope we can agree on that!For exemple, why do you think Vulkan is such a hit ?
Having worked on consoles for a long time, I have had to debug black boxes frequently, and have had to take arcanely obscure platform differences into account many times (and I really like doing that). But if/when I design a cross-platform API, I put every effort into ensuring I can provide consistent behaviour across platforms.Maybe this small point stuff seem pointless, but you will encounter a lot of much more bigger black boxes that you wish you could peek inside.
Well not really, there has to be agreement first. Otherwise any changes I would make would not be accepted. It's okay to discuss you know!Also if a behavior doesn't fit what you like, just program it !
Love2d source code is avaible here if you want to know what's going on: https://github.com/love2d/love
--
Having said this, I need to point out that the discussion about consistent behaviour I had with pgimeno was not meant to be about cross-platform development and whatnot, but rather about the results across different axis aligned primitive types. But it seems to have taken a turn that way. That's a bit off-topic!
Always great seeing people have enough passion to take the time to express their opinions in a thread. Not ignoring answers, just a bit busy atm to properly keep up.
Last edited by stingund on Tue May 04, 2021 8:37 am, edited 2 times in total.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
Oh I hadn't seen this in the docs actually. Odd that I missed it, since this is the sort of information I was looking for.LÖVE's coordinate system is rooted in the upper-left corner of the screen, which is at location (0, 0) [...] the location (0, 0) aligns with the upper-left corner of the pixel as well, meaning that for some functions you may encounter off-by-one problems in the render output when drawing 1 pixel wide lines. You can try aligning the coordinate system with the center of pixels rather than their upper-left corner. Do this by passing x+0.5 and y+0.5
You are underestimating the precision of floating point numbers by a lot! You have to get at much higher quantities before no longer being able to match integer.In Lua floating point, there are only three exact quantities: 0, 1, and NaN. All other numbers are approximations.
It looks like this thread has gotten a lot of activity. I haven't been able to catch-up to everything, but it looks like I had missed some portions of the docs. I assumed a few things about the contract love2D was exposing, I'll familiarize myself with the docs better.
Re: Coordinates for lines vs points (and pixel grid alignment for points)
Can't reproduce. I get 10 both times, not 10.0.darkfrei wrote: ↑Tue May 04, 2021 7:05 am It's interesting, that Lua has no integer data type, but there is small different:Somehow 10.0 will be same as 10, but it prints it in other way.Code: Select all
a = 10 b = 100/10 -- looks like 10 print(a) -- prints 10 print(b) -- prints 10.0 print(tostring(a==b)) -- prints true
Edit: Ah, it happens in Lua 5.3, which has separate integer and float types. Löve only supports 5.1.
Last edited by pgimeno on Tue May 04, 2021 3:21 pm, edited 1 time in total.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Coordinates for lines vs points (and pixel grid alignment for points)
I mean, at its core, it uses OpenGL, and that's a 3D API... call it a simplification or a crutch that löve doesn't expose everything to do 3D stuff with, but it's something that's possible nevertheless.
To me, at least, there were posts in this thread that explained completely why the differences between drawing non-infinitessimally small rectangles that the APIs call points, non-infinitessimally thin rectangles the API calls lines and "regular" rectangles seemingly behave differently due to the assumed definitions of their positioning.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Who is online
Users browsing this forum: No registered users and 3 guests