I was able to validate your results with my test case, too. Seems I just had luck :
I’ve traced it down a bit:
OrderedGroup --instanceof tests–> Node -> OrderedState -> Renderer Stuff
and there ends my knowledge.
@bohdan: what renderer are you using?
I am using com.xith3d.render.jogl
can anyone please test this with lwjgl and jsr231 please?
Thanks Arne, for helping!
Yes, I actually originally tested it on jsr231…
No go on “lwjgl” too…
Here is an interesting test, I think ;D It is animated for convenience…
I have here 2 quads, Green and Blue. They are placed in OrderedGroup so that Green one supposed to be rendered on top of Blue one.
If you make them exactly the same size and exactly the same position the OrderedGroup is working perfectly!!!
If you want - change the order and you will get BLUE on top - working just as it is expected…
But!!! If you shift one just little bit or change its size - look what funny efects you get here… :o
Well…Ok, this efects are understood of course and not strange if to assume that OrderedGroup is not working under this conditions…
Use dX_BLUE as delta shift, and dSize_BLUE - as delta size…
http://homepage.ntlworld.com/bohdan.lozynskyy/OrderedGroup.jpg
import java.awt.Color;
import javax.swing.JFrame;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.xith3d.render.CanvasPeer;
import com.xith3d.render.RenderPeer;
import com.xith3d.render.jsr231.RenderPeerImpl;
import com.xith3d.scenegraph.Appearance;
import com.xith3d.scenegraph.BranchGroup;
import com.xith3d.scenegraph.Canvas3D;
import com.xith3d.scenegraph.ColoringAttributes;
import com.xith3d.scenegraph.Locale;
import com.xith3d.scenegraph.OrderedGroup;
import com.xith3d.scenegraph.Shape3D;
import com.xith3d.scenegraph.View;
import com.xith3d.scenegraph.VirtualUniverse;
import com.xith3d.test.TestUtils;
public class OrderedGroupTest {
public OrderedGroupTest() {
JFrame frame = new JFrame("OrderedGroupTest");
frame.setSize(500, 500);
//======= setting up Universe ===============
VirtualUniverse My_Universe = new VirtualUniverse();
Locale locale = new Locale();
My_Universe.addLocale(locale);
BranchGroup scRootBG = new BranchGroup();
locale.addBranchGraph(scRootBG);
//------------------------------
RenderPeer renderPeer = new RenderPeerImpl();
CanvasPeer canvasPeer = renderPeer.
makeCanvas(frame.getContentPane(), 0, 0, 32, false);
Canvas3D scrCanvas = new Canvas3D();
scrCanvas.set3DPeer(canvasPeer);
//------------------------------
View scView = new View();
scView.addCanvas3D(scrCanvas);
My_Universe.addView(scView);
//------------------------------
Appearance a1 = new Appearance();
a1.setColoringAttributes(new ColoringAttributes(new Color3f(Color.GREEN),0));
Appearance a2 = new Appearance();
a2.setColoringAttributes(new ColoringAttributes(new Color3f(Color.BLUE),0));
//======= adding OrderedGroup ===============
float dX_BLUE = 0; // <<++ play here
float dSize_BLUE = 0; // <<++ or here
//-------------------------------------------
Shape3D quadGREEN = new Shape3D(TestUtils.
createPlane(0, 0, 0, 1, 1),a1);
Shape3D quadBLUE = new Shape3D(TestUtils.
createPlane(dX_BLUE, 0, 0, 1f + dSize_BLUE, 1f + dSize_BLUE),a2);
OrderedGroup ordGR = new OrderedGroup();
//--- here play with order ------
ordGR.addChild(quadGREEN);
ordGR.addChild(quadBLUE);
//-------------------------------
scRootBG.addChild(ordGR);
//======= running =============================
frame.setVisible(true);
Point3f camL = new Point3f(0,1.8f,1.8f);
Point3f lookAtV = new Point3f();
Vector3f upV = new Vector3f(0,0,1);
float a = 0;
long currTime = System.currentTimeMillis();
long lastTime = currTime;
while (frame.isVisible()) {
scView.renderOnce();
//--------------------
currTime = System.currentTimeMillis();
if (currTime - lastTime > 30) {
lastTime = currTime;
a += 0.03f;
camL.z = (float)(1.8f*(Math.cos(a/2)));
camL.x = (float)(1.8f*Math.sin(a));
camL.y = (float)(1.8f*Math.cos(a));
scView.getTransform().lookAt(camL,lookAtV,upV);
}
//--------------------
}
System.exit(0);
}
public static void main(String args[]) {
new OrderedGroupTest();
}
}
BTW, if you put Spheres instead of quads - exactly the same story apply… You can control order with no problems…
So basicaly, it seems like OrderedGroup/DecalGroup is working only when geometries of shapes are exactly coinciding! Then you really have control over rendering order!!!
Interesting… what is the logic behind the OrderedGroup then? How it really works and why this condition (coinciding geometries) is necessary? Why it couldn’t be applied just to any shapes?
yup that are exactly the results I’m getting.
If it would work like that consequently there would be no problem (from my side of view), but as I mentioned previously, transparency is also not handled correctly - With transparency I’m talking about alpha values of 0.5 and such. 0/1 transparency seems to work.
Actually if you want to specify the order of the rendering you could use the new MultipassView, but I think this might be a bit too overcomplicated.
Well… agree, but only regarding DecalGroup since the meaning of name “DecalGroup” assuming “decals” and everybody can expect certain conditions needs to be met.
But!!! “OrderedGroup” has too strong and general name to be limitted to this kind of behaviour. It either should be fixed to work for any shapes as it’s name suggest, or need to be renamed to reflect the limitations!
Do you agree?
I agree.
And I’ll look into the code.
Well, I must learn a bit more about the renderers architecture before understanding where OrderedGroup is handled…
I’ll see what I can do.
I agree, too
Another interesting discovery ???
Actualy, if in those tests mentioned above you change OrderedGroup/DecalGroup to just Group - will make no difference at all!
This that the rendering order is controled by order in the group when Shapes’ geometries coincide fully apply to “Group” too!!!
But this is actually understood, if geometries coincide no dicision can be maden by renderer who goes first so the order is just left intact, so we getting order as specified in the group and there is no magic!
In other worlds it seems that neither OrderedGroup neither DecalGroup is ever handled differently from just ordinary Group they extend…
Arne, you was saying you have some applications of OrderedGroup… Can you try to change OrderedGroup to Group there and see if it makes any difference? I positive it will work just exactly the same way. Its seems they all three are just equivalent… :-\
Hi,
[quote]In other worlds it seems that neither OrderedGroup neither DecalGroup is ever handled differently from just ordinary Group they extend…
[/quote]
Not true. I am using OrderedGroups extensively, and they work for me perfectly.
Note that:
- OrderedGroup works ONLY for Opaque shapes, and ONLY when opaque sorting policy set to View.OPAQUE_SORT_BY_SHADERS (should be default).
- OrderedGroup DOES NOT WORK for Transparent Shapes (for now - can be changed afterwards)
- On Opaque Shapes, you will see the result of OrderedGroup IF AND ONLY IF you disable the depth test - otherwise gfx card still may skip pixels because of they do not pass configuret depth test
- It is very easy to add new sort modes, but it is not a good idea right now to let user set a custom state sorting function because of it will require exposing too much of rendering pipeline internals that may (and will) change in future.
- As of rendering coplanar geometry, in OpenGL there is a special thing called Polygon Offset for handling such a cases - refer to Xith3DPolygonOffsetTest.java I wrote long time ago when added support for this feature. It also supposed to handle “nearly co-planar” shapes, as well as “exactly coplanar” which you are testing.
- To check details of how state sorting works, explore Renderer.buildRenderFrame - it controls all the sorting.
- Practically, you will get desired results (I think) when change depth test function in RenderingAttributes to LESS_OR_EQUAL instead of default LESS - this will allow one shape to override the other even if depth buffer already has equal value (which is not the case in default configuration).
- Note that currently there is hard-coded limitation of 10 nested ordered groups (which is easy to change). Refer to render.OrderedState for details how it is built.
… I even think I missed something, but I believe that 1-1.5 years ago I already was describing behavior of ordered groups in details when transparency rendering was disucssed…
[quote]Its seems they all three are just equivalent…
[/quote]
Again, not.
Yuri
Yay!! got it working
- OrderedGroup works ONLY for Opaque shapes, and ONLY when opaque sorting policy set to View.OPAQUE_SORT_BY_SHADERS (should be default).
seems to be the default - didn’t need to set it[quote]
2. OrderedGroup DOES NOT WORK for Transparent Shapes (for now - can be changed afterwards)
[/quote]
It does work - I have tested it[quote]
3. On Opaque Shapes, you will see the result of OrderedGroup IF AND ONLY IF you disable the depth test - otherwise gfx card still may skip pixels because of they do not pass configuret depth test
[/quote]
That did the trick!!! I think we should add a comment in the javadocs [quote]
4. It is very easy to add new sort modes, but it is not a good idea right now to let user set a custom state sorting function because of it will require exposing too much of rendering pipeline internals that may (and will) change in future.
5. As of rendering coplanar geometry, in OpenGL there is a special thing called Polygon Offset for handling such a cases - refer to Xith3DPolygonOffsetTest.java I wrote long time ago when added support for this feature. It also supposed to handle “nearly co-planar” shapes, as well as “exactly coplanar” which you are testing.
6. To check details of how state sorting works, explore Renderer.buildRenderFrame - it controls all the sorting.
7. Practically, you will get desired results (I think) when change depth test function in RenderingAttributes to LESS_OR_EQUAL instead of default LESS - this will allow one shape to override the other even if depth buffer already has equal value (which is not the case in default configuration).
8. Note that currently there is hard-coded limitation of 10 nested ordered groups (which is easy to change). Refer to render.OrderedState for details how it is built.
… I even think I missed something, but I believe that 1-1.5 years ago I already was describing behavior of ordered groups in details when transparency rendering was disucssed…
[/quote]
Interesting - I’ll look into it
Arne
Hi,
[quote]Quote
2. OrderedGroup DOES NOT WORK for Transparent Shapes (for now - can be changed afterwards)
It does work - I have tested it
[/quote]
Arne, try with coplanar shapes of different size when the center of the shapes does not match, rotate your view around the shapes and you will (should) see it does not work - default sorting for transparent pass does not take ordering into account in favor of more precise transaprency rendering.
(OK, I will not enforce you to agree that it does not work, just giving a warning )
[OK, I think we should add one more sorting mode for transparent pass, also having in mind that the method for it is already there - RenderBin.sortOrderedBackToFront (I remember I was programming it, but really do not understand why it is not added to the transparent pass sort modes set).
Yuri
Hi!
Thanks Yuri, for the explanation! I going to give it a try again…
- On Opaque Shapes, you will see the result of OrderedGroup IF AND ONLY IF you disable the depth test - otherwise gfx card still may skip pixels because of they do not pass configuret depth test
I’m not to sure how to “disable the depth test”… Is it about RenderingAttributes.setDepthBufferWriteEnable/setDepthBufferEnable ? Or it should be something different?
[quote]I’m not to sure how to “disable the depth test”… Is it about RenderingAttributes.setDepthBufferWriteEnable/setDepthBufferEnable ? Or it should be something different?
[/quote]
yep that’s it.
[quote](OK, I will not enforce you to agree that it does not work, just giving a warning )
[/quote]
mmh you’re right … It only works, if one of the two shapes is opaque.
what does View.TRANSPARENCY_SORT_NONE do? The result looks ok for my test-case (but I guess it’s only the testcase, where it works)

[quote]I’m not to sure how to “disable the depth test”… Is it about RenderingAttributes.setDepthBufferWriteEnable/setDepthBufferEnable ? Or it should be something different?
yep that’s it.
[/quote]
Well… if its so - I am totaly confused now… :-\
-
From my experience setting DepthBufferWrite(false) will always leave the order intact, whatever order you add you shapes in - in this order they going to be rendered… You don’t need any OrderedGroup for that ??? Am I wrong? You can use just ordinary Group or even don’t use any Groups at all… as soon as DepthWrite is off or DepthBuffer is off just add shapes in order you like to the scene and that’s it. So I still don’t understand what is the difference in handling OrderedGroup appart from ordinary Group.
-
Well, another point here. if I need to play with depth buffer there are other problems:
a) Let’s say I have two kind off “OrderedGroups”. I want each to contain two quads. I want to specify order of quads in each group. I have to set DepthBufferWrite(flase) on each quad to keep the order in groups the way I want. Well, fine - I achivied predefined rendering order this way… but unfortunately not only within the groups! The groups itself will be ordered in respect of DepthBuffer in the order I add them to the scene too!!! So side effect of playing with the depth buffer is that one group will be always rendered in front of another now…
b) Even if I have only one “OrderedGroup”, I can’t use shapes different to “flat” shapes (quads etc). If I want two cubes to be in ordered group, swithching depth buffer on cube - will totaly destroy the cube!!! So again, I don’t see how can I apply OrderedGroup just to any shapes… Only flat shapes (or those that looks same way regardless what is the depth buffer settings ) are assumed to be used here, is it?
Sorry guys if I’m too annoying… I really just want to get clear understanding… and so far… it is too far ;D
The nature & purpose of OrderedGroup is still mysterious to me…
Hi,
[quote]1. From my experience setting DepthBufferWrite(false) will always leave the order intact
[/quote]
No. Depth buffer tests have no relation to rendering order, they just determine if a pixel of the shape being rendered will be written to the frame buffer or will be skipped.
[quote]whatever order you add you shapes in - in this order they going to be rendered
[/quote]
Not true. This depends VERY MUCH on complexity of the scene and appearance attributes set. Example: are adding shapes as following: A textured with TexA, B textured with TexB, C textured with TexA. Assuming that ALL THE OTHERS attributes are exactly the same, State sorter will perform renderer either as A C B, or B A C - in this case objects with the same texture will go consequently to minimize state switches.
[quote]You don’t need any OrderedGroup for that Am I wrong? You can use just ordinary Group or even don’t use any Groups at all… as soon as DepthWrite is off or DepthBuffer is off just add shapes in order you like to the scene and that’s it.
[/quote]
And you will loose performance because of hige overpaint introduced - it will eat all the fill rate and all your FPS.
[quote]So I still don’t understand what is the difference in handling OrderedGroup appart from ordinary Group.
[/quote]
Ordered Group is designed to preserve the rendering order, and it does so. Another thing that you are not necessary see the rendering results - try disable color buffer writes and you will not see your shapes, while depth buffer will be formed correctly.
[quote]View.TRANSPARENCY_SORT_NONE
[/quote]
Just as named - disables sorting. Means shapes will be rendered in the order of scenegraph traversing. It is useful when you 100% know you don’t need sorting because of specific of your scene, and don’t want to loose some CPU cycles.
Yuri
P.S. At this point, I suggest you to start exploring the source code of Xith3D from the anchors I gave - check what is inside and try to build your example to see the difference. I again confirm that OrderedGroup is doing exactly what it should do.
Thanks Yuri!
Yes, you are right, it seems I really need to acquaint myself better with this subject first… befor dropping into conclusions…