Thursday, January 12, 2012
Rendering images in a background thread in Qt
QImage instead of QPainter should be used. According to the QImage class reference, QPainter can be used to draw directly onto images. When using QPainter on a QImage, the painting can be performed in another thread than the current GUI thread.
Render-to-texture in OpenSceneGraph
// Create a render-to-texture camera with an absolute
// reference frame and pre-render
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
// Set the camera's projection matrix to reflect the
// world of the geometries that will appear in the texture
camera->setProjectionMatrixAsOrtho2D(minx, maxx, miny, maxy);
//Set the camera's viewport to the same size of the texture
camera->setViewport(0, 0, textureWidth, textureHeight);
// Set the camera's clear color and masks
camera->setClearColor(clearColor);
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Create the texture image
osg::ref_ptr<osg::Image> image = new osg::Image();
image->allocateImage(textureWidth,
textureHeight,
1, // 2D texture is 1 pixel deep
GL_RGBA,
GL_UNSIGNED_BYTE);
image->setInternalTextureFormat(GL_RGBA8);
// Create the texture object and set the image
osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D();
texture2D->setImage(image);
// Attach the texture to the camera. You can also attach
// the image to the camera instead. Attaching the image may
// work better in the Windows Remote Desktop
camera->attach(osg::Camera::COLOR_BUFFER, texture2D.get());
// Add the geometries that will appear in the texture to the camera
camera->addChild(geometriesInTexture);
// Create a geode to display the texture
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// Create a geometry for the geode
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
geode->addDrawable(geometry);
// The coordinates can be different if we want to display the
// texture at a location different from the coordinates of the
// geometries inside the texture
osg::ref_ptr<osg::Vec3Array> vertexArray = new osg::Vec3Array();
vertexArray->push_back(osg::Vec3(minx, miny, minz));
vertexArray->push_back(osg::Vec3(maxx, miny, minz));
vertexArray->push_back(osg::Vec3(maxx, maxy, minz));
vertexArray->push_back(osg::Vec3(minx, maxy, minz));
geometry->setVertexArray(vertexArray);
// The geometry color for the texture mapping should be white
// (1.f, 1.f, 1.f, 1.f) so that color blending won't affect
// the texture real color
osg::ref_ptr<osg::Vec4Array> colorArray = new osg::Vec4Array();
colorArray->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f));
geometry->setColorArray(colorArray);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
// We are using the entire texture by using the four corners
// of the texture coordinates
osg::ref_ptr<osg::Vec2Array> texCoordArray = new osg::Vec2Array();
texCoordArray->push_back(osg::Vec2(0.f, 0.f));
texCoordArray->push_back(osg::Vec2(1.f, 0.f));
texCoordArray->push_back(osg::Vec2(1.f, 1.f));
texCoordArray->push_back(osg::Vec2(0.f, 1.f));
geometry->setTexCoordArray(0, texCoordArray);
// We always create a square texture.
geometry->addPrimitiveSet(
new osg::DrawArrays(GL_TRIANGLE_FAN, 0, 4));
// Add the texture to the geode
geode->getOrCreateStateSet()->setTextureAttributeAndModes(
0, texture2D, osg::StateAttribute::ON);
// Make sure that we are using color blending
// and the transparent bin, since the features may not
// cover the entire texture and the empty
// space should be transparent.
geode->getOrCreateStateSet()->setRenderingHint(
osg::StateSet::TRANSPARENT_BIN);
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
geode->getOrCreateStateSet()->setAttributeAndModes(blendFunc);
// Add both the rtt camera and the geode to the scene graph
sceneGraph->addChild(camera);
sceneGraph->addChild(geode);
* NOTE: If we only want to render one frame on the texture, we can remove the camera from the scene graph after the frame is rendered. The geode will still display the static texture in the scene graph properly.
// reference frame and pre-render
osg::ref_ptr<osg::Camera> camera = new osg::Camera();
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
// Set the camera's projection matrix to reflect the
// world of the geometries that will appear in the texture
camera->setProjectionMatrixAsOrtho2D(minx, maxx, miny, maxy);
//Set the camera's viewport to the same size of the texture
camera->setViewport(0, 0, textureWidth, textureHeight);
// Set the camera's clear color and masks
camera->setClearColor(clearColor);
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Create the texture image
osg::ref_ptr<osg::Image> image = new osg::Image();
image->allocateImage(textureWidth,
textureHeight,
1, // 2D texture is 1 pixel deep
GL_RGBA,
GL_UNSIGNED_BYTE);
image->setInternalTextureFormat(GL_RGBA8);
// Create the texture object and set the image
osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D();
texture2D->setImage(image);
// Attach the texture to the camera. You can also attach
// the image to the camera instead. Attaching the image may
// work better in the Windows Remote Desktop
camera->attach(osg::Camera::COLOR_BUFFER, texture2D.get());
// Add the geometries that will appear in the texture to the camera
camera->addChild(geometriesInTexture);
// Create a geode to display the texture
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// Create a geometry for the geode
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
geode->addDrawable(geometry);
// The coordinates can be different if we want to display the
// texture at a location different from the coordinates of the
// geometries inside the texture
osg::ref_ptr<osg::Vec3Array> vertexArray = new osg::Vec3Array();
vertexArray->push_back(osg::Vec3(minx, miny, minz));
vertexArray->push_back(osg::Vec3(maxx, miny, minz));
vertexArray->push_back(osg::Vec3(maxx, maxy, minz));
vertexArray->push_back(osg::Vec3(minx, maxy, minz));
geometry->setVertexArray(vertexArray);
// The geometry color for the texture mapping should be white
// (1.f, 1.f, 1.f, 1.f) so that color blending won't affect
// the texture real color
osg::ref_ptr<osg::Vec4Array> colorArray = new osg::Vec4Array();
colorArray->push_back(osg::Vec4(1.f, 1.f, 1.f, 1.f));
geometry->setColorArray(colorArray);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
// We are using the entire texture by using the four corners
// of the texture coordinates
osg::ref_ptr<osg::Vec2Array> texCoordArray = new osg::Vec2Array();
texCoordArray->push_back(osg::Vec2(0.f, 0.f));
texCoordArray->push_back(osg::Vec2(1.f, 0.f));
texCoordArray->push_back(osg::Vec2(1.f, 1.f));
texCoordArray->push_back(osg::Vec2(0.f, 1.f));
geometry->setTexCoordArray(0, texCoordArray);
// We always create a square texture.
geometry->addPrimitiveSet(
new osg::DrawArrays(GL_TRIANGLE_FAN, 0, 4));
// Add the texture to the geode
geode->getOrCreateStateSet()->setTextureAttributeAndModes(
0, texture2D, osg::StateAttribute::ON);
// Make sure that we are using color blending
// and the transparent bin, since the features may not
// cover the entire texture and the empty
// space should be transparent.
geode->getOrCreateStateSet()->setRenderingHint(
osg::StateSet::TRANSPARENT_BIN);
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
geode->getOrCreateStateSet()->setAttributeAndModes(blendFunc);
// Add both the rtt camera and the geode to the scene graph
sceneGraph->addChild(camera);
sceneGraph->addChild(geode);
* NOTE: If we only want to render one frame on the texture, we can remove the camera from the scene graph after the frame is rendered. The geode will still display the static texture in the scene graph properly.
Tuesday, January 3, 2012
OpenGL Version in Windows Remote Desktop
Qt shows that the current version and the only supported version in Windows Remote Desktop is 1.1.
Changing the current OpenGL version in Qt
We can change the current OpenGL version by creating a QGLFormat object and calling QGLFormat::setVersion, then passing the format into the QGLWidget's contructor.
NOTE: OpenGL 3.3 is being shown on my current machine with an ATI Radeon HD 2400 Pro graphics card. However, setting the version to 3.2 will give out a lot of warnings and nothing is being drawn on the screen. Setting the version to any versions between 1.x and 2.x will end up with version 3.3. The only version that I can successfully set to is 3.0 only.
NOTE: OpenGL 3.3 is being shown on my current machine with an ATI Radeon HD 2400 Pro graphics card. However, setting the version to 3.2 will give out a lot of warnings and nothing is being drawn on the screen. Setting the version to any versions between 1.x and 2.x will end up with version 3.3. The only version that I can successfully set to is 3.0 only.
The supported OpenGL versions in Qt
The supported OpenGL versions can be queried from QGLFormat in a QGLWidget. The function QGLFormat::openGLVersionFlags returns all the supported versions of the platform.
The current OpenGL version in Qt
The OpenGL version can queried from QGLFormat in a QGLWidget . The function QGLFormat::majorVersion and QGLFormat::minorVersion returns the current OpenGL version the platform is using.
Subscribe to:
Posts (Atom)