Hi everyone!Time for some updates. Implementing the actual atlas took quite a little longer than a week, which however, was to be expected. After all it was a rather complex change. During the last two weeks the atlas code has gone through quite some changes. As you may recall in an earlier A&O I described, how I seperated texture internals to sprites and textures.
Atlas after adding 14 sprites
Atlas after adding 7 sprites
The next logical step was to pack several sprites into a shared texture like you can see in the following images:
The whole process works adaptive, meaning one sprite can be added after another. The packer will try to insert the requested sprite as good as it can into the free region(s).
However at some point new sprites wont fit in anymore. As you can see the atlas is already quite full after having added 13 sprites to it.
Time for this weeks A&O.
I've pretty much finished upgrading everything thats relevant to GL2+ and GLES 1.3+.
Meaning we should be more or less ready for ES2.
For the water rendering (It really just was a vertical gradient), I've added a seperate shader.
The only stuff thats still missing to be upgraded is the stereo draw mode.
For this week I've planned starting to finally integrate the rectpacker into the engine.
Both modes, GL2 and the original FFP GL1.x mode should benefit from this, as this reduces
the amount of times textures must be changed.
I'm as well trying to get an ES2 emulation layer on my desktop in order to find the last missing pieces, keeping the GL2 version incompatible.
As promised last week, we now have a GL2 version that uses GLSL 1.20 shaders (with a few compatibility propfile features) to render everything.
I've as well replaced all projection related code by using a plain uniform matrix.
This is an essential step towards the non FFP using GLSL 1.30+ transition, which we will need for ES2+ or GL3+ only systems.
So far everything, but the water rendering, runs smooth.
I did not decide, yet, if I shall honor per vertex coloring for all sprites or if we'd have
an additional, independant render pass for the water, as only the water requires this feature.
By next week I hope to have a fully functional GLSL 1.30+ pipeline.
The major changes involved here, are replacing all gl*Pointer stuff with attributes,
as well as removing some leftover FFP state as glColor to uniforms.
Once this is done I'll need to rewrite the stereo rendering, which, due to using quite some FFP, is most likeley broken at the moment.
At that point we should pretty much have forward and backward compatibility ranging from GL1.1 to GL4.x and I can finally start with the actual atlas optimization, which I already prepared two weeks ago.
Time for this weeks A&O report.
As indicated by last weeks objectives, I've started reducing the Fixed Function Pipeline (FFP) code,
which became obsolete with GL2 and finally deprecated with GL3/GLES2.
In particular I refactored pretty much all of the matrix related code.
So for me it was just doing some applied linear algebra that week.
OpenGL1 had a so called Matrix stack functioning like this:
Backs up the current matrix.
Most GL implementations don't provide pusing more than 16 times, however Hedgewars required only one time.
Restores the most recently pushed matrix.
Sets the current matrix to identity (1)
glScale, glTranslate, glRotate, glOrtho2d, (gl utility funcs gluPerspective gluOrtho):
Multiply the current matrix with specific matrices thus chaining the mapping.
These functions allowed for easy chaining of transformations like:
glRotate(), glTranslate(), glScale() would first rotate the object around its center
then move it along the rotated coordinate system and then scale the object.
As already stated this functionality became completley stripped at some point.
So I either had to emulate existing functionality with an own matrix stack and replacement versions of all the above functions, or I could explicitly calculate matrices
The later option was quite a nice way to go, as Hedgewars first of all just uses 2d transforms
and futhermore all of them were composed like "translate rotate translate".
Thus replacing the reoccuring pattern of:
glPushMatrix() glTranslate(x, y, 0) glRotate(angle, 0, 0, 1); glTranslate(s, t, 0);
m = calculate(x, y, angle, s, t); glLoadMatrix(m);
was a quite straight way to go, as opposed to use full blown matrix multiplications.
To keep the impact of the changeset low I decided to not have some god-function as calculate() above,
but provided utility funcs that semantically m
The image to the right shows the old encoding sprites had. TTexture described a sprite/texture as a single, shared entity defined by it's width (s.w) and height (s.h), together with the actual image data of the sprite (the rect portion within the black rect). However due to hardware restrictions the actual texture might need to be of a certain size and thus to be larger.
The new encoding splits TTexture to two independant entities. A sprite now stores information about its size and references to physical image by storing a link to it and a position where the sprite is located.
This encoding allows to pack multiple sprites (red rects) into a shared image (black rect). Doing so may reduce the amount of unused empty space as well as the total count of black rects. Graphics hardware generally benefits from both.
Right now however each sprite (red rect) will be created together with a unique texture (black rect) and stored in the lowever left of it, mimicing exactly the original behaviour. The next step on this frontier obviously will be taking the rectangle packer and allocate multiple sprites within shared textures.
Before doing this step however, I'll continue with removing as much deprecated OpenGL1.x as possible and probably write some GL2 renderer.