Canvas
- Praetor
- OGRE Retired Team Member
- Posts: 3335
- Joined: Tue Jun 21, 2005 8:26 pm
- Location: Rochester, New York, US
- x 3
- Contact:
- ajs15822
- OGRE Expert User
- Posts: 570
- Joined: Mon Jan 02, 2006 2:05 am
- Location: Texas
- x 2
- Contact:
Sure, I'll add that in.Frenetic wrote:s... so a feature for general texture-size constraints, maybe an error-check or something, would be nice.
Atlas is not dynamic because re-packing potentially invalidates the UV coords within the GlyphInfo/TextureInfo instances. If you *really* need to change your assets, you will need to create new instances of Atlas/Canvas and clear out any GlyphInfo/TextureInfo instances you have accumulated (like in a text-layout cache, for example).And maybe the ability to "reserve()" a certain size ala std::vector.
... Oh, and the fonts in my app are (supposed to be) user-customizable. Dynamically regenerating the fonts shouldn't be too hard, right? (This feature does not need real-time performance, of course)
Yes, you could use several Canvas+Atlas instances in the same viewport-- just be aware that the z-order of each layer within a Canvas is independent of the z-ordering of another Canvas.I suppose I can use several Canvas+Atlases if I expect to be using a crap-ton of textures? I'll probably replace my own GUI-drawing code with this (improving my own code would be re-inventing the wheel now) and I have lots of fonts and text, lots of background images, lots of icons, etc. so going beyond the max texture size my card supports is almost certain.
Also, I really recommend attempting to minimize your texture assets by taking advantage of Canvas's tiling capabilities. Any textured fill that is smaller than the rectangle it fills will be tiled. For example, say you had a fancy little dialog box with rounded corners:
Instead of slapping the entire background into Atlas as one texture, you could slice the unique parts up. (This comes with the added bonus of dialog resizability)
Slicing it up gives us eight unique images. The images outlined in red would be tiled horizontally/vertically, depending on the size of the content area. Oh, and as a sidenote: when creating tiling images, try not to make them single-pixel widths/heights because the textures are tiled geometrically-- each new tile means an extra quad. (One of the limitations of texture atlases is that you can't use the videocard's native texture-wrapping/tiling)
Sorry about that, it's just my style. ^^;Lastly, it bugs me that you don't use the mWhatever member-variable convention... everything else is so far above my highest standards, that this tiny issue stands out...
Y'all are welcome.various ogre users wrote:Thanks.
The former is correct-- Atlas/Canvas is simply a tool that Ogre3D developers can use to help create their own custom GUI/HUD/Interface/2D solutions. It is not meant to be an all-in-one HUD/GUI library because I can't predict nor accommodate what everyone wishes to achieve in their own games/applications.scriptkid wrote:As you mention, you wrote it to power simple HUD elements. Does that mean that users should combine your system with a more full-blown system in order to create an options screen or an inventory, for example? Or are you going to add more widget types?
I'm glad that you and others like the demo, but I really only designed it as an example of what is possible. (Hence the rather random, 'DancingGraphElement')Lord LoriK wrote:Wow, ajs15822! Very good job. Well done, as always.
Suggestions:
* I think quite a lot of the "demo" source should go into the main library. The Document, Element, ImageElement, Parser and TextFlowElement feel like "core" classes, IMO.
* Add text justification to TextFlowElement.
* Add serialization support. Creating an editor with that would be a piece of cake.
If I ever were to create a full GUI library, you'll know.
Could you give a little more detail about what you mean?* Multitexture support. Even if this increases the batch count, is the only way to provide nearly limitless flexibility.
* AnimatedImageElement. 'Nuff said.
All of these were originally in Canvas in the beginning but I faced a few problems:* Primitive drawing: point, line, circle, square, polyline. Maybe a fill function, too.
* Because the texture-atlas has no padding between elements (for maximum efficiency), aliased geometry bleeds at the edges (regardless of clamp mode).
* I wanted to support clipping but couldn't use the render-system to do it (otherwise, extra batch call). Clipping aligned rectangles (and their complex fills) programmatically is the best I can do. (Otherwise, I'd have to introduce a tessellation dependency)
* Confining the geometry to quads allows me to fully optimize the index buffer and minimize the amount of vertices that need to be updated per render-operation.
I debated with myself for a long while over Spring Break about which direction to take Canvas (performance versus feature-support) and decided to go with performance.
Cool, I'm always looking for more brains.I had to reinstall my system a few days ago, but if I manage to set my development environment soon enough, I'll gladly help with these.
- Frenetic
- Bugbear
- Posts: 806
- Joined: Fri Feb 03, 2006 7:08 am
Hmm. One thing that worries me is that I need to show different icons in my GUI. Because there could be potentially thousands of icons, loading them all at the same time is probably not a good idea. The icons, combined with all the other assets and fonts, means I'll probably want to do something to avoid running out of the 2048x2048 max texture space...ajs15822 wrote:Atlas is not dynamic because re-packing potentially invalidates the UV coords within the GlyphInfo/TextureInfo instances.
Aye. I mitigate the z-ordering problem in my existing code by rendering potentially overlapping things (like draggable windows) in separate batches.ajs15822 wrote:Yes, you could use several Canvas+Atlas instances in the same viewport-- just be aware that the z-order of each layer within a Canvas is independent of the z-ordering of another Canvas.
I'm not sure how I'm going to tackle this issue if I use Canvas.
I already do this.ajs15822 wrote:Instead of slapping the entire background into Atlas as one texture, you could slice the unique parts up. (This comes with the added bonus of dialog resizability)
-
- Kobold
- Posts: 36
- Joined: Sun Feb 24, 2008 2:39 pm
You might be interested my own 'labour of love' - Vexi. It uses a box model layout to create user interfaces although it's currently Java only. I would like to, eventually, get it running as a library on top of SDL or even one day Ogre (at one point Vexi was compiled to native binaries using GCJ).
- altren
- Gnome
- Posts: 329
- Joined: Tue Oct 24, 2006 9:02 am
- Location: Moscow, Russa
- x 24
- Contact:
Really interesting work. I want to talk about Canvas used as GUI basis. I think you can't create fully functional GUI because it can use many different textures (for example lots of icons as Frenetic want) and you can't use it in one batch because you'll need very large textures. Anyway it will be best solution if GUI don't need to show any images and have only it's own skin and fonts.
I realized it when I was thinking about integration your technique in MyGUI. Anyway I like your text formatting and I'm thinking about including it as separate widget (kind of RichText). Just one question: am I right that you generate only used glyphs for different fonts? So it can be used only for infrequently changing text. Otherwise it'll need all possible glyphs packed into Atlas texture.
I realized it when I was thinking about integration your technique in MyGUI. Anyway I like your text formatting and I'm thinking about including it as separate widget (kind of RichText). Just one question: am I right that you generate only used glyphs for different fonts? So it can be used only for infrequently changing text. Otherwise it'll need all possible glyphs packed into Atlas texture.
-
- Goblin
- Posts: 254
- Joined: Tue Feb 13, 2007 5:33 am
I basically meant to suggest a way to provide a bigger "atlas" (many atlases, if this was done) keeping the texture size limited to 1024x1024 or 2048x2048 to make it compatible. Using many textures automatically would provide extra space to cache fonts, images, etc. The animated element needs no explanation, I guess...ajs15822 wrote:Could you give a little more detail about what you mean?* Multitexture support. Even if this increases the batch count, is the only way to provide nearly limitless flexibility.
* AnimatedImageElement. 'Nuff said.
Understood. Maybe the performance versus more features should be selected by the user at creation time, so more complex effects could be achieved only on the more GPU-demanding Canvas?ajs15822 wrote:All of these were originally in Canvas in the beginning but I faced a few problems:* Primitive drawing: point, line, circle, square, polyline. Maybe a fill function, too.
* Because the texture-atlas has no padding between elements (for maximum efficiency), aliased geometry bleeds at the edges (regardless of clamp mode).
* I wanted to support clipping but couldn't use the render-system to do it (otherwise, extra batch call). Clipping aligned rectangles (and their complex fills) programmatically is the best I can do. (Otherwise, I'd have to introduce a tessellation dependency)
* Confining the geometry to quads allows me to fully optimize the index buffer and minimize the amount of vertices that need to be updated per render-operation.
I debated with myself for a long while over Spring Break about which direction to take Canvas (performance versus feature-support) and decided to go with performance.
EDIT: typos in quote tags... D'oh!
-
- Greenskin
- Posts: 102
- Joined: Tue May 10, 2005 11:42 pm
- Location: SF, California
- Contact:
-
- Kobold
- Posts: 33
- Joined: Thu Aug 18, 2005 12:20 am
Very nice work, I develop my own UI http://developers.xkpmedia.com/wiki/doku.php?id=ui and have recently came up with the canvas concept. I have actually designed and implemented using cairo and it doesn't seem crazily difficult to adapt your canvas.
This is mst def the way to go, I render my whole UI easily with a 256x256 map.
I would have to admit it will allow my cairo based interface to be fully implemented
Now a few observations of mine:
* wouldn't it make sense to provide custumers with a reference to a specific primitive? it would make sense when you need to update.
* I don't see the need to keep a 1-to-1 relationship between the Canvas and the Atlas, multile atlases will do wonders for many of the problems stated and going from one batch to a few shouldn't hurt performance too much.
Hope that helped a little bit.
Also, I really recommend attempting to minimize your texture assets by taking advantage of Canvas's tiling capabilities. Any textured fill that is smaller than the rectangle it fills will be tiled. For example, say you had a fancy little dialog box with rounded corners:
This is mst def the way to go, I render my whole UI easily with a 256x256 map.
I'll somehow disagree with this one, In order to use the card's tilng I used to keep my tilables in separate textures (horizontal and vertical) but then tried th estretching capanilites (ie drawing a big quad) and works perfectly. Of course only in cases when there is not detail to repeat (like in your fancy dialog)when creating tiling images, try not to make them single-pixel widths/heights because the textures are tiled geometrically-- each new tile means an extra quad. (One of the limitations of texture atlases is that you can't use the videocard's native texture-wrapping/tiling)
Wonder if may I interest you in joining a mature oneI'm glad that you and others like the demo, but I really only designed it as an example of what is possible. (Hence the rather random, 'DancingGraphElement')
If I ever were to create a full GUI library, you'll know.
The easiest solutions for the bleeding is to add a pixel on the borders (I don't think 4 pixels are going to kill nobody), as for the tesselation, true is a dependency, but the feature set and possibilities will skyrocket.All of these were originally in Canvas in the beginning but I faced a few problems:
* Because the texture-atlas has no padding between elements (for maximum efficiency), aliased geometry bleeds at the edges (regardless of clamp mode).
* I wanted to support clipping but couldn't use the render-system to do it (otherwise, extra batch call). Clipping aligned rectangles (and their complex fills) programmatically is the best I can do. (Otherwise, I'd have to introduce a tessellation dependency)
* Confining the geometry to quads allows me to fully optimize the index buffer and minimize the amount of vertices that need to be updated per render-operation.
I would have to admit it will allow my cairo based interface to be fully implemented
Now a few observations of mine:
* wouldn't it make sense to provide custumers with a reference to a specific primitive? it would make sense when you need to update.
* I don't see the need to keep a 1-to-1 relationship between the Canvas and the Atlas, multile atlases will do wonders for many of the problems stated and going from one batch to a few shouldn't hurt performance too much.
Hope that helped a little bit.
-
- Kobold
- Posts: 26
- Joined: Sun Sep 24, 2006 3:41 pm
- Contact:
hi,
one quick question:
is it possible to draw a texture from the atlas rotated? because i'll need it for a speedometer. currently i use ogre's overlays which i want to avoid
thanks in advance
bloodyfanatic
one quick question:
is it possible to draw a texture from the atlas rotated? because i'll need it for a speedometer. currently i use ogre's overlays which i want to avoid
thanks in advance
bloodyfanatic
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg. (Bjarne Stroustrup)
-
- Kobold
- Posts: 26
- Joined: Sun Sep 24, 2006 3:41 pm
- Contact:
- ajs15822
- OGRE Expert User
- Posts: 570
- Joined: Mon Jan 02, 2006 2:05 am
- Location: Texas
- x 2
- Contact:
Currently it is not possible to rotate any element (or draw any non-screen-aligned quad) because of two reasons:BloodyFanatic wrote:hi,
one quick question:
is it possible to draw a texture from the atlas rotated? because i'll need it for a speedometer. currently i use ogre's overlays which i want to avoid
thanks in advance
bloodyfanatic
-- texture filtering is disabled to allow the texels to be perfectly aligned with the screen; your rotated texture wouldn't look very nice
-- we use a non-padded texture atlas and so when any non-screen-aligned fragment attempts to sample adjacent texels, we get edge bleeding
If you need true graphic transformations, I would recommend using Hikari instead.
- Curtaoa
- Gnoblar
- Posts: 15
- Joined: Thu Jan 08, 2009 8:50 pm
Re: Canvas
Funny you should mention HIkari, I'm trying to get canvas to play nice with it--
I have only one issue right now and that's getting canvas first in the Z-order. Since Hikari renders to an overlay and Canvas does not, is there even a way to do it at all? Will I have to do something underhanded like render canvas to a different viewport then snapshot its texture and create a 2D overlay with it to accomplish this? or am I completely out in the weeds..
I have only one issue right now and that's getting canvas first in the Z-order. Since Hikari renders to an overlay and Canvas does not, is there even a way to do it at all? Will I have to do something underhanded like render canvas to a different viewport then snapshot its texture and create a 2D overlay with it to accomplish this? or am I completely out in the weeds..
- ajs15822
- OGRE Expert User
- Posts: 570
- Joined: Mon Jan 02, 2006 2:05 am
- Location: Texas
- x 2
- Contact:
Re: Canvas
Hmm, you could try changing the render queue ID of Canvas to be something higher than the Overlay render queue.Curtaoa wrote:Funny you should mention HIkari, I'm trying to get canvas to play nice with it--
I have only one issue right now and that's getting canvas first in the Z-order. Since Hikari renders to an overlay and Canvas does not, is there even a way to do it at all? Will I have to do something underhanded like render canvas to a different viewport then snapshot its texture and create a 2D overlay with it to accomplish this? or am I completely out in the weeds..
In Canvas.cpp, go to the Canvas constructor definition (should be around line 82), and change it from this:
Code: Select all
Canvas::Canvas(Atlas* atlas, Ogre::Viewport* viewport) : atlas(atlas), viewport(viewport), vertexData(0), indexData(0),
bufferSize(100), renderQueueID(Ogre::RENDER_QUEUE_OVERLAY), isDirty(false), visibility(true)
Code: Select all
Canvas::Canvas(Atlas* atlas, Ogre::Viewport* viewport) : atlas(atlas), viewport(viewport), vertexData(0), indexData(0),
bufferSize(100), renderQueueID(Ogre::RENDER_QUEUE_OVERLAY + 1), isDirty(false), visibility(true)
- Curtaoa
- Gnoblar
- Posts: 15
- Joined: Thu Jan 08, 2009 8:50 pm
Re: Canvas
This does indeed do the trick, knew it had to be something simple. Still learning Ogre, thx for the quick answer.ajs15822 wrote:Hmm, you could try changing the render queue ID of Canvas to be something higher than the Overlay render queue. <snip>
-
- Gnoblar
- Posts: 6
- Joined: Tue Apr 10, 2007 6:46 pm
Re: Linux port
Yes. I've run into this before, as I code for both Windows AND Linux. Just add this to the top of Atlas.cpp:Fuinelen wrote:First of all, thanks a lot for sharing
I'm trying to port it to linux right now (using code::blocks) and I got so far as to only receive this lonely error :
any ideas what I missed?Code: Select all
Canvas - May 12th 2008/Canvas/Source/Atlas.cpp||In member function ‘void Atlas::pack(ComputationVector&)’:| Canvas - May 12th 2008/Canvas/Source/Atlas.cpp|385|error: no matching function for call to ‘sort(__gnu_cxx::__normal_iterator<ComputationRect**, std::vector<ComputationRect*, std::allocator<ComputationRect*> > >, __gnu_cxx::__normal_iterator<ComputationRect**, std::vector<ComputationRect*, std::allocator<ComputationRect*> > >, Atlas::pack(ComputationVector&)::compare)’|
Code: Select all
#include <functional>
namespace std {
template<>
struct greater<ComputationRect *> : public binary_function<ComputationRect *, ComputationRect *, bool>
{
bool operator()(ComputationRect *a, ComputationRect *b)
{
return (a->area > b->area);
}
};
}
/************************
* TextureInfo
************************/
Code: Select all
std::sort(rectangles.begin(), rectangles.end(), std::greater<ComputationRect *>());
Also, I have attached my Makefile that I created to create Canvas.a. Just put it into the Canvas subdirectory and type "make".
Enjoy!
Code: Select all
# Project
PROJECT_DIR = .
PROJECT_NAME = Canvas
SOURCE_DIR = $(PROJECT_DIR)/Source
INCLUDE_DIR = $(PROJECT_DIR)/Include
OUTPUT_DIR = $(PROJECT_DIR)/Lib
OBJECT_FILE_DIR = $(PROJECT_DIR)/Objects
OGRE_HOME = /usr/include
ADDITIONAL_INCLUDE_DIRECTORIES = -I$(PROJECT_DIR)/Include -I$(OGRE_HOME)/include -I$(OGRE_HOME)/include/OGRE -I/usr/include/freetype2
HEADER_FILES = $(INCLUDE_DIR)/Atlas.h $(INCLUDE_DIR)/Canvas.h
SOURCE_FILES = $(SOURCE_DIR)/Atlas.cpp $(SOURCE_DIR)/Canvas.cpp
OBJECT_FILES = $(OBJECT_FILE_DIR)/Atlas.o $(OBJECT_FILE_DIR)/Canvas.o
LIBRARY = $(OUTPUT_DIR)/$(PROJECT_NAME).a
USER_C++FLAGS = $(ADDITIONAL_INCLUDE_DIRECTORIES)
#
# System
C++ = g++
C++_ENABLE_FULL_WARN = -Wall -Wno-reorder
PREPROCESS_FLAGS = -I/usr/X11R6/include -I/usr/include/X11 $(STL_INC) -D_LINUX -DFUNCPROTO
C++FLAGS = -pipe -march=pentium4 $(USER_C++FLAGS) $(PREPROCESS_FLAGS) $(C++_ENABLE_FULL_WARN)
C++COMPFLAGS = $(USER_C++COMPFLAGS) $(C++FLAGS)
#
all: $(LIBRARY)
ar -ru $(LIBRARY) $(OBJECT_FILES)
ranlib $(LIBRARY)
$(LIBRARY): $(HEADER_FILES) $(OBJECT_FILES)
$(OBJECT_FILE_DIR)/Atlas.o: $(SOURCE_DIR)/Atlas.cpp
$(C++) -c $(C++COMPFLAGS) -o $(OBJECT_FILE_DIR)/Atlas.o $(SOURCE_DIR)/Atlas.cpp
$(SOURCE_DIR)/Atlas.cpp: $(INCLUDE_DIR)/Atlas.h
$(OBJECT_FILE_DIR)/Canvas.o: $(SOURCE_DIR)/Canvas.cpp
$(C++) -c $(C++COMPFLAGS) -o $(OBJECT_FILE_DIR)/Canvas.o $(SOURCE_DIR)/Canvas.cpp
$(SOURCE_DIR)/Canvas.cpp: $(INCLUDE_DIR)/Canvas.h
-
- Greenskin
- Posts: 142
- Joined: Thu Dec 18, 2008 11:32 am
Re: Canvas
Oh wow... I got 6000+ Fps.
Say do you think you can write a wiki on how to use your library so everyone can get a quick start and overview of using your library?
Otherwise awesome work!
Say do you think you can write a wiki on how to use your library so everyone can get a quick start and overview of using your library?
Otherwise awesome work!
- AshMcConnell
- Silver Sponsor
- Posts: 605
- Joined: Fri Dec 14, 2007 11:44 am
- Location: Northern Ireland
- x 16
- Contact:
Re: Canvas
Hi Folks,
Just wondering if anyone else is getting spikes in performance with canvas?
I have some debug that i output onscreen showing the time different sub-sections of the code is taking, it usually takes 200-300 microsecs, but occasionally it jumps to 20000-40000. Any ideas what could be causing it? Perhaps it could be switching to another process on the PC but it seems to be consistently the canvas update that jumps in time.
Thanks!
All the best,
Ash
Just wondering if anyone else is getting spikes in performance with canvas?
I have some debug that i output onscreen showing the time different sub-sections of the code is taking, it usually takes 200-300 microsecs, but occasionally it jumps to 20000-40000. Any ideas what could be causing it? Perhaps it could be switching to another process on the PC but it seems to be consistently the canvas update that jumps in time.
Thanks!
All the best,
Ash
-
- Greenskin
- Posts: 142
- Joined: Thu Dec 18, 2008 11:32 am
Re: Canvas
Actually Im curious why Canvas can reach Fps as high as 6000 whereas my empty Ogre release build can only reach 3000?
- ajs15822
- OGRE Expert User
- Posts: 570
- Joined: Mon Jan 02, 2006 2:05 am
- Location: Texas
- x 2
- Contact:
Re: Canvas
@mr_mocap:
Thanks a lot for the Linux port!
@mickeyren:
If I find the time, I might write something up-- but for now the documentation in the headers and the demo application should suffice.
By the way, I've also been working on an extensible, data-driven UI library that's totally powered by Canvas. More details about it later!
@AshMcConnell:
By the 'canvas update', do you mean 'Canvas::updateGeometry'? If so, the 'performance spike' you are seeing may be when Canvas rebuilds the vertex buffer due to new draw/clear calls or, more probably, it might be the delay it takes Ogre to lock the vertex buffer from the videocard.
Thanks a lot for the Linux port!
@mickeyren:
If I find the time, I might write something up-- but for now the documentation in the headers and the demo application should suffice.
By the way, I've also been working on an extensible, data-driven UI library that's totally powered by Canvas. More details about it later!
@AshMcConnell:
By the 'canvas update', do you mean 'Canvas::updateGeometry'? If so, the 'performance spike' you are seeing may be when Canvas rebuilds the vertex buffer due to new draw/clear calls or, more probably, it might be the delay it takes Ogre to lock the vertex buffer from the videocard.
- AshMcConnell
- Silver Sponsor
- Posts: 605
- Joined: Fri Dec 14, 2007 11:44 am
- Location: Northern Ireland
- x 16
- Contact:
Re: Canvas
First of all, wow, a UI driven from Canvas will be awesome!
I should have been more specific, I am calling Document::update() each frame, every so often (from a few secs to 20 secs perhaps - i can't quite see a regular pattern) the time taken to execute shoots up quite a lot. It probably isn't a problem, but if I am doing something silly i'd like to avoid it
Thanks again for the hard work
All the best,
Ash
I should have been more specific, I am calling Document::update() each frame, every so often (from a few secs to 20 secs perhaps - i can't quite see a regular pattern) the time taken to execute shoots up quite a lot. It probably isn't a problem, but if I am doing something silly i'd like to avoid it
Thanks again for the hard work
All the best,
Ash
-
- Halfling
- Posts: 83
- Joined: Fri Feb 15, 2008 6:39 pm
Re: Canvas
LGPL would mean I'd have to release my source code if I statically linked to canvas? That's pretty much the only reason I probably won't be able to use Canvas. I'd love to be able to use it.
- KungFooMasta
- OGRE Contributor
- Posts: 2087
- Joined: Thu Mar 03, 2005 7:11 am
- Location: WA, USA
- x 16
- Contact:
Re: Canvas
ajs15822 wrote:@mr_mocap:
By the way, I've also been working on an extensible, data-driven UI library that's totally powered by Canvas. More details about it later!
Creator of QuickGUI!
- ajs15822
- OGRE Expert User
- Posts: 570
- Joined: Mon Jan 02, 2006 2:05 am
- Location: Texas
- x 2
- Contact:
Re: Canvas
Ah, okay-- I haven't done too much profiling on the Demo code and so there's probably room for optimization with the text-flow algorithm. I'll look into it.AshMcConnell wrote:First of all, wow, a UI driven from Canvas will be awesome!
I should have been more specific, I am calling Document::update() each frame, every so often (from a few secs to 20 secs perhaps - i can't quite see a regular pattern) the time taken to execute shoots up quite a lot. It probably isn't a problem, but if I am doing something silly i'd like to avoid it
Thanks again for the hard work
All the best,
Ash
Well don't statically link to it then-- just wrap it up in a DLL.Penguin wrote:LGPL would mean I'd have to release my source code if I statically linked to canvas? That's pretty much the only reason I probably won't be able to use Canvas. I'd love to be able to use it.