Point at which gl size = pixel size

Started by
6 comments, last by Headkaze 13 years, 9 months ago
I am attempting to find out how to draw sprites in OpenGL in a specific way:

Imagine you have a quad size 32 x 32 (in opengl sizes) directly facing the camera, and it's textured with a 32 x 32 pixel texture, and the quad is travelling away from the camera in the z axis. At some point that quad is going to appear to actually be 32 x 32 pixels in size. What I would like to do is define the point at which the the opengl size is the same as the pixel size. I.e. at -10 from the camera the 32 x 32 quad will be 32 x 32 pixels wide/high. I imagine I need to scale it somehow...

I want the sprites to get bigger or smaller if they are closer/further away from the screen, I just want to be able to define the point at which they render at the correct size.

Any help appreciated
Advertisement
Perhaps you could use orthographic projection? This way objects won't be shrinking in the distance so they'll always keep your size?
OpenGL fanboy.
I specifically want the objects to scale based on z distance.
Assuming that the quad is already facing the camera and also assuming a symetric frustum projection this means that after the projection the initial quad'x x and y must equal x'(projected) and y'(projected).

x' = x*near/z
y' = y*near/z

this is true only when near / z = 1 so near / z = 1 and so z = 1/near, where near is the distance from the center of projection to the nearplane.
I am not really sure if that is what I am looking for. The reason I think this is because I really think this has some relation to the size of the viewport. Assume for example I found the point z such that a 32 x 32 quad appeared to be 32 by 32 pixels. Render the same quad at the same z distance in a larger/smaller viewport and the quad will appear larger/smaller than 32 x 32 pixels. So clearly we should be talking about ratios of the viewport size.
I asked a similar question here except I wanted to know the size of a texel when Z=0. Ashaman73 gave me a basic algorithm to calculate a texel in world space when using gluPerspective(). Here is my translation to a function.

static inline SizeF getTexelSize(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar){	GLfloat height = tanf(fovy / 2.0f) * zNear;	GLfloat width = height * aspect;		SizeF texelSize = SizeFMake(width / SCREEN_WIDTH, height / SCREEN_HEIGHT);		return texelSize;}


I'm not entirely sure if it's correct, but supposedly it gives a texel size when Z=0. Not exactly what you were after but it may help?
I think this could actually be useful

static inline SizeF getTexelSize(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar){	GLfloat height = tanf(fovy / 2.0f) * zNear;	GLfloat width = height * aspect;		SizeF texelSize = SizeFMake(width / SCREEN_WIDTH, height / SCREEN_HEIGHT);		return texelSize;}


Basically I think I need to work out how height and width change based on z distance so I would take this

GLfloat height = tanf(fovy / 2.0f) * zNear;
GLfloat width = height * aspect;

and formulate

GLfloat heightAtZ = f( z ) * height
GLfloat widthAtZ = aspect * heightAtZ

Where z is the z distance and f calculates the scale factor at z.

I then want to solve the equations

widthScale * SCREEN_WIDTH / widthAtZ = 1
heightScale * SCREEN_HEIGHT / heightAtZ = 1

i.e

widthScale = widthAtZ / SCREEN_WIDTH
heightScale = heightAtZ / SCREEN_HEIGHT

(this is the texels/pixel ratio)

I believe the height equation is wrong, that's only half the height. so it should be

height = 2 * tanf(fovy / 2.0f) * zNear;

I also think that by using similar triangles, f( z ) = 1 + z/nearPlane

Which would yield a function like:


static inline SizeF getSpriteSize(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar, int pixelWidth, int pixelHeight, GLfloat zRealSize ){	GLfloat height = 2 * tanf(fovy / 2.0f) * zNear;        GLfloat heightAtZ = ( 1 + zRealSize/zNear ) * height;        GLfloat widthAtZ = aspect * heightAtZ;                GLfloat heightScale = heightAtZ/SCREEN_HEIGHT;        GLfloat widthScale = heightAtZ/SCREEN_WIDTH;        GLfloat spriteHeight = heightScale * pixelHeight;        GLfloat spriteWidth = widthScale * pixelWidth;        	SizeF spriteSize = SizeFMake( spriteWidth, spriteHeight );		return spriteSize;}


I think this function should give me the width and height of the quad to draw so that when I draw a sprite at distance z it is pixelWidth by pixelHeight in size. It would also maintain the aspect ratio of the sprite itself if it works correctly.

[Edited by - MoonDemon on July 22, 2010 1:26:39 PM]
Here are the two functions I ended up with

static inline SizeF getTexelSize(GLfloat fovy, GLfloat zoom){	GLint viewPort[4];	glGetIntegerv(GL_VIEWPORT, viewPort);	GLfloat screenWidth = viewPort[2], screenHeight = viewPort[3];	GLfloat height = tanf((fovy * M_PI / 180.0f) / 2.0f) * zoom * 2.0f;	GLfloat width = height * (screenWidth / screenHeight);		SizeF texelSize = SizeFMake(width / screenWidth, height / screenHeight);		return texelSize;}static inline SizeF getScreenSize(GLfloat fovy, GLfloat zoom){	GLint viewPort[4];	glGetIntegerv(GL_VIEWPORT, viewPort);	GLfloat screenWidth = viewPort[2], screenHeight = viewPort[3];	GLfloat height = tanf((fovy * M_PI / 180.0f) / 2.0f) * zoom * 2.0f;	GLfloat width = height * (screenWidth / screenHeight);		return SizeFMake(width, height);}

This topic is closed to new replies.

Advertisement