Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411564 Posts in 69385 Topics- by 58444 Members - Latest Member: darkcitien

May 04, 2024, 03:19:36 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)How many unique "normal" colors in a RGB cube?
Pages: [1]
Print
Author Topic: How many unique "normal" colors in a RGB cube?  (Read 1605 times)
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« on: August 10, 2014, 09:32:42 AM »

Given a rgb cube of 256 colors per length
and the fact that a normal are coded inside this cube such as its length is always equal

Assuming a certain level of precision error
1. how many unique color in the rgb cube that satisfied this constrain?
2. ho many unique color are needed to code a tangent map if we omit the blue color?
3. what is the formula to derive these numbers given a level of precision?

Basically it's about counting the number of pixel color on the surface of a sphere centered inside the RGB cube
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #1 on: August 10, 2014, 11:48:57 AM »

There are standard formula for the area of a sphere, and of a circle (for omitting blue), that should get you pretty close to the exact answer.

Not sure what you're trying to achieve, but you can use polar co-ordinates to encode normals, which uses a rectangular space more efficiently and have different precision in different directions. It's not normally done as the encode/decode process is more CPU intensive.
Logged
Boreal
Level 6
*


Reinventing the wheel


View Profile
« Reply #2 on: August 10, 2014, 12:29:40 PM »

This problem is basically that of voxelizing the surface of a sphere.  Although rasterizing a hollow circle is easy using Bresenham's algorithm, unfortunately, there is not a 3D equivalent.  The most robust method I can think of is to voxelize a solid sphere, then only count the voxels with at least one "exposed" side.
Logged

"In software, the only numbers of significance are 0, 1, and N." - Josh Barczak

magma - Reconstructed Mantle API
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #3 on: August 10, 2014, 12:58:36 PM »

