将Coin3D SoOffscreenRenderer转换为QImage并使用OpenGL进行渲染
我试图通过使用SoOffscreenRenderer
在QGLWidget
中用QT显示Coin3D / Open Inventor场景,我需要帮助将它转换为QImage
我到目前为止所尝试的是将场景渲染成SoOffscreenRenderer
并获取像这样的缓冲区:
unsigned char * getCoinCubeImgBuffer(){
// [...] create the scene, add lightning and camera
SoOffscreenRenderer offscreenRenderer(vpRegion);
offscreenRenderer.setComponents(
SoOffscreenRenderer::Components::RGB_TRANSPARENCY
);
SbBool ok = offscreenRenderer.render(root);
// to be sure that something is actually rendered
// save the buffer content to a file
SbBool ok = offscreenRenderer.render(root);
qDebug() << "SbBool ok?" << ok;
qDebug() << "wasFileWrittenRGB" <<
offscreenRenderer.writeToRGB("C:/test-gl.rgb");
qDebug() << "wasFileWrittenPS" <<
offscreenRenderer.writeToPostScript("C:/test-gl.ps");
unsigned char * imgbuffer = offscreenRenderer.getBuffer();
return imgbuffer;
}
然后从缓冲区数据创建一个QImage
:
QImage convertImgBuffer(){
unsigned char *const imgBuffer = getCoinCubeImgBuffer();
QImage img(imgBuffer, windowWidth, windowHeight, QImage::Format_ARGB32);
// Important!
img = img.rgbSwapped();
QImage imgGL = convertToGLFormat(img);
return imgGL;
}
这是否是正确的方法?
正如在关于绘制QImage的这个问题中所描述的,如果源是图片,我可以绘制它。
e:为了确保我的缓冲区实际上包含一个场景,我将缓冲区内容写入两个文件。 例如,您可以使用IrfanView及其插件查看.rgb和.ps文件。
e2:刚发现,我必须使用img.rgbSwapped()
。 现在,它显示了黑白的场景,没有闪电。 我会进一步调查。
e3:使用这样的代码,您需要以这种方式调整OpenGL调用以进行彩色渲染
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(),
tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
第一种格式是GL_RGB,第二种是GL_RGBA。 立方体仍然是完全黑色的。
e4:这是我场景中的错误,您必须在添加其余部分之前添加灯光,尤其是在添加相机之前。
因此,现在我可以使用像`bindTexture()`这样的`QGLWidget`函数,或者使用直接的OpenGL调用,但我不确定具体如何。 如果有人能把我推向正确的方向,那将是很棒的。 我不能像这样使用OpenGL吗? glEnable(GL_TEXTURE_2D); glGenTextures(1,&offscreenBufferTexture); glBindTexture(GL_TEXTURE_2D,offscreenBufferTexture); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,imgGL.width(),imgGL.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,imgGL.bits()); 或者`glDrawPixels()`? glDrawPixels(imgGL.width(),imgGL.height(),GL_RGBA,GL_UNSIGNED_BYTE,imgGL.bits());
我想出了如何使用OpenGL绘制QImage,请参阅此主题。 所以缓冲区或其转换似乎存在问题。
以下是正确呈现场景的结果代码。
首先创建一个有效的场景
void loadCoinScene(){
// Init Coin
SoDB::init();
// The root node
root = new SoSeparator;
root->ref();
// Add the light _before_ you add the camera
SoDirectionalLight * light = new SoDirectionalLight;
root->addChild(light);
vpRegion.setViewportPixels(0, 0, coinSceneWidth, coinSceneHeight);
SoPerspectiveCamera *perscam = new SoPerspectiveCamera();
root->addChild(perscam);
SbRotation cameraRotation = SbRotation::identity();
cameraRotation *= SbRotation(SbVec3f(0, 1, 0), 0.4f);
perscam->orientation = cameraRotation;
SoCube * cube = new SoCube;
root->addChild(cube);
// make sure that the cube is visible
perscam->viewAll(root, vpRegion);
}
然后将场景渲染到Offscreen Buffer并将其转换为QImage
:
QImage getCoinCubeImgBuffer(){
SoOffscreenRenderer offscreenRenderer(vpRegion);
offscreenRenderer.setComponents(
SoOffscreenRenderer::Components::RGB_TRANSPARENCY
);
offscreenRenderer.render(root);
QImage img(offscreenRenderer.getBuffer(), coinSceneWidth,
coinSceneHeight, QImage::Format_ARGB32);
// Important!
return img.rgbSwapped();
}
如果您现在要渲染QImage
与OpenGL的,用我的解决方案从我的使用OpenGL渲染的问题QImage上,改变loadTexture2()
方法如下:
QImage loadTexture2(GLuint &textureID){
glEnable(GL_TEXTURE_2D); // Enable texturing
glGenTextures(1, &textureID); // Obtain an id for the texture
glBindTexture(GL_TEXTURE_2D, textureID); // Set as the current texture
QImage im = getCoinCubeImgBuffer();
// Convert to OpenGLs unnamed format
// The resulting GL format is GL_RGBA
QImage tex = QGLWidget::convertToGLFormat(im);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(), tex.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glDisable(GL_TEXTURE_2D);
return tex;
}
我不认为有必要通过QImage提供纹理。 以下是一个工作示例:
#include <QApplication>
#include <QGLWidget>
#include <Inventor/SoInput.h>
#include <Inventor/SoOffscreenRenderer.h>
#include <Inventor/nodes/SoSeparator.h>
static GLuint textureID(0);
class GLWidget : public QGLWidget
{
public:
explicit GLWidget() : QGLWidget() {}
~GLWidget() {}
protected:
void initializeGL() {
glShadeModel(GL_FLAT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
static GLfloat lightAmbient[4] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
}
void paintGL() {
if (!textureID)
return;
glClearColor(0.4f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
glTexCoord2f(1,0); glVertex3f( 1, -1, -1);
glTexCoord2f(1,1); glVertex3f( 1, 1, -1);
glTexCoord2f(0,1); glVertex3f(-1, 1, -1);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void resizeGL(int width, int height) {
int side = qMin(width, height);
glViewport((width - side) / 2, (height - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
GLWidget glWidget;
glWidget.show();
static const char * inlineSceneGraph[] = {
"#Inventor V2.1 asciin",
"n",
"Separator {n",
" PerspectiveCamera { position 0 0 5 }n",
" DirectionalLight {}n",
" Rotation { rotation 1 0 0 0.3 }n",
" Cone { }n",
" BaseColor { rgb 1 0 0 }n",
" Scale { scaleFactor .7 .7 .7 }n",
" Cube { }n",
"n",
" DrawStyle { style LINES }n",
" ShapeHints { vertexOrdering COUNTERCLOCKWISE }n",
" Coordinate3 {n",
" point [n",
" -2 -2 1.1, -2 -1 1.1, -2 1 1.1, -2 2 1.1,n",
" -1 -2 1.1, -1 -1 1.1, -1 1 1.1, -1 2 1.1n",
" 1 -2 1.1, 1 -1 1.1, 1 1 1.1, 1 2 1.1n",
" 2 -2 1.1, 2 -1 1.1, 2 1 1.1, 2 2 1.1n",
" ]n",
" }n",
"n",
" Complexity { value 0.7 }n",
" NurbsSurface {n",
" numUControlPoints 4n",
" numVControlPoints 4n",
" uKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]n",
" vKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]n",
" }n",
"}n",
NULL
};
SoInput in;
in.setStringArray(inlineSceneGraph);
glWidget.resize(600, 600);
SoOffscreenRenderer renderer(SbViewportRegion(glWidget.width(),
glWidget.height()));
renderer.setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY);
renderer.setBackgroundColor(SbColor(.0f, .0f, .8f));
SoSeparator *rootScene = SoDB::readAll(&in);
rootScene->ref();
renderer.render(rootScene);
rootScene->unref();
glEnable(GL_TEXTURE_2D); // Enable texturing
glGenTextures(1, &textureID); // Obtain an id for the texture
glBindTexture(GL_TEXTURE_2D, textureID); // Set as the current texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
renderer.getViewportRegion().getViewportSizePixels()[0],
renderer.getViewportRegion().getViewportSizePixels()[1],
0, GL_BGRA, GL_UNSIGNED_BYTE, renderer.getBuffer());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glDisable(GL_TEXTURE_2D);
return app.exec();
}
用SoWin,Coin3D渲染本地场景的一个简单例子(从这里下载SoWin)
SoSeparator * CreateScene(SoSeparator* root)
{
root->ref();
root->setName("root_node");
SoPerspectiveCamera * camera = new SoPerspectiveCamera;
camera->setName("simple_camera");
SbRotation cameraRotation = SbRotation::identity();
cameraRotation *= SbRotation(SbVec3f(1, 0, 0), -0.4f);
cameraRotation *= SbRotation(SbVec3f(0, 1, 0), 0.4f);
camera->orientation = cameraRotation;
SoCone* cone1= new SoCone();
cone1->setName("Cone1");
SoBaseColor * color = new SoBaseColor;
color->setName("myColor");
root->addChild(camera);
root->addChild(cone1);
root->addChild(color);
return root;
}
渲染上面创建的场景
void RenderLocal()
{
HWND window = SoWin::init("IvExample");
if (window==NULL) exit(1);
SoWinExaminerViewer * viewer = new SoWinExaminerViewer(window);
SoSeparator * root = new SoSeparator;
auto* data = CreateScene(root);
data->getNumChildren();
viewer->setSceneGraph(root);
viewer->show();
SoWin::show(window);
SoWin::mainLoop();
delete viewer;
root->unref();
}
从iv文件渲染场景
int RenderFile()
{
HWND window = SoWin::init("Iv");
if (window==NULL) exit(1);
SoWinExaminerViewer * viewer = new SoWinExaminerViewer(window);
SoInput sceneInput;
if ( !sceneInput.openFile( "example.iv" ) )
return -1;
if ( !sceneInput.openFile(cPath) )
return -1;
SoSeparator *root =SoDB::readAll( &sceneInput );
root->ref();
viewer->setSceneGraph(root);
viewer->show();
SoWin::show(window);
SoWin::mainLoop();
delete viewer;
}
链接地址: http://www.djcxy.com/p/38543.html
上一篇: Convert Coin3D SoOffscreenRenderer to QImage and render with OpenGL