Closed mattrdowney closed 5 years ago
(preferably centered) so that pixel bands appear to be interlaced rather than having a gap along angle=0
Mipmapping, even for power of 2 textures, is non-trivial.
I was wondering how radial textures would be compressed and it turns out it was wayyy simpler than I thought:
If a radial texture uses the following pixels: x xxx xxxxx xxxxxxx xxxxxxxxx xxxxxxxxxxx xxxxxxxxxxxxx xxx.xxx.xxx.xxx.xxx
Then it might be said to be a 8×15 texture with extra pixels that are not used being left at the liberty of the programmer: ideally being used to maximize accuracy and minimize file size.
E.g. for JPEG images that compress in 8x8 blocks the following would be a good encoding scheme:
aaaaaaaa abcabcab abcdeabc abcdefga abcdefghiabcdefg abcdefghijkabcde abcdefghijklmabc abcdefghijklmnoa
Where a,b,c... indicate the position of the pixel in the row.
This assumes accuracy is the most important. The final (unrepresented) block would likely match the average color of the other three 8x8 blocks.
On why:
Z-culling isn't particularly relevant in Planetaria, c-distance is more relevant (center distance).
Additionally, if you imagine placing square tiles all over a sphere, the seams between edges would have uneven contours at points (which would be visually distracting). Circles, on the other hand, fare a little better and work better at the vertices of a "subdivided octahedron sphere".
On why (sub-note):
Radial textures are intended for a sparce/flyweight representation of PlanetRenderers that can be run-length encoded. I might call that a texelplex or something for the hell of it.
If it's hard to visualize, this is for "painting the ground of a circle" (e.g. with grass or dirt) and is conceptually similar to reusable tile textures.
Renderer rotation on a Planet must wrap continuously (ideally) for aesthetically pleasing tiling.
The texelplex would probably do best if quasi-recursively defined. E.g. the texelplex stores a reference to the radial textures (sort of like how gifs reference their pixel color definitions) and then maps from the same circular grid as before (storing only a unique index into the texture array).
Conveniently, the number of pixels in a ring is 1 +2r, which increases linearly like the circumference (2pir), which means that c-distance would work well for texturing (without causing graphical artefacts at seams as the radius expands).
Visual note: tiling near the pole will look uncannily similar to the biohazard symbol.
I have come to the conclusion that my favorite texture format is:
2,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62, etc (conveniently symetric and avoids a double radius at the first pixel)
Where compression/packing looks like:
abab.abab.abab.abab efab.cdef.abcd.efab cdef.ghij.abcd.efgh ghij.klmn.abcd.efgh
which ends up being a n x 4n picture (4 columns for every row).
Notably: the center right column always starts with a and list cells in increasing order to the right (and decreasing and wrapping order to the left)
I feel like simpler would be better, since this spiraled out of control and prime numbers make any two radial strips difficult to compress (e.g. a ratio of 3/5, 5/7, etc).
For the moment being, pixels should probably be compressed as a linear strip top-to-bottom, left-to-right, with run-length encoding.
In the future, compression might happen in cartesian-2D or polar coordinates, but for now that feature would be difficult to properly make.
One possible encoding scheme:
Create three radial compression lines: left, right, and center.
E.g. 1,3,5,7,9 would use the left, right and center pixel to determine changes along the radius.
Create n circular compression lines as before.
Then combine results.
A better sequence is 3x (1,3,5,7,9...)
Because 3 ~= pi (the circumference is 2 pi r (Note: the sequence is 1 + 2r))
Name: PlanetariaTexture
Done as of e68ed5f02fe884088a989f20ab09c766e1f9d4d5
(Although some comments are unfinished.)
The compression technique (four quadrants of a square texture) came to mind when looking at the most recent implementation of SphericalRectangleUVCoordinates, where the result of simple stretching of the square approximated a spherical circle, hence the tangent.
I fucked up (twice)
Seems to be done (tested on bivariate color scheme - not a checker board).
Notably, none of this is happening on GPU (so it's slow and must be done in a pre-processing step).
While Cartesian 2D circles follow the PI*r^2 area formula, in spherical coordinates pixels close to the center are larger.
https://www.sciencedirect.com/science/article/pii/S0925772112000296#! Provides some good insights.
This is also similar to some shader I made for brick walls back in the day.
Texture with pixels (still picture elements) laid out like so:
Center pixel is a circle with radius 1/sqrt(pixels). Next element is a ring of three pixels surrounding the arc from 1/sqrt(pixels) to 1/(2sqrt(pixels)) - three segments (preferably centered). And so on with sizes 1,3,5,7,9 (sum: 1, 4, 9, 16, 25...), inner radii 1/[(k-1)sqrt(pixels)] to 1/[(k)sqrt(pixels)] The textures have even resolution (i.e.) area = pir^2 and the inner area indeed increases by r squared (hence the 1, 4, 9, 16, 25...).
To run fast on GPU, it's hard to say what would have to be done...
That being said if the pixels were laid out in a texture colors[n]:
the radius essentially gives an additive shift radial_index: +1, +4, + 9, etc the angle combined with the radial_index gives a angular_index: +0, +1, +2, etc