@Boris
The case with tangent would not be a circle but an hemisphere (mapping coordinate[1,-1] onto vertical (azimuth in G) and horizontal(horizon R), blue coding implicitly degree of the surface normal as -1 (facing the opposite of the surface normal) don't make sense)

While the blue channel don't contribute it's reconstructed with a cross product given each component to resolve a distance of 1 again as a normal is always 1 of length.

Boreal is right it is a voxel sampling problem, so there is only brute force possible?
Logged

jgrams
Level 3
***



View Profile
« Reply #4 on: August 11, 2014, 03:44:30 AM »

Maybe you could use Bresenham to iterate around a quarter or half of the "prime meridian", then for each pixel, figure the radius and use Bresenham again to iterate around the "latitude line"? At first I thought you could just use one of the sequences that gives an answer to Gauss's circle problem instead of the second Bresenham, but that gives you the volume, not the "surface area".

And...hmm. You'd probably have to warm-start the latitude line Bresenham with special values since you wouldn't be starting exactly on the center of a voxel...
Logged
Columbo
Level 0
***


View Profile
« Reply #5 on: August 11, 2014, 10:41:15 AM »

Just brute force it. There's only 16.7 million possible values, shouldn't be hard to write a quick program that tests them all against your criteria.
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #6 on: August 11, 2014, 04:50:20 PM »

Ok let's look at brute force, I'm not much of a programmer myself but
- my first idea was to enumerate through each pixel and test it against length.
- then I simplified the problem to one axis to see how it would works, quickly noticing that on a 256 scales there is no clear middle (-1 to 1 without a clear 0) because it's even.
- then quickly decide it's not a problem because all that count is to have a "float" and check if the end point of the vector is inside a particular pixel
- then wondering how do I check this in 3D?

I must found for each pixel if a normal vector centered at 0 end inside it.

What would the code look like?

I have no idea right now but it sound like a kind of aabb collision system, point vs cube. However there is an infinite amount of vector inside a cube that can satisfied the length requirement, not sure it's the best way.

Another way of looking at it is to compute the intersection of the surface of a sphere with a cube. So for a given cube how to compute if it intersect the surface of a normal sphere centered at 0?

Logged

Fallsburg
Level 10
*****


Fear the CircleCat


View Profile
« Reply #7 on: August 12, 2014, 04:09:03 AM »

I think you are overthinking it.

I think it should go something like:

Code:
Dictionary<int,int> results = new Dictionary<int, int>();
Vector3 testVec = new Vector3();
for (int red = 0; red < 256; red++){
for (int green = 0; green < 256; green++){
for (int blue = 0; blue < 256; blue++){
testVec.x = red;
testVec.y = green;
testVec.z = blue;
testVec.Normalize();
results[ Mathf.RoundToInt(testVec.x*255)+256*Mathf.RoundToInt(testVec.y*255)+256*256*Mathf.RoundToInt(testVec.z*255)] = 1;
}
}
}
Debug.Log(results.Count);

I might have fucked up the rounding at the end (I feel like I'm always off by one on that type of thing.

Anyway, that code says that there are 148,547 unique values that lie on the unit sphere.
Logged
jgrams
Level 3
***



View Profile
« Reply #8 on: August 12, 2014, 05:41:49 AM »

I think your rounding should be fine, but you're treating them as unsigned (0 to 1) instead of signed (-1 to +1, with no exact zero). But yeah, that's way more straightforward than the midpoint-circle method I was playing with. Correcting for that, I come up with 293,480. That's higher than the number I was coming up with from my midpoint-circle method, so I wonder if it's not doubling up on some points. But...I guess you probably want that, since a method for generating normal maps might well use all of them.

I was using this (C) code to convert back-and-forth from 8-bit to float:

Code:
double to_float(int ix) { return 2.0 * ((ix / 255.0) - 0.5); }
int to_int(double x) { return nearbyint(((x/2.0) + 0.5) * 255.0); }
Logged
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #9 on: August 12, 2014, 07:12:22 AM »

Oh good!

Just in time before I figure out the sphere to cube collision (and maybe getting it wrong  XD )

Quote from: jgrams
But...I guess you probably want that, since a method for generating normal maps might well use all of them.

However I don't see how you can use that to optimize normal map, the number fall into the 2^19 which mean you still need 24bits to store it, even by indexing. We would need a texture of 543² to fit all colors and that mean it would be a 512*1024 texture in memory ... I think :/
If anything we can have some extra precision from the remaining but the memory cost is not worth it, it does not beat a single look up.
unless you have a better idea, I'm not an expert, trying to make guess.

However I ask the number out of curiosity, it's 57,1x times less that the full spectrum
Logged

Fallsburg
Level 10
*****


Fear the CircleCat


View Profile
« Reply #10 on: August 12, 2014, 10:02:22 AM »

Ah, right. I was only thinking about it between 0-1. 
Logged
Ashaman73
Level 0
***



View Profile WWW
« Reply #11 on: August 14, 2014, 10:59:17 PM »

However I don't see how you can use that to optimize normal map, the number fall into the 2^19 which mean you still need 24bits to store it, even by indexing. We would need a texture of 543² to fit all colors and that mean it would be a 512*1024 texture in memory ... I think :/
If anything we can have some extra precision from the remaining but the memory cost is not worth it, it does not beat a single look up.
unless you have a better idea, I'm not an expert, trying to make guess.

However I ask the number out of curiosity, it's 57,1x times less that the full spectrum
I'm not sure if I understood you right, but you want to compress normals in a standard normal map while keeping a high-level of quality ?

Just some thoughts, if you target normal mapping for rendering:

1. If you have really large lookup textures (to use a index to get the hi-quality normal), then your performance will likly suffer under almost random texture access (lot of cache misses).
2. If you have a tangent space normal map, consider using only two channels (2x8 bits) and recalculate the third z=sqrt(1-x*x-y*y). The assumption is, that your normals dont' point into the surface (only positive values).
3. Normal maps can be further compressed by using hardware compression (look for DXT5 like compression of normal maps).
4. Take a look http://aras-p.info/texts/CompactNormalStorage.html for more normal compression algorithm, thought they are more suited for g-buffers and higher bitdepth (e.g. 16-bit half floats)
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #12 on: August 15, 2014, 08:41:08 AM »

No I ask the question for curiosity, this breakdown was just to put number in perspective (and an answer to someone it could be use to optimize normal map), however I basically said nearly the same things you demonstrate.

Things you can do however is to store some level of "ao" or "cavity" in the normal map by multiplying the normal with this map. Since length will be non zero, basic light shader would have dimmer result on multiplied normal (assuming the shader does not renormalize). Would not work on more complex shader.
Logged

peteandwally
Level 0
**


how could i fail now


View Profile
« Reply #13 on: September 04, 2014, 08:52:58 AM »

shouldn't it be something close to a triangle inset into the square for the 2d case (a lower limit). Then for 3-d it'd be a pyramid inset into the cube. so, with a radius of 200, the pyramid base has at least 200+199+...+2+1 pixels on it's surface.

Now, the 'point' of the pyramid is all pi/4 radian angles, so the base is radius*sqrt(2)/2 long on each side, whereas a circle imposed on one of those faces would have an arclength of radius*pi/4. So, maybe a guess for the sphere's actual surface is something like pi/sqrt(Cool* (200+199+... yada yada..)

or maybe I'm way off.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic