How do you determine when an object is drawn on-screen in OpenGL? - opengl

I'm extremely new to OpenGL. I'm writing a program that displays flying 3D text on screen. I need to know when certain text string appears (drawn) onto the screen and are visible to the user. The program needs to identify which text strings are displayed. (Note: although my problem deals with text, it could be generalized to any OpenGL object).
At first, I started to think that I could use OpenGL's picking mechanism, but so far I've only seen examples where the selection area is focused on some sort of user interaction. I want to know what objects are displayed on the entire window area. This leads me to think I'm on the wrong track... Am I missing something?
Any suggestions are welcome.

You can use the query objects (specifically those object created using GL_ARB_occlusion_query extension Specification). Those object are used to query how many fragments are rendered using a sequence of OpenGL operations (begin/end, etc...).
Another scheme (software only), is to determine a bounding box for your rendered text, then compute mathematically whether the bounding box is inside the view frustrum (derived from the current perspective used for rendering.
A note: using OpenGL picking doesn't necessary imply the use of gluPickMatrix. You can render you scene "as is", and the query the rendered names (altought picking is deprecated from OpenGL 3).
Query objects are easy to use, and they are lightweight. Picking is another good solution for most hardware, but more schematic than query objects.

hmm, is it actually in 3D? or is it just 2D text on the screen in 2D space? in that case I would just keep track of it manually. how exactly are you drawing your text?
generally the way you do this is with a "frustum check" where you basically just make a volume for the camera and test whether you're 3d objects are inside it or not.

You can try OpenGL's feedback mechanism. In this mode, OpenGL generates fragments and passes them to a feedback buffer. If something is clipped, no fragments will be generated. When the text becomes visible, you will find the corresponding fragment in the fragment buffer.
This link should get you started.
Here is another link, the Question 10.010 seems particularly relevant to what you want.

Run your object coordinates through your projection and modelview matrices to get screen-space coordinates. Compare the X/Y output against your screen extents to figure out if the text is on-screen.

Related

OpenGL & Qt : display a label on the mouseover

I'm working with OpenGL and Qt. I render a scene in an OpenGLWidget. When hovering over objects in the scene, I would like to display a box near the selected object with some text. I have already implemented the selection of the object.
I thought of two possible approaches.
Place a widget (such as a QLabel) above the OpenGLWidget in
which the scene is rendered.
Render the text in a quad directly in OpenGL.
Which of the two approaches you recommend and you could please give me some suggestions on implementation. Alternatively, you could recommend another approach. Thanks!
Hi #Artic I am not a Qt expert so I can't give you information on widgets, but I can give you some pointers for creating a label with OpenGL. Giving a full implementation is tricky here because it depends a lot on how you want to display the text. But I'll try to outline some of your options.
To render text in OpenGL most people go with a technique known as bitmap fonts, see more here:
https://learnopengl.com/In-Practice/Text-Rendering
The concept of bitmap fonts is fairly straight forward, all characters are pre-rasterized to a texture and then you can sample from each part of the texture depending on the character you need. You build your label out of quads, textured with each part of the bitmap you sample from for each character.
Signed distance fields essentially use the same technique but the pre-rasterized texture of characters are rendered using signed distance fields which deal with some of the issues that standard bitmaps fonts have.
In basic terms, SDF works by generating a special texture, or image, of the font that stores the distance from the edge of each character to its centre, using the colour channels of the image to record the data.
If you use signed distance fields it won't be enough to just sample from your bitmap, fonts rendered this way require extra work (typically done using a shader program) to produce the correct rendering.
Once you have a way of generating a label you can decide if you want to display it in screen space or in world space.
If you want to display it in world space (where the label is hovering over the model or item) you will need to do more work if you want that label to always face the camera and this technique is called billboarding.
You could also render your text "on the fly" if you just want to render some text to the screen in screen space. You can use a library like SDL_ttf.
See: http://lazyfoo.net/tutorials/SDL/16_true_type_fonts/index.php
In this example you use SDL_ttf to render a string of text to a surface with dimensions of your choosing, you can then create an OpenGL texture from that surface and render it to the screen.
Sorry if this information is a bit broad, I would need a more specific question to give you further implementation details.
For an implementation, I would evaluate the pros and cons based on what you need. If you haven't implemented a system for rendering text before it's probably best to stick with something simple; there are more techniques for text rendering than I have listed here such as turning text in to polygons and other libraries which attempt to deal with some of the issues with traditional font rendering techniques but you probably don't need anything complicated.
For a recommendation on which to use I would go with the technique that you feel most comfortable with, typically doing things from scratch in OpenGL will take more time but it can provide you with a nicer set of functionality to use in the future. However if Qt already has something nice for rendering a label (such as a widget that you mentioned) it is probably worth taking the time to learn how to use it as it may yield faster results and you don't want to reinvent the wheel if you don't need to. On that note though doing things from scratch with OpenGL can be very rewarding and greatly improve your understanding since you have to get familiar with how things are done when you don't have a layer of abstraction to depend on. Ultimately it depends on you. Good luck!
You could use tool tips in Qt. The string will appear when the OpenGlWidget is hovered over. You can change the text of the tool tip based on the mouse location in the scene, using the tool tip method showText():
QToolTip::showText(QPoint &position, QString &text, QWidget *w);
There are more options for the showText() method and can be found in Qt's tool tip documentation. Also, here are more examples on how to use Qt tool tips.

Fake X11 rendering as output to vector format

I'm provided with an application which renders highly complex geometries either via X11 or OpenGL (a computed voronoi diagram and other things).
I'm searching for a way to export renderings to a vector file. Because of the complexity of how the geometries are rendered, this does not seem to be as easy as thought.
I thought I could use Xfvb to fake parts of the rendering. But how can I later vectorize (or pseudo-vectorize) the screen buffer?
I do have a chance to change the screen to output only one kind at a time.
Or is there a way to substitute for example XFillArc() with something that, given a screen width and scale, provides for example a linestring?

OpenGL : GL_QUADS hides part of glutBitmapCharacter

I am trying to visualize a CAD geometry where GL_QUADS is used for the geometry and glutBitmapCharacter to annotate with a text.
The GL_QUADS hides the text partially (e.g 33,32,... here) for some view orientations (picture 1).
If I use glDisable(GL_DEPTH_TEST) to get the text displayed properly, I get the text that is supposed to annotate the back surface is also displayed (picture 2).
My objective is to annotate the visible front surfaces without being obscured but having the annotation on the back surfaces not shown.
(I am able to solve this by slightly offsetting the annotation normal to the quad, but this will cause me some other issues in my program, so I don't prefer this solution)
Could somebody please suggest me a solution ?
Well, as I expect you already know, it looks like the text is getting cut off because of the way it's positioned/oriented - it is drawing from a point and from right-to-left on the screen.
If you don't want to offset it (as you already mentioned, but I still suggest as it's the simple solution) then one way might be to rotate the text the same way the object's being rotated. This would (I'd expect) simply be a matter of changing where you draw the text to the same place you draw each quad (thus using the same Matrix). Of course then the text won't be as legible. This solution also requires the use of a different Object for rendering the text, such as FreeType Fonts.
EDIT 2: another solution would be texture-mapped text
Could somebody please suggest me a solution ?
You need to implement collision detection engine.
If point in 3d space at which label must be displayed is not obscured, render text with depth test disabled. This will fix your problem completely.
As far as I can tell, there's no other way to solve the problem if you want to keep letters oriented towards viewer - no matter what you do, there will always be a a good chance of them being partially obscured by something else.
Since you need a very specific kind of collision detection (detect visibility of a point), you could try to solve this problem using select buffer. On other hand, detecting ray/triangle (see gluUnProject/gluProject) collision isn't too hard to implement, although on complex scenes things will quickly get more complicated and you'll need to implement scene graph and use algorithms similar to octrees.

