nuklear
nuklear copied to clipboard
Add subpixel API.
This PR tries to provide subpixel drawing API as discussed in #425.
In this PR, a new macro, NK_ENABLE_SUBPIXEL_API
is proposed. User can turn-on subpixel API by defining this macro before ALL inclusion of nuklear.h
.
When this macro is defined, the following changes are made inside nuklear:
- All draw command structs (except
nk_command_custom
) will usefloat
instead ofshort
/unsigned short
, usenk_vec2
instead offnk_vec2i
. - All draw command routines (except
nk_push_custom
) will have asubpixel
counterpart. For example, in addition tonk_stroke_polyline
,nk_stroke_polyline_subpixel
will be defined. In these subpixel version, there will be no narrowing fromfloat
toshort
.
No documentation is changed currently.
Thanks @itsuhane . An important question - it seems to me, that now it behaves differently than you proposed in #425:
As a proposal, there could be a global macro like
NK_VERTEX_VALUE_TYPE
, which defaults toshort
, but allow user to override withfloat
to support subpixel drawing. Current draw routines will keep the casting to make sure they don't broke any pixel-perfect drawing for UI elements. Meanwhile, they will have subpixel counterparts,nk_stroke_polyline_subpixel
for example, for any user who want advanced control on their drawing.
use case | NK_ENABLE_SUBPIXEL_API defined |
NK_ENABLE_SUBPIXEL_API NOT defined |
---|---|---|
old codebase | all pixel-perfect calculations break (as nk_stroke_polyline behaves differently than originally) |
no change, everything works |
new codebase | works as expected (nk_stroke_polyline behaves the same as nk_stroke_polyline_subpixel ) |
the old Nuklear behavior (i.e. internal conversion float -> short ) |
Thinking about this further we might actually afford making nk_stroke_polyline
(and others) behave differently (i.e. not convert float
to short
internally) if and only if NK_ENABLE_SUBPIXEL_API
(or rather NK_ENABLE_SUBPIXEL_PRECISION
or alike as it has nothing to do with API) is defined (by default this macro won't be defined). So actually there shouldn't be any need for _subpixel()
counterparts and the above table would look like this:
use case | NK_ENABLE_SUBPIXEL_API defined |
NK_ENABLE_SUBPIXEL_API NOT defined |
---|---|---|
old codebase | all pixel-perfect calculations break (as nk_stroke_polyline behaves differently than originally) |
no change, everything works |
new codebase | works as expected (nk_stroke_polyline doesn't do any float -> short conversions internally) |
the old Nuklear behavior (i.e. internal conversion float -> short ) |
Btw please also bump version accordingly :wink:.
Thanks for your quick response!
Since we changed the internal representation for struct nk_command_*
, some pixel-perfect version API must be changed accordingly. But their behavior was not changed: In the old codebase, we perform float
-to-short
conversions when creating these command structs. But before drawing, these short
data are converted back to float
, for example in line 1294 in nk_convert
:
https://github.com/vurtun/nuklear/blob/bb327b97a98d865984263ce6a3d8c50739f8dcb1/src/nuklear_vertex.c#L1291-L1297
Effectively, the float
-to-short
conversion is just rounding-off the decimal parts. I think we can safely use float
in commands without breaking the pixel-perfect drawing behavior.
Originally, I was thinking about having a macro named NK_VERTEX_VALUE_TYPE
, and user can define it to float
. However, there are three types involved in the command structs: nk_vec2i
, short
and unsigned short
, if the user chooses float
, unsigned float
is neither meaningful nor legal in C. And in some compilers, unsigned float
will be interpreted as unsigned int
without giving an error. That's why I choose a different macro.
If we give up the conversion, all UI rendering will no-longer be pixel-perfect. I believe it will introduce artifacts. If there are artifacts, then we cannot easily remove the conversion. Two separate set of drawing API must co-exist. I will try subpixel UI drawing first and make some screenshot.
But in some sense, I agree to have only one set of implementation because my current PR contains massive code duplication. Can I create some macro ("templated C") to help elide the duplication ?
If we give up the conversion, all UI rendering will no-longer be pixel-perfect. I believe it will introduce artifacts.
This might be the case, but I think there is one problem which I'm reluctant to digest :wink:. Namely, that Nuklear users won't have any clue which API (one of pixel-perfect and subpixel) in which case to use as they won't know how it behaves and how to combine the APIs. We must not introduce such problem at any cost.
I will try subpixel UI drawing first and make some screenshot.
This would be great - and once you're at it, try as many backends as you can to get some overview. This will be much appreciated.
Can I create some macro ("templated C") to help elide the duplication ?
Sure, just make some proposals a and we'll discuss it. Usually one comes with the best ideas when working with code, but not up front, so I won't comment technically on this until there is some practical demonstrations :wink:.