3 ms·
TL;DR: that's tough, sigh. For the Sciter project ( https://sciter.com https://sciter.com ) I did exactly that: created abstract graphics C++ library that wrap
by c-smile 8y ago
TL;DR: that's tough, sigh.
For the Sciter project ( https://sciter.com https://sciter.com ) I did exactly that: created abstract graphics C++ library that wraps all supported backends:
1. Direct2D and GDI+ on Windows;
2. Skia on Windows, MacOS and Linux;
3. Cairo on Linux/GTK;
4. CoreGraphics on MacOS;
So I hope I know the subject, and here are few comments:
Biggest problem.
Two significantly different drawing models:
GPU based libraries (Direct2D/DirectX, Skia/OpenGL): these use batch rendering - calls like graphics::fill_rect(...) just produce record in command stream that gets sent to GPU for rendering. Kind of asynchronous rendering.
CPU libraries - rasterization of graphic primitives to a bitmap / framebuffer. These are Cairo, GDI+ and CoreGraphics.
While GPU and CPU ways of rendering can be wrapped into single, unified interface but there are nuances.
GPU libraries update target surface in full. Even when you need to change one pixel - you send full batch to GPU to render whole thing all together. (there are optimizations in that but in 99% that is that way)
CPU libraries update just that pixel on bitmap. But when you need to update whole window on high-DPI monitors ...
Number of pixels on 300ppi screen is 9 times larger than on 96ppi screen. Our current CPUs and buses are still from "96ppi era". GPU is the only option with high-DPI.
Pixel composition operations (https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/...) are achievable on CPU but there is no target bitmap on GPU in common sense - not clear what these mean there, etc.
Conceptually C++ 2D library can be built around single GFX backend function similar to NV_path_renderer (
https://www.khronos.org/registry/OpenGL/extensions/NV/NV_path_rendering.txt https://www.khronos.org/registry/OpenGL/extensions/NV/NV_pat... ). All 2D primitives can be simple wrappers of NV_path_renderer calls + blend_bitmap().
But there is another huge problem - text rendering. Just few keywords: LTR, RTL, TTB text layouts. Fonts discovery and substitution. Different font formats. ClearType and other antialiasing technics tied with monitor architectures. That's too big and I am not sure about the size of 2D specification that will include all needed details.
- raphlinus 8y agoI've been playing in the space too, and basically agree with what you say but have some other observations. 1. The "fancy" operations like the blending modes (I believe these were originally from Photoshop and are now part of PDF, among other things) are definitely doable on GPU, but many of them require shaders and cannot be done in the fixed-function blend pipeline. 2. There are a bunch of optimizations that are still very useful on GPU, including reordering to improve batching of draw calls, and techniques to reduce overdraw when an operation will be completely painted over. Webrender uses hierarchical z-buffer to GPU-accelerate these. 3. There are advanced things like linear-sRGB colorspaces that are very useful, well supported on modern GPU hardware. 4. CoreGraphics on MacOS is pretty slow. On Windows, I've had varying results with Direct2D (I know we chatted some in a previous thread). I think it depends a lot on the quality of drivers. 4. Incremental repaint (as opposed to painting the surface in full) is still useful, if for no other reason than to reduce energy use. It's difficult on some platforms (Mac), well supported on others (Windows), and optional/driver dependent on others (Linux/Android). 5. Clipping is still where much of the performance dies. Sure, you _can_ specify everything in terms of bitmap blending, but do you want to? That's an awful lot of gmem bandwidth you're churning. And yes, text is fantastically complicated. Long story short, I don't see any good one-size-fits-all solution here.
- arandr0x 8y agoI work in 3D (and 2D) graphics primarily in C++. I don't think the standards committee can come up with anything that'll replace the GPU-accelerated APIs (there's already the Direct3D 12-vs-Vulkan split that's really unlikely to have a clear winner), however, I'd take simpler, CPU-only libs for common tasks: * Vector and matrix math -- vec2d, vec3d, conversion to quaternion, a matrix library that doesn't suck, overloaded operators, etc. I dabble in Python, always have, and numpy isn't the best lib out there (some things are oddly named, I'm missing the operators, etc) but it's more complete, more usable, and better documented than any lib I've used in C++. * Basic image manipulation. Like "write bitmap image to PNG" basic. This will never get used for anything serious but will be useful for toy projects/debugging * Basic intersection tests. This is 2018 and I had to write some variant of (basic geometry primitive) intersects (other basic geometry primitive) using formulas most people probably haven't seen since their SATs 5 times since the beginning of the year, because I at least know the formula by heart by now, whereas all the aforementioned libraries are too verbose, not documented, require linking a huge library, are header-only and will bloat your compilation times by a factor 10, etc. I agree that such a library should steer well clear of text rendering. Text rendering is really hard, has weird edge cases, and the people who do it have their own favorite library already. But the other stuff I mentioned, that's stuff already present to some extent in the "mainstream" C++ libraries, like boost and Qt. I think such a library should definitely not be 2D-only. Tons of libraries go that direction (for example Canvas in HTML5) because 2D is easier if you have no hardware acceleration, but even in the 3D space, there are algorithms where usability>performance and currently the people writing those algorithms are copy-pasting left and right and spending hours writing unit tests for high school math.