fix culling
there's already some open issues related to this but let's review culling in all primitives, both 2d and 3d, and debug draw for objects like nodes, lights... decide which kind of culling we want and fix it for good. i'm milestoning this for 0.11 but we can start working on it whenever, if it's ready before 0.10 is released we can include it then.
That's close to my heart =)
I'm linking issues #3381, and #2676 here, which are related / refer to this.
Had a really hard time with these culling issues as I am a beginner with OF.
- Using :
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) for two sided lit polygons.
- glEnable (GL_CULL_FACE) with glCullFace(GL_BACK) for culling backfaces.
Both cases provoke a global lighting reverse. Correlatively the wrong sides are culled (front instead of back). glFrontFace(GL_CW) seems to neutralize this odd behavior.
- getTessellation() method of ofPath returns reversed normals on faces, so I need to mirror all points on X axis beforehand to fix this before passing to a ofMesh. I tried before to fix it with each modes inside setPolyWindingMode() method but no luck here. I'm not sure if it is related to 1).
Hope that theses spaghettis balls aren't going to blow up in my face later ;)
ping @vade
@tgfrerer at the moment is the ofBoxPrimitive the only one doing CCW winding? Have you noticed any other cases where winding is not CW?
It sounds like a good fix would be to make all winding CW ( as almost all is ) and then set glFrontFace(GL_CW) in the setupDefaults() call.
A more involved solution would be a global way to set CW vs CCW which could allow an OF app to be CCW by default if set, this would probably mean all the OF primitives would need to generate both winding orders - but that might be as simple as just doing std::reverse on their indexes.
A good first step would be to get it all consistent. pinging @NickHardeman also as he wrote a lot of the primitive code.
hey hey @ofTheo - this is the major issue I was seeing - working with deferred rendering with offscreen gbuffers means flipped normals and wrong lighting, wrong culling, etc : #3381 - which I see is mentioned above.
ofBoxPrimitive is CCW, yes, while most other elements i can think of are CW. The icosphere primitive is currently "patched" by swapping vertices shortly after generating and could be easily switched back to CCW (which would make it faster when generating).
Although it might be slightly more work to switch all primitives to consistently to use CCW, i think it's a good idea to do so:
It stays true to the principle of least surprise. Having a "hidden" global GL default setting which would deviate from the GL default (the GL default being CCW) increases the friction for people who come with expectations from other frameworks and libraries.
I like the idea of having the option to specify winding order when generating primitives (if we could do this without globals, the better).
How about a signature like:
static ofMesh m = ofMesh::icosphere(200,3, OF_WINDING_CCW);
with OF_WINDING_CCW being an enum, and the default parameter setting for these methods being: OF_WINDING_CCW?
@tgfrerer
how would this relate to what @memo brought up here: https://github.com/openframeworks/openFrameworks/issues/2676#issuecomment-66174941
From what I understand OF's winding order is related to its handedness - so wouldn't changing the winding default, without changing the handedness cause other issues?
Or is that just OF's default handedness - vs ofCamera which is like OpenGL's
also @tgfrerer could you see any other bugs/regressions being caused in existing projects from switching winding to CCW?
Thanks!! Theo
I think it could make sense to tackle each of these two things separately. As this article mentions, the two questions are related, but can be looked at independently.
Reading the article again, I found myself agreeing heartily with the mention that in the end, if you got your maths right, it boils down to setting either a "minus" or a "plus" sign.
The more important point imho is to create consistency within each domain, so that the maths can be correct. So if we agree on a winding order, we need to make sure that it's applied 100% consistenly.
Part of why i'm reeling under such dilemmas is that i'm a self-diagnosed binary dyslexic: left and right and ccw and cw and row-major and column major "feel" absolutely the same to me - and it takes me extra effort to remember them correctly, and I cherish consistency because once I have memorised them painfully enough, it frees me not to have to look these things up every time I use them. I might not be the only one feeling like this =)
It's not that a particular handedness requires a particular CW vs CCW winding order. But you DO have to construct your mesh differently depending on the coordinate system you're creating it in, AND how front faces (i.e. normals) are defined (in the case of opengl: glFrontFace). I cannot see how handedness can be totally independent from mesh construction / winding order. That article omits winding order altogether, and when it's brought up in the first comment the OP accepts that you'd need to flip winding order. I do agree that consistency is the most important thing.
I really don't want to repeat anything I wrote in my other looong comment https://github.com/openframeworks/openFrameworks/issues/2676#issuecomment-66174941 :), so here is a new practical example:
(this is from memory so might be inaccurate, pls someone correct me if any detail is wrong).
E.g. imagine creating a unit cube in LHCS (e.g openframeworks / processing / unity / unreal4) using coordinate system +x right, +y up, +z into screen (i.e. rotating coordinate system 90 deg around x-axis in openframeworks):
(I found and modified this image from http://www.ctralie.com/Teaching/Tetrahedron/cube4vertices.png)
if glFrontFace is set to its default CCW (i.e. the face normal points towards the direction from which the vertex order of the face appears to be CCW), then we'd want to wind the vertices CCW looking at each face flat on from the outside (i.e. with its desired normal pointing towards us):
- front face: 1-2-4-3 (at z == 0)
- back face: 6-5-7-8 (at z == 1) (notice that this is CW relative to the image above, because we want it facing away from us. It is CCW if we were looking at the cube from behind)
- left face: 5-1-3-7 (at x == 0)
- right face: 2-6-8-4 (at x==1)
- bottom face: 5-6-2-1 (at y== 0)
- top face: 3-4-8-7 (at y == 1)
(if glFrontFace were CW, then we'd have to create the vertices in the opposite order for each face)
In RHCS, one of the axes would be flipped. (e.g. default opengl is x+ right, +y up, +z out of screen)
So if we used our model in say default RHCS opengl, the vertices 5-6-7-8 (at z == 1) would now be the front of the cube (since +z is pointing out of the screen) while vertices 1-2-3-4 (at z == 0) would be the back of the cube. The directions of their normals would not change but would now be pointing inwards instead of outwards (because the back became the front and the front became the back).
Also the normals for the other faces would be flipped, because looking from the right, 2-6-8-4 (right face) wouldn't appear to be winding CCW, but would appear to be CW. Or to put it another way, 2-6-8-4 would appear to be CCW (i.e. matching glFrontFace) only if we look at it from the left. Likewise with 5-1-3-7 (left face) etc.
So the mesh itself doesn't really have a 'winding order' per se. Instead each face is constructed with a particular winding order to face the desired direction in a particular coordinate system.
In other words it doesn't matter how you construct your mesh, as long as you do it correct for the specified glFrontFace (or whatever convention is defined as 'front') and the handedness of your coordinate system. If you move that mesh to another handed coordinate system you will need to flip the mesh and possibly manually invert normals, flip the winding order and/or definition of 'front' faces (e.g. glFrontFace), depending on rendering pipeline.
I think @tgfrerer's advice is a good one, leave glFrontFace as opengl default (CCW) to minimize confusion, and then rewrite all of the ofPrimitives to construct meshes to have desired normals with default openFrameworks camera (LHCS).
Having an option for winding order is also a really good idea, as it means if someone decides to switch to default opengl coordinate system (RH), they can still use the primitives. However I fail to see OF_WINDING_CW or OF_WINDING_CCW as the correct parameter for this. Because as I described above, for a simple cube 2-6-8-4 would give us the desired CCW winding in a LHCS, whereas 6-2-4-8 would give us desired CCW winding in RHCS.
I think a simple option could be ofMesh::flipNormals() (and/or ofMesh::flipWinding()). By default all primitives construct in a way to match glFrontFace(CCW) and LHCS, but we can just flip normals of any mesh. That way if someone switches to a different handed coordinate system, they can flip all normals of their mesh if something goes wrong.
I think this will have the least backwards compatibility issues, and most flexibility going forwards.
Definitely agreed that consistency is the most important thing. The fbo problem mentioned in one of the other issues needs to be resolved separately, probably by again flipping the winding order of quad. Which could be done by the new ofMesh::flipWinding() method perhaps :)
yeah +1 to switch everything to ccw and not touch open gl defaults. it would be more work but it shouldn't break much i think
sounds good to me!
I do think some easy way to flip normals makes sense too.
ps: I love @memo posts - its almost like a chapter from a book I want to read :)