OpenGl box fullscreen

I'd like to draw the inside of a box fullscreen (i.e. it should completely fill the viewport) using OpenGL. The box should have perspective.
I presume I'll have to change the dimensions of the box depending on the viewport size but I'm not sure how to go about this.
I'm trying to achieve something like the room in this image
My question is: how can I achieve this?
Use the same coords for the fronts of the four "wall" quads as you passed to glFrustum. The usual viewport code will work just fine without modification (it's basically just telling OpenGL where to display its output, which you (nearly) always want as the full size of the window you're given). Just be aware that since you're told it to fill the view, you'll get linear distortion when/if the shape of the display area changes (i.e., square window->square box, oblong window->oblong box).
it's a bit late after almost one year but seen that there is not a complete answear or at least i couldn't solve the problem with what is here i'll point you to this question wich can help for sure
How to ensure that a plane perfectly fills the viewport in OpenGL ES

OpenGL game development - scenes that span far into view

I am working on a 2d game. Imagine a XY plane and you are a character. As your character walks, the rest of the scene comes into view.
Imagine that the XY plane is quite large and there are other characters outside of your current view.
Here is my question, with opengl, if those objects aren't rendered outside of the current view, do they eat up processing time?
Also, what are some approaches to avoid having parts of the scene rendered that aren't in view. If I have a cube that is 1000 units away from my current position, I don't want that object rendered. How could I have opengl not render that.
I guess the easiest approaches is to calculate the position and then not draw that cube/object if it is too far away.
OpenGL faq on "Clipping, Culling and Visibility Testing" says this:
OpenGL provides no direct support for determining whether a given primitive will be visible in a scene for a given viewpoint. At worst, an application will need to perform these tests manually. The previous question contains information on how to do this.
Go ahead and read the rest of that link, it's all relevant.
If you've set up your scene graph correctly objects outside your field of view should be culled early on in the display pipeline. It will require a box check in your code to verify that the object is invisible, so there will be some processing overhead (but not much).
If you organise your objects into a sensible hierarchy then you could cull large sections of the scene with only one box check.
Typically your application must perform these optimisations - OpenGL is literally just the rendering part, and doesn't perform object management or anything like that. If you pass in data for something invisible it still has to transform the relevant coordinates into view space before it can determine that it's entirely off-screen or beyond one of your clip planes.
There are several ways of culling invisible objects from the pipeline. Checking if an object is behind the camera is probably the easiest and cheapest check to perform since you can reject half your data set on average with a simple calculation per object. It's not much harder to perform the same sort of test against the actual view frustrum to reject everything that isn't at all visible.
Obviously in a complex game you won't want to have to do this for every tiny object, so it's typical to group them, either hierarchically (eg. you wouldn't render a gun if you've already determined that you're not rendering the character that holds it), spatially (eg. dividing the world up into a grid/quadtree/octree and rejecting any object that you know is within a zone that you have already determined is currently invisible), or more commonly a combination of both.
"the only winning move is not to play"
Every glVertex etc is going to be a performance hit regardless of whether it ultimately gets rendered on your screen. The only way to get around that is to not draw (i.e. cull) objects which wont ever be rendered anyways.
most common method is to have a viewing frustum tied to your camera. Couple that with an octtree or quadtree depending on whether your game is 3d/2d so you dont need to check every single game object against the frustum.
The underlying driver may do some culling behind the scenes, but you can't depend on that since it's not part of the OpenGL standard. Maybe your computer's driver does it, but maybe someone else's (who might run your game) doesn't. It's best for you do to your own culling.