draw an object that looks the same size regarles the distance in perspective view

hello everyone,

I am trying to draw many objects that are place on a perspective projection view but that have to look the same size on the pc screen regardless the distance, something like text box on top of the head of a character showing what its talking, I thought on unproject the position to screen coordinate and then using a orthogonal projection and project the screen coordinate position back and draw the object, but I want faster way more efficient because I gonna be using this heavily and the application will run on a mobile device.

thank you.

Why don’t you calculate the perspective projected space position where you want to place your text box using simple vector/matrix math and then render the text box using an ortho projection matrix.

can you explain that a little bit please? because since the projection are going to be diferent I don’t see how will they be place a same position in screen view

Well, what you have to do is the following:

  1. Set perspective projection matrix for rendering
  2. Render your scene
  3. Calculate normalized position of UI elements by multiplying your UI element positions with the perspective projection matrix (this should give you NDCs).
  4. Set an identity matrix as your projection matrix
  5. Render your UI in NDC space (i.e. X and Y are in the range [-1, +1]) using the coordinates calculated in step #3

Of course, there are a lot of other alternatives, you can use e.g. screen space instead of NDC space, etc. But this is probably the most simple.

I don’t see how will they be place a same position in screen view

in your vertex shader, transform the vector (0,0,0) to clipspace. This will get the W the object’s pivot will be divided by, thus you get the “inverseScale” that will be applied to vertices.


before:
gl_Position = mvp * vec4(inVertexPos.xyz, 1);

after:

uniform float reciprScaleOnscreen = 0.01; // change value to match resolution.    = (2 * ObjectSizeOnscreenInPixels / ScreenWidthInPixels)

float w = (mvp * vec3(0,0,0)).w;
w *= reciprScaleOnscreen;

gl_Position = mvp * vec4(inVertexPos.xyz * w , 1);


const float reciprScaleOnscreen = 0.01;

Right? :wink:

Correction of an obvious typo:
float w = (mvp * vec4(0,0,0,1)).w;

Having the “reciprScaleOnscreen” as a uniform is necessary, to handle different screensizes or ratios; or even easily animate the scale for some effect.

Having the “reciprScaleOnscreen” as a uniform is necessary, to handle different screensizes or ratios;

True, but showing code assigning a value to a uniform might cause the thread starter or others reading this to think that writing to a uniform in a shader stage is legal. Just want to avoid confusion and misunderstandings.

the way I used but couldn’t posted before I was using the z value of the vector in world space as scale value but multiplying it instead of dividing it as I notice the projection matrix does so the bigger the z the smallest the object will look, and using the identity of the modelview so no rotation of the camera could affect the object direction so it always face the camera