OoliteProject/oolite — pull request #108 by kanthoney (2014-08-11 20:39:34+00:00)
Title: Shader update

As discussed on the mailing list, we have a problem with our planet shader. The original manifestation of this problem was the razor sharp terminator on the planets when using some graphics cards. We found a work around for that but it turned out that had it's own problems - it stopped the normal mapping from working correctly on affected cards, causing Lave for example to look flat. Eventually, the problem was traced to the matrix gl_NormalMatrix used in the shader. Use of this matrix is deprecated, and some cards simply don't bother calculating it.

The non-legacy method of using shaders is to calculate this (and other) matrices in the application, and pass them to the shader via uniforms, which is what this branch does. It contains a matrix manager which calculates the OpenGL model-view and projection matrices (and matrices derived from these) and then passes them to OpenGL and the shaders. This means that direct use of the OpenGL matrix functions such as glPushMatrix and glMultMatrix to manipulate the model-view and projection matrices needs to be avoided, so I've defined the functions:

void OOGLPushModelView();
OOMatrix OOGLPopModelView();
OOMatrix OOGLGetModelView();
void OOGLResetModelView();
void OOGLLoadModelView(OOMatrix matrix);
void OOGLMultModelView(OOMatrix matrix);
void OOGLTranslateModelView(Vector vector);
void OOGLRotateModelView(GLfloat angle, Vector axis);
void OOGLScaleModelView(Vector scale);
void OOGLLookAt(Vector eye, Vector center, Vector up);
void OOGLResetProjection();
void OOGLPushProjection();
OOMatrix OOGLPopProjection();
OOMatrix OOGLGetProjection();
void OOGLLoadProjection(OOMatrix matrix);
void OOGLMultProjection(OOMatrix matrix);
void OOGLTranslateProjection(Vector vector);
void OOGLRotateProjection(GLfloat angle, Vector axis);
void OOGLScaleProjection(Vector scale);
void OOGLFrustum(double left, double right, double bottom, double top, double near, double far);
void OOGLOrtho(double left, double right, double bottom, double top, double near, double far);
void OOGLPerspective(double fovy, double aspect, double zNear, double zFar);
OOMatrix OOGLGetModelViewProjection();

to be used instead, and replaced the existing matrix functions throughout the code.

If a shader defines any of the following uniforms:

ooliteModelView
ooliteProjection
ooliteModelViewProjection
ooliteNormalMatrix
ooliteModelViewInverse
ooliteProjectionInverse
ooliteModelViewProjectionInverse
ooliteModelViewTranspose
ooliteProjectionTracnspose
ooliteModelViewProjectionTranspose
ooliteModelViewInverseTraspose
ooliteProjectionInverseTranspose
ooliteModelViewProjectionInverseTranspose

then Oolite will populate it. Of these, ooliteNormalMatrix is of type mat3 and all the rest are mat4. The planet shader has been updated accordingly. Shaders that use gl_NormalMatrix and other matrices will work just as well (or as badly) as they did before.

One problem that has arisen with this branch is this glitch:

![oolite-294-nq8](https://cloud.githubusercontent.com/assets/5890866/3882031/71eb69b2-2193-11e4-8c06-8dd17b1b1e45.png)

The problem here is that the planet mesh has a vertex directly on each of the poles (seen in wireframe below, the green line is the y-axis), and the vertex shader works by creating a coordinate system at each vertex one basis vector of which points west (or east, I can't remember). Since there's no west at the poles, the shader fails for this vertex, messing up the adjoining triangles.

![oolite-044](https://cloud.githubusercontent.com/assets/5890866/3882107/1d207f84-2194-11e4-94de-45c19ec26025.png)

I've hopefully solved this problem in this branch by regenerating the planet mesh in such a way that there is no vertex on the poles (in the picture below you can just see the green axis going straight through the middle of one face):

![oolite-045](https://cloud.githubusercontent.com/assets/5890866/3882161/a2609b84-2194-11e4-94f8-3e2985b44462.png)

This means there's no vertex on the poles which should eradicate the problem, although my card doesn't show the problem in the first place.

The downside to this approach is that it replaces a 48,000 line computer generated file (OOPlanetData.c) with another one. Hopefully that won't cause issues (it will increase my contribution to the project in terms of the number of lines by a factor of about ten!) Probably this file shouldn't be managed by git, but I don't know if there's anything we can do about that. In order to regenerate the file I've had to rewrite parts of the icosmesh tool so that it compiles on GNUsetp, and also use a different set of base vertices. I did test the rewritten tool using the original base vertices and the OOPlanetData.c file came out exactly the same.

I've had to change the Mac code a little, but can't test that with no Mac.