# Icon drawing in 3d

**URL:** <https://community.khronos.org/t/icon-drawing-in-3d/65420>\
**Category:** OpenGL: Basic Coding\
**Created:** [August 19, 2011, 12:57pm UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420 "2011-08-19T12:57:25Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![anopgl](https://community.khronos.org/letter_avatar_proxy/v4/letter/a/839c29/32.png) [@anopgl](https://community.khronos.org/u/anopgl)\
**Post date:** [August 19, 2011, 12:57pm UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/1 "2011-08-19T12:57:25Z")

</div>

Hi

I’m drawing some 2d icons in 3d game using billboarding(they should always face the camera). They purpose is to sign specific places in the scene.  
How can I keep icon(image ) sizes small and correct looking while drawing in 3d perspective projection? Is there any known relation between original icon size in pixels and the size to to be given in 3d metric space?

Thanks

---

<div class="post-metadata">

**Author:** ![Ilian\_Dinev](https://community.khronos.org/user_avatar/community.khronos.org/ilian_dinev/32/109_2.png) [@Ilian\_Dinev](https://community.khronos.org/u/Ilian_Dinev)\
**Post date:** [August 19, 2011, 3:21pm UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/2 "2011-08-19T15:21:44Z")

</div>

try:

```auto

You have:
vec3 IconPos; // where the icon is
mat4 mvp; // model-view-projection matrix
float invWidth = 1.0/640; 
float invHeight= 1.0/480;
int iconSize=32; // if you want to see it always 32x32px big
//-----------------
vec4 clip = mvp * vec4(IconPos,1.0);
float dx = iconSize * invWidth * 0.5 * clip.w;
float dy = iconSize * invHeight * 0.5 * clip.w;

vec4 vout[4];
vout[0] = vec4(clip.x - dx, clip.y + dy, clip.z,clip.w);
vout[1] = vec4(clip.x - dx, clip.y - dy, clip.z,clip.w);
vout[2] = vec4(clip.x + dx, clip.y - dy, clip.z,clip.w);
vout[3] = vec4(clip.x + dx, clip.y + dy, clip.z,clip.w);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBegin(GL_QUADS);
	glTexCoord2f(0,0);	glVertex4fv(&vout[0].x);
	glTexCoord2f(0,1);	glVertex4fv(&vout[1].x);
	glTexCoord2f(1,1);	glVertex4fv(&vout[2].x);
	glTexCoord2f(1,0);	glVertex4fv(&vout[3].x);
glEnd();
	

```

---

<div class="post-metadata">

**Author:** ![BionicBytes](https://community.khronos.org/user_avatar/community.khronos.org/bionicbytes/32/137_2.png) [@BionicBytes](https://community.khronos.org/u/BionicBytes)\
**Post date:** [August 22, 2011, 4:57pm UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/3 "2011-08-22T16:57:54Z")

</div>

@llian,  
I tried the code you posted and it works very, very well. :eek:

How did you ever figure out that:

```auto

vout[0] = vec4(clip.x - dx, clip.y + dy, clip.z,clip.w);
vout[1] = vec4(clip.x - dx, clip.y - dy, clip.z,clip.w);
vout[2] = vec4(clip.x + dx, clip.y - dy, clip.z,clip.w);
vout[3] = vec4(clip.x + dx, clip.y + dy, clip.z,clip.w);

```

would ever work?

---

<div class="post-metadata">

**Author:** ![Alfonse\_Reinheart](https://community.khronos.org/user_avatar/community.khronos.org/alfonse_reinheart/32/4357_2.png) [@Alfonse\_Reinheart](https://community.khronos.org/u/Alfonse_Reinheart)\
**Post date:** [August 22, 2011, 7:01pm UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/4 "2011-08-22T19:01:24Z")

</div>

I’m guessing he employed math 😉 All he’s doing is computing positions that will effectively reverse the perspective projection, thus keeping it at the correct size.

---

<div class="post-metadata">

**Author:** ![Ilian\_Dinev](https://community.khronos.org/user_avatar/community.khronos.org/ilian_dinev/32/109_2.png) [@Ilian\_Dinev](https://community.khronos.org/u/Ilian_Dinev)\
**Post date:** [August 23, 2011, 12:24am UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/5 "2011-08-23T00:24:14Z")

</div>

I figured the 4 vertices should have the same z and w, and backtraced how to “unproject” xy.

---

<div class="post-metadata">

**Author:** ![BionicBytes](https://community.khronos.org/user_avatar/community.khronos.org/bionicbytes/32/137_2.png) [@BionicBytes](https://community.khronos.org/u/BionicBytes)\
**Post date:** [August 23, 2011, 1:48am UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/6 "2011-08-23T01:48:51Z")

</div>

I can see you were unprojecting the icon position into clip space, but the next step you took was a stroke of genius in my opinion as it’s not immediately obvious to me that the key to this technique is dx \* clip.w to ‘perspectively’ correct the icon size.

float dx = iconSize \* invWidth \* 0.5 \* clip.w;  
float dy = iconSize \* invHeight \* 0.5 \* clip.w;

I suppose if you figure that the next step in the FF pipeline is to perform a perspective divide with a computed clip-space w (just as you did), then it all makes sense as you have just reversed the projection.

Anyway, well done!

---

<div class="post-metadata">

**Author:** ![anopgl](https://community.khronos.org/letter_avatar_proxy/v4/letter/a/839c29/32.png) [@anopgl](https://community.khronos.org/u/anopgl)\
**Post date:** [August 23, 2011, 1:58am UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/7 "2011-08-23T01:58:14Z")

</div>

Yes, MANY THANKS to Ilian. Sorry for late update. It solved my problem and seems like I’ll use this approach a lot.

---

<div class="post-metadata">

**Author:** ![anopgl](https://community.khronos.org/letter_avatar_proxy/v4/letter/a/839c29/32.png) [@anopgl](https://community.khronos.org/u/anopgl)\
**Post date:** [August 29, 2011, 2:49am UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/8 "2011-08-29T02:49:19Z")

</div>

Hi  
Sorry for bringing it up again.  
But now I copied the code to another project where my metric space is relatively large[-2500,2500] and when I do rendering it doesnt work anymore. I can’t see the icons anymore.  
It looks like clip vector values are the problem.

Please take a look at my code:

```auto

GLfloat matProj[16];
GLfloat matModelProj[16];
float InvWidth = 1.0/winWidth;
float InvHeight= 1.0/winHeight;
float vClip[4],vPos[4] = {icon.x,icon.y,icon.fz,1.0f};

glBindTexture(GL_TEXTURE_2D, icon.TexID);
glEnable(GL_TEXTURE_2D);				 
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);	 
glEnable(GL_BLEND);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glPushMatrix();

 glGetFloatv(GL_PROJECTION_MATRIX, matProj);
 glMultMatrixf(matProj);
 glGetFloatv(GL_MODELVIEW_MATRIX,matModelProj);

 //multiply modelview-proj matrix with position
 Matrix4MultiplyByVector(matModelProj,vPos,vClip);  
 float dx = (float)icon.SizeX * (float)winWidth *0.5f * vClip[3];
 float dy = (float)icon.SizeY * (float)winHeight *0.5f * vClip[3];

 float vScr1[4] = {vClip[0] - dx, vClip[1] + dy, vClip[2],vClip[3]};
 float vScr2[4] = {vClip[0] - dx, vClip[1] - dy, vClip[2],vClip[3]};
 float vScr3[4] = {vClip[0] + dx, vClip[1] - dy, vClip[2],vClip[3]};
 float vScr4[4] = {vClip[0] + dx, vClip[1] + dy, vClip[2],vClip[3]};

 glPopMatrix();
 glBegin(GL_QUADS);
        glTexCoord2f(0,0);	glVertex4fv(vScr1);
	glTexCoord2f(0,1);	glVertex4fv(vScr2);
	glTexCoord2f(1,1);	glVertex4fv(vScr3);
	glTexCoord2f(1,0);	glVertex4fv(vScr4);
 glEnd();

 glDisable(GL_BLEND);
 glDisable(GL_TEXTURE_2D);

 

```

Thanks

---

<div class="post-metadata">

**Author:** ![Dark\_Photon](https://community.khronos.org/user_avatar/community.khronos.org/dark_photon/32/4349_2.png) [@Dark\_Photon](https://community.khronos.org/u/Dark_Photon)\
**Post date:** [October 24, 2021, 12:25am UTC](https://community.khronos.org/t/icon-drawing-in-3d/65420/9 "2021-10-24T00:25:34Z")

</div>


