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.
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:
- Set perspective projection matrix for rendering
- Render your scene
- Calculate normalized position of UI elements by multiplying your UI element positions with the perspective projection matrix (this should give you NDCs).
- Set an identity matrix as your projection matrix
- 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.
gl_Position = mvp * vec4(inVertexPos.xyz, 1);
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;
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