At the moment CEGUI only supports image formats that contain raster graphics. For a graphical user-interface library, such as CEGUI, it is of particular interest to provide a solution for scalable content. This is needed considering the different screen resolution of devices it could be used on. Raster graphics however would have to be downscaled and upscaled in relation to the screen size, in order to adapt to it. This is not optimal and only vector graphics provide an optimal solution for this issue, as they can be rendered at any size. SVG is an open format that provides a solution for saving vector graphics in XML. A parser could be integrated into the CEGUI library to interpret files of this format and to import SVG vector graphics into CEGUI. As addition, the renders of CEGUI (OpenGL, DirectX, Ogre, Irrlicht) would have to be improved in a way that they are able to render vector graphics as geometry in real-time.
The suggested project would consist of two main parts. One is the SVG parsing and subsequent management of SVG-based images inside the CEGUI core library. The other part is the rendering, which has to be adapted for the different renderers that CEGUI provides and which has to collaborate with the new SVG-related classes inside CEGUI.
Custom SVG parser
Although SVG parsing could be theoretically done with an existing external library, this would cause CEGUI to require an additional dependancy, the library would have to have an apprioriate Open Source licens and also the parser could not be modified for specific requirements of CEGUI. For these reasons, a custom parser is a better solution. This parser would be integrated into CEGUI and could be designed after the code of existing open-source SVG-parsers, such as cairo library and the Skia graphics library. The parser will translate the SVG file into a data structure inside a new CEGUI class, which could carry the name SVGImage, and which will be designed as a subclass of CEGUI::Image. Before rendering the SVGImage, the shapes defined in it need to be tesselated into vertex data, that can then be rendered in real-time by OpenGL or Direct3D.
Custom vertex-based vector graphics rendering
There are two options how to render vector graphics in an application. One way is by creating a texture, in a specific resolution, based on the vector graphics beforehand and using the pre-created texture later on, to render the rasterized vector graphics as a textured rectangle during the actual rendering process. This has the benefit that it is easy to do, no care has to be taken of rendering performance issues because the texture is only created once and usually not recreated. However, this also brings a big disadvantage, namely that things like zooming and animation are not possible without recreating the texture each frame. This practically defeats the main benefit for which vector graphics are usually chosen: scalability. A better solution is to dynamically tesselate the vector graphics into vertex geometry whenever a new scaling is needed. The geometry can then be rendered with appropriate vertex and fragment shaders by the different renderers of CEGUI. For this to be possible, an optional stage before rendering a SVGImage has to be implemented, which tesselates general shapes defined in SVG, such as lines, triangles, rectangles, ellipsoids and circles, into triangle meshes. These meshes can then be rendered with a vertex shader and a fragment shader. The meshes should only be generated when a specific scale is needed and then kept for rendering until something changes that requires a different scale. SVG supports two types of gradients: linear and radial. These two types of gradients can be emulated with a fragment shader and do also require the vertex shader to be adapted slightly. Although it would be possible to combine full support for all gradients into one big shader with a number of if-cases, it is probably recommandable to seperate them and render the two types of gradient and the solid geometry each in a respective render batch with the appropriate shaders set. Also, considering that Direct3D and OpenGL require different shader program languages, the shaders will have to be written both in hlsl and glsl.
Also for batching to be possible to happen, the renderers have to be changed to use geometry with depth values and render with the depth buffer on. This requires additional changes to all renderers.
For the geometry rendering, it would also be important to, at least, optionally support hardware anti-aliasing, as offered by OpenGL. A public function like:
could be provided for this purpose. Similarly it could be done for the other renderers.
SVG supports animation. Because of this, future animation-support should be considered during the development, although the implementation of this will not be part of this project. For the animation-support it is relevant how and when tesselated geometry is being invalidated and recached. The SVGImage class should optimally be designed in a way that it will invalidate and recache the tesselated geometry on-the-fly with lazy-updates. It is important to define the specific situations that require a retesselation. These are:
- The SVGImage class' vector graphics data has changed. This happens at the initial loading of the SVG file. During animation, this would happen every frame, while the animation is running.
- The size at which an SVGImage class is being displayed has changed. This occurs whenever the widget using the SVGImage is being resized (which can also occur when a parent or the render window being resized).
The tesselation can slow down the program when complex or big SVG files are being processed, especially when it has to be done every frame (animation). To circumvent the stalling of the program, a render frame could be skipped so the processing of data for tesselation can be done inparallel, in a seperate thread. However, the threading-support is purely optional.
I think the best way to work on the project is by working in iterations.
The first iteration(milestone) should provide the following:
- Be able to read in a basic SVG file containing a definition for a line/rectangle
- Parse it into a a data-structure stored inside the SVGImage clas
- Tesselate it into geometry
- Use the geometry inside CEGUIOpenGL3Renderer
All these steps are new and require a novel implementation for CEGUI
This way I will have a proof of concept and will also be able to see possible issues early on. Later on I will have 2 more iterations, which each improve all of these steps. In the second iteration, all types of SVG shapes will be supported and the Ogre renderer will be supported (hlsl shaders). The third and last iteration will add gradients, by using fragment shaders, and support the different Direct3D renderers and the Irrlicht renderer.
[Optionally] CEGUI Imagesets supporting SVG
For usability it should be possible to define SVG images in a CEGUI Imageset file (.imageset). This way, they can be used analogically to raster graphics images and loaded automatically. The existing ChainedXMLLoader can be used to load the SVG XML files from within the imageset XML file. However, each image definition would refer to one SVG file, instead of having a texture atlas and referring to parts of sections of the image. An alternative would be to use groups ("g" elements) defined inside the SVG file, whereas each lowest-level group could be interpreted as containing one vector-graphic image. The group's ID could be used as name of the SVGImage in CEGUI.
27.5. - 17.6. Conduct research about existing SVG parsers. Plan the approximate design of the parser and the SVGImage class.
17.6. - 7.7. In this time I will have some tests and submissions for university so I will only be able to work at smaller amounts. I will begin writing the parser, write a basic SVGImage class. In the end a line or rectangle should be able to be saved in the internal datastructure of an SVGImage class.
7.7. - 14.7. Add a tesselation stage in connection to the SVGImage, so that the a line or rectangle can be parsed and then tesselated into geometry that is suitable to be used in renderers later.
14.7. - 21.7. MILESTONE 1: Adapt the OpenGL3 Renderer (which should serve as basis for proof of concept implementations), so that it can render a simple line/rectangle with solid fill and without contour. The rnederer will have to be changed to accept the triangles from the tesselation stage and render them using custom shader(s). At this point we should be able load a rectangle/line from an SVG file and render it using CEGUI.
21.07.-25.8. Improve the SVGImage class and tesselator to support both the line-contours of rectangles as well as their filling (solid only).
25.8. - 30.8. Add support for SVG shapes, such as circles and ellipsoids and polygon meshes, so that all (important) shapes are covered.
30.8. - 4.8. Integrate the rendering adaptions of OpenGL3 also into the OpenGL renderer. This requires an exception in case SVG usage is attempted and are shaders not supported by the OpenGL version of the user. If no shaders are available, SVG won't be supported at all.
4.8. - 14.8. MILESTONE 2: Change the Ogre renderer to be able to use the tesselated geometry. Since Ogre can render both Direct3D AND OpenGL, the shader programs will have to be provided for both libraries and be generated from within the OgreRenderer. This requires porting the glsl code to hlsl. Now all important shapes defined in SVG should be renderable both in Ogre(D3D or OGL) and OpenGL3 and OpenGL.
14.8. - 25.8. Add GLSL shaders, so that the SVG gradients (linear, radial) can be supported. Port the shaders to HLSL and test in Ogre.
25.8. - 7.9. Milestone 3: Adapt the various D3D Renderers for the changes needed to support triangle rendering using the shaders. Now gradients are supported and SVG should be able to be rendered in all Renderers of CEGUI.
7.9.- X Buffer time, in case issues appear. Add comments and refactor code.
Discussion regarding the development of CEGUI itself - as opposed to questions about CEGUI usage that should be in the help forums.
1 post • Page 1 of 1
Who is online
Users browsing this forum: No registered users and 2 guests