My program works perfectly fine in a normal 3D with one buffer, it is coded with SFML window management.
I would like to add quad buffered stereo, therefore i changed my drawing code to the following :
glDrawBuffer(GL_BACK_LEFT);
camera->OnMouseMotion(sf::Vector2i(-1,0));
for (auto i = objects->cbegin(); i != objects->cend(); ++i)
(*i)->draw(camera);
glFlush();
glDrawBuffer(GL_BACK_RIGHT);
camera->OnMouseMotion(sf::Vector2i(2,0));
for (auto i = objects->cbegin(); i != objects->cend(); ++i)
(*i)->draw(camera);
glFlush();
camera->OnMouseMotion(sf::Vector2i(-1,0));
Notice that my camera changed are not perfectly right and i know i will have to change these, right now i am focusing on displaying an image just using quad buffered stereo. I noticed in all examples of programs using this stereo that they were initialising the window with something like this :
type = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO;
glutInitDisplayMode(type);
Using SFML, such function isn't available, my questions are :
Can i use a low-level openGL function to achieve the same result ? Can i use another window managing library with SFML ? Should i forget SFML for my program and completly change it to another one ?
SFML doesn't have an initialisation function, it creates openGL context automatically, two things you can do :
Modify SFML sources you are using, and try to add somewhere in the window creation function your parameter
change your display library to create the openGL context, however you may or not keep SFML 2D drawing functions, i am not sure these are gonna work if you create your context with glut for example.
EDIT : after a small check, you cannot create a context with another library and still use SFML for drawing simple 2D forms, i am afraid you are forced to let SFML go.
Related
I'd like to show my Qt Quick content on a virtual screen inside my OpenSceneGraph scene.
The approach I'm using right now is highly inefficient:
Render Qt Quick to the offscreen surface using FBO (FrameBufferObject)
Download pixels with QOpenGLFramebufferObject::toImage()
Upload pixels to the OSG
So it's GPU-CPU-GPU transfer. Source code
A proper solution should somehow utilize existing FBO and be able to transfer data solely inside the GPU.
There are two options exist:
Create FBO on the Qt side and use its texture on the OSG side
Create FBO on the OSG side and feed it to the Qt Quick renderer
The Qt part is OK. And I'm completely lost with the OSG. Could anyone provide me with some pointers?
Finally made it.
General idea:
Render QtQuick to texture using FBO - there are some examples over the internet available.
Use this texture inside OpenSceneGraph
The whole thing includes several tricks.
Context Sharing
To perform certain graphics operations, we must initialize OpenGL global state, also known as context.
When a texture is created, context stores it's id. Ids are not globally unique, so when another texture is created within another context, it may get the same id, but with different resource behind it.
If you just pass your texture's id to another renderer (operating within different context), expecting it to show your texture, you end up showing another texture or black screen or crash.
The remedy is context sharing, which effectively means sharing ids.
OpenSceneGraph and Qt abstractions are not compatible, so you need to tell OSG not to use its own context abstraction. This is done by calling setUpViewerAsEmbeddedInWindow
Code:
OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags flags)
: QOpenGLWidget(parent, flags)
, m_osgViewer(new osgViewer::Viewer)
{
setFormat(defaultGraphicsSettings());
// ...
m_osgGraphicsContext = m_osgViewer->setUpViewerAsEmbeddedInWindow(x(), y(), width(), height());
}
// osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> m_osgGraphicsContext;
From now on, the existing QOpenGLContext instance will be used as an OpenGL context for OSG rendering.
You will need to create another context for QtQuick rendering and set them shared:
void Widget::initializeGL()
{
QOpenGLContext* qmlGLContext = new QOpenGLContext(this);
// ...
qmlGLContext->setShareContext(context());
qmlGLContext->create();
}
Remember, there can be only one active context at a time.
Your scheme is:
0. create osg::Texture out of QOpenGLFrameBufferObject::texture()
1. make QtQuick context active
2. render QtQuick to texture
3. make primary (OSG) context active
4. render OSG
5. goto 1
Making of a proper osg::Texture
Since OSG and Qt API are incompatible you barely can link QOpenGLFrameBufferObject to osg::Texture2D as it is.
QOpenGLFrameBufferObject has QOpenGLFrameBufferObject::texture() method which returns opengl texture id, but osg::Texture manages all openGL stuff on its own.
Something like osg::Texture2D(uint textureId); could help us but it just doesn't exist.
Let's make one by ourselves.
osg::Texture is backed by osg::TextureObject which stores OpenGL texture id and some other data as well. If we construct osg::TextureObject with a given texture id and pass it to osg::Texture, the latter will use it as its own.
Code:
void Widget::createOsgTextureFromId(osg::Texture2D* texture, int textureId)
{
osg::Texture::TextureObject* textureObject = new osg::Texture::TextureObject(texture, textureId, GL_TEXTURE_2D);
textureObject->setAllocated();
osg::State* state = m_osgGraphicsContext->getState();
texture->setTextureObject(state->getContextID(), textureObject);
}
Complete demo project here
I am trying to make one application with two windows with SDL2. To make draw process faster and capable to run 3d animations I am using OpenGL. But when I open second window, how can I said to OpenGL (gl functions) to draw in second window?
I searched into libsdl wiki but cant find anything.
You are looking for the SDL_GL_MakeCurrent function.
Use this function to set up an OpenGL context for rendering into an OpenGL window.
Example:
SDL_GL_MakeCurrent(window, gl_context);
// OpenGL functions will draw to window
// ...
SDL_GL_MakeCurrent(window2, gl_context);
// OpenGL functions will draw to window2
I just recently changed all rendering in my application/game from SDL to OpenGL. I still use SDL for keyboard input, loading images and creating the window.
But since i only render in OpenGL do you think that i should change the window to a OpenGL initialized window instead of a SDL window. The header i use for OpenGL functions at the moment is "SDL_opengl.h". Does that affect things?
What are the advantages and disadvantages if i do this? Right now it feels like it's the logical "next step" since i got rid of all other SDL rendering code.
Just keep on using SDL for input and window management.
There's no provision for either in the OpenGL spec so there's really no such thing as an "OpenGL initialized window".
As genpfault said, you should keep using SDL for your window initialization. It's more clean and portable than OS-specific methods of initializing a window for OpenGL rendering.
I would also recommend switching from SDL_opengl.h to SDL.h and gl.h; the definitions in SDL_opengl.h aren't necessary for basic window management, and they conflict with the definitions in other OpenGL libraries like GLEW (which you may want to use later for pixel shaders and framebuffers).
I am trying to write a compositor, like Compiz, but with different graphical effects. I am stuck at the first step, though, which is that I can't find how to get X to render windows to a texture instead of to the framebuffer. Any advice on where to start?
X11 composition goes like following.
you redirect windows into a offscreen area. The Composite extension has the functions for this
you use the Damage extension to find out which windows did change their contents
in the compositor you use the GLX_EXT_texture_from_pixmap extension to submit each windows' contents into corresponding OpenGL textures.
you draw the textures into a composition layer window; the Composite extension provides you with a special screen layer, between the regular window layer and the screensaver layer in which to create the window composition is taking place in.
I know you can do the same in lrrlicht, but I want to use SDL code/ functions to draw text, images inside Irrlicht (to handle 2d) and use Irrlicht to do the hardcore 3D thing, how can you apply text or images from sdl to this Irrlicht Engine, can you show me simple code, so that I can understand?
In the SDL you can do such:
// I start by declare the SDL video Name
SDL_Surface *screen;
// set the video mode:
screen = SDL_SetVideoMode(640, 480, 32, SDL_DOUBLEBUF | SDL_FULLSCREEN); if (screen == NULL) { printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; }
// I can now display data, image, text on the screen by using the declared SDL video Name " screen "
SDL_BlitSurface(my_image, &src, screen, &dest);
If you are using / targeting Windows , and are a little familiar with the WinApi, you may be able to use SDL with Irrlicht by running both inside a Win32 Window, using a combination of the SDL Window ID Hack (also see this thread) and running Irrlicht in a Win32 Window. The only problems you may face is that running SDL in a Win32 Window is extremely difficult and unpredictable.
You may be also be able to achieve a similar result using GTK+ (for cross-platform purposes), but I have personally never succeeded in running SDL or Irrlicht in a GTK+ Window.
Also, if you want a light graphics and media library like SDL , may I suggest SFML. It can run in Win32 and X/11 windows without any problems and may easily work with Irrlicht.