Page 1 of 1
News on real-time shadows in D2X-XL and a call for help
Posted: Thu Nov 23, 2006 7:09 am
by Diedel
I have had some time recently to dig into the real-time shadowing code in D2X-XL, and finally managed to get it to work using a very simple 'ship' model in the form of a cube to simplify things.
In the course of this I have found out that even that model was already flawed - either inherently due to the oof format, or by the author, as one face had its normal (perpendicular on the face) pointing inside the model instead of outside.
After fixing this I finally managed to get working shadowing code.
When employing the regular ship models (both low and hires) shadowing didn't properly work though. This is due to flaws in the model data (like face vertex lists in the wrong order, normals pointing to the wrong the direction, adjacent faces not directly connected).
Bottom line: With the current models, realtime shadowing in D2X-XL will not be possible.
So if someone has time at his hands, he'd be welcome to create new, well-modeled player ships (and possibly other bots).
One technical hint: Face vertex order may be reversed, but the face normals must point to the proper direction (if this is assured, I can determine face winding in D2X-XL).
Posted: Sat Nov 25, 2006 5:11 am
by Neumaennl
well, recalculating the normals outside is absolutely no problem in any 3D program, but unless you have a different model from the ones available at the Descent Network it's a major PITA to fix the faces thingy, I've already looked at them and the meshes are horrible.
You'd be better off remodeling them from scratch.
I was going to make a short animation featuring a Pyro for the CG class at University, but when I saw the ugly meshes of the models from the Descent Network I tried to fix them for a few hours, but I eventually got too frustrated to continue and started a completely different scene featuring some kind of mermaid.
Posted: Sat Nov 25, 2006 8:55 am
by Diedel
I know how to compute face normals, but their direction is depending on vertex order. If I knew how OpenGL determined polygon winding, it would be no problem to fix any flaws here.
I do however have a custom pyro where face normals and the entire mesh are 100% error free.
I still have major problems with shadow rendering though. Somehow all calculations are depending on viewer position, and I have no explanation for this. If you know something about this stuff and can help me, let me know and I will explain some more details.
Edit: I am slowly getting closer. Oh man, the D2 transformation code is really getting in my way here ...
Posted: Sun Nov 26, 2006 5:16 am
by Neumaennl
sorry, I suppose I can't help very much here as I don't know anything about OpenGL programming - I'm just starting to get the hang of some modeling things
Posted: Sun Nov 26, 2006 1:03 pm
by Diedel
The problems are more of mathematical nature, but it looks like I am pretty close to having working volume shadow rendering already.
Posted: Sun Nov 26, 2006 1:04 pm
by pATCheS
I imagine debugging the shadowing would be at least a little easier if you made your ship model a single triangle. Have you tried that yet?
I'm looking at the OGL2.1 spec, can't seem to find where it says how normals are computed. I'm thinking it'll be better to look at a 1.x specification for that information, since it's formatted differently and with older hardware in mind.
Say, why does OGL's normal computation matter anyway? Doesn't D2 compute all its own normals? And you need to have face culling off for shadows, so really OGL has no business knowing the shadow faces' normals.
[edit] pfffft one minute apart lol.
Posted: Sun Nov 26, 2006 3:22 pm
by Diedel
I need a more complex model now to test the volume side face rendering (which currently is flawed). The question is not how to compute a face normal, the question is how OpenGL determines face winding. OpenGL needs this for face culling (determining whether it is looking at a face's front or back side).
Currently it looks like the volume side's faces do not always have their normals facing to the proper direction.
Man I am so close to finally having some working shadow rendering (at least for properly constructed models).
Posted: Sun Nov 26, 2006 11:51 pm
by pATCheS
DOH, I just realized, you need culling to selectively increment and decrement the stencil buffer. Well,
this page tells you somewhat how OGL determines face normals. Don't know what the math behind it is, but there's really only two ways it can go, CW or CCW
As far as test models go, test a 4 vertex pyramid, then move up to a 3x larger pyramid with a 1x pyramid taken out of the center (so you're left with 4 1x pyramids). If you can get both of those models to render correctly in all rotations relative to the light, most any solid model should work (not sure of the cases where any wouldn't, but it has to do with the number of faces per edge). If these test cases work but shadowing a complex object still doesn't work, odds are something's wrong with the object's model.
Posted: Mon Nov 27, 2006 3:07 am
by Diedel
I don't need your pyramid models, I have all the models I need. I also don't need your insight about face culling, because I am already three miles ahead of you in this area.
But I will explain to you what the problem is. To render the shadow volumes, you have to extrude the volume sides from the edges that form the silhouette of the model as seen from the light source.
Now face direction (front/back) is determined by OpenGL with some geometrical operation depending on the position of a polygons vertices (polygon winding). Lets take a quad for the sake of simplicity: You have four corners v[4] at (0,0), (1,0), (1,1) and (0,1). That is GL_CCW (counter-clockwise). You can determine this by determining the sign of (v[1].x - v[0].x) * (v[2].y - v [1].y) (you don't need to consider z for this). If it's < 0, you have GL_CCW, otherwise GL_CW.
Extruding a volume side quad goes by using its edge's two vertices (ev[2]) and computing two more vertices by projecting them to infinity as seen from the light source (lv). This goes like
ev[2] = (ev [1] - vl) * INFINITY
ev[3] = (ev [0] - vl) * INFINITY
where INFINITY is some sufficiently huge value. (You can do infinity projections by setting up a special transformation matrix, but it works good enough this way).
So far, so good, but when computing the silhouette edges, I am getting their vertices in some arbitrary order. That means that the volume sides extending from them have some random winding. That means that they can be considered a back face by OpenGL although they should be a front face and vice versa.
(A silhouette edge is an edge between two model faces where one of the faces is visible from the light source and the other is not).
Generally in D2 all faces are defined GL_CW (so you have to enable GL_CULL_FRONT if you want to have OpenGL not render the faces pointing away from the viewer - a small quirk in the engine). Now consider two adjacent model polygons (i.e. sharing an edge). Depending on which I treat first when determining silhouette edges, I will get the edge's vertices in the order (v
,v[i+1]) or (v[i+1],v) (i being a valid index of the polygon's vertex list).
I am having an example using a cubic model where this already causes problems.
I have no idea how to fix this. And this the key to making this stuff finally work.
Edit: Maybe I can determine the winding of the faces after having transformed their vertices ... a volume face should have the winding of that face of its edge that is invisible to the light source ...
Edit 2: Seems like I can't ...
Posted: Mon Nov 27, 2006 5:49 pm
by Diedel
I have asked in some OpenGL forum and got a good answer ...
Posted: Mon Nov 27, 2006 7:11 pm
by Shadowfury333
Diedel wrote:I have asked in some OpenGL forum and got a good answer ...
And that answer is?
Posted: Mon Nov 27, 2006 8:26 pm
by Diedel
You always need to look at the vertex order the edge has in the polygon facing the light source.
Btw, the shadowing code is working now, but it is as I suspected: The Descent 2 models and also Eagle's hires pyro are horribly broken in terms of shadow rendering. Even my own custom Pyro had quite a few flaws (mostly duplicate faces). I have fixed most of them, but one is still present.
So in theory we can now have real time shadowing in d2x-xl, but in practise it doesn't work due to the badly built models. :-/
This is kind of a let down.
heh.
At least I learned a few more things about OpenGL and could optimize D2X-XL rendering processes a little bit. The guy(s) doing the initial OpenGL code did somewhat of a half-baked job. They were probably learning by doing, like me.