views:

744

answers:

2

Using GLfixed as my vertex number type the following code draws textures as expected:

GLfixed vertices[] = 
{
 (int)point.x,   (int)point.y + size.height,
 (int)point.x + size.width, (int)point.y + size.height,
 (int)point.x,   (int)point.y,
 (int)point.x + size.width, (int)point.y
};

glVertexPointer(2, GL_FIXED, 0, vertices);

I read in the OpenGL docs that GLfixed is the least efficient type and that I should be using GLfloat instead. But when I switched my code over to floats nothing gets drawn.

GLfloat vertices[] = 
{
 point.x,  point.y + size.height,
 point.x + size.width, point.y + size.height,
 point.x,  point.y,
 point.x + size.width, point.y
};

glVertexPointer(2, GL_FLOAT, 0, vertices);

Is there another flag I need to set in the OpenGL state machine to get this to behave as expected?

A: 

When I look at the documentation it looks like GL_FIXED is a fixed point 16:16 format. That means that the 16 upper bits of a GLfixed represents the integer part and the fraction is the lower 16 bits divided by 65536 (1 << 16).

To convert this to a float simply divide the number by 65536:

const float scale = 1.0f / 65536.0f;
GLfloat vertices[] = 
{
        point.x * scale               , (point.y + size.height) * scale,
        (point.x + size.width) * scale, (point.y + size.height) * scale,
        point.x * scale               , point.y * scale,
        (point.x + size.width) * scale, point.y * scale
};

glVertexPointer(2, GL_FLOAT, 0, vertices);

If you're vertex coordinates etc is also in GL_FIXEDformat you'll have to scale them as well.

Hope this helps.

Andreas Brinck
Is that another way of saying that `GLfloat` is incompatible with `float` (the default type of `CGPoint` and `CGSize` used to calculate these vertices)?
Shaun Inman
@Shaun No, not at all. But if the values in `point` are float that just means that they've been scaled with 65536 to work correctly with `GLfixed`.
Andreas Brinck
Thanks Andreas. That totally works but I still don't understand why it's necessary. None of the example OpenGL code I've come across online or in iPhone dev books require this scaling to use `float`s.
Shaun Inman
You're probably using GLfixed values elsewhere, perhaps in the setup of your projection or model view matrix. This might be setting your viewable volume to be 0..1, 0..1, 0..1, so if you just typecast the fixed-point values to floats, your model is probably way outside of that volume. By normalizing the fixed-point values to 1.0 before typecasting to floats, your model would now lie within the viewable volume.
Brad Larson
@Brad That's probably it since I use `glOrthox()` to set a specific pixel size (my games are blocky 8-bit affairs) instead of `glOrthof()`.
Shaun Inman
+1  A: 

Fixed is a 16:16 format. When you cast a value to 'fixed', the compiler doesn't know this format is special, so it is the same as if you cast to int.

For example, if point.x is one, then:

(int)point.x -> 0x00000001
(GLfixed)point.x -> 0x00000001

When OpenGL interprets 0x00000001 as a GLfixed value, OpenGL actually sees 1/65536. If you wanted OpenGL to read 1.0, then the proper encoding is 0x00010000.

When you switched to float, OpenGL was actually getting a real 1.0.

So, it isn't that you need to scale the float values, the problem is that you are ALREADY scaling your fixed values, and the rest of your app is already set up to compensate for that. When float is used, that existing scale factor is now not doing what you want.

For example, get your app working by doing a proper conversion to fixed (int << 16, assuming your points are stored in integers), and you'll see the same bug. Once you find that other transform and fix it, then both 'proper fixed' and float should behave the same.

Frogblast
Thanks Frogblast. Your answer threw what Andreas was saying into focus.
Shaun Inman