将Coin3D SoOffscreenRenderer转换为QImage并使用OpenGL进行渲染 [英] Convert Coin3D SoOffscreenRenderer to QImage and render with OpenGL

查看:356
本文介绍了将Coin3D SoOffscreenRenderer转换为QImage并使用OpenGL进行渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过使用 SoOffscreenRenderer QGLWidget 中显示带有QT的Coin3D / Open Inventor场景>我需要帮助将其转换为 QImage

I'm trying to display a Coin3D/Open Inventor scene with QT in a QGLWidget, by using the SoOffscreenRenderer and I need help converting it to a QImage

到目前为止,我试图将场景渲染为 SoOffscreenRenderer 并获得如下的缓冲区:

What I tried so far, is render the scene into SoOffscreenRenderer and get the buffer like this:

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 从缓冲区数据:

and then create a QImage from the buffer data:

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文件。

e: To make sure that my buffer actually contains a scene, I write the buffer content to two files. You can view .rgb and .ps files for example with IrfanView plus its plugins.

e2:刚才知道,我必须使用 img .rgbSwapped()。现在它显示黑色和白色的场景,没有闪电。我会进一步调查。

e2: Just figured out, that I have to use img.rgbSwapped(). Now it's showing the scene black&white and without lightning. I will investigate further.

e3:使用这样的代码,你需要调整OpenGL调用以这种方式呈现彩色

e3: With the code like this, you need to adapt the OpenGL call in this way to render in color

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(), 
    tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());

第一种格式是GL_RGB,第二个GL_RGBA。

First format is GL_RGB, second GL_RGBA. The cube is still completely black though.

e4:这是我的场景中的一个错误,你必须添加一个光,然后再添加其余的,尤其是在添加

e4: It was an error in my scene, you have to add a light before you add the rest and especially before you add the camera.


我想出了如何使用OpenGL绘制QImage, a href =http://stackoverflow.com/questions/20245865/render-qimage-with-opengl>此主题。所以似乎有一个缓冲区或其转换的问题。

I figured out how to draw a QImage with OpenGL, see this thread. So there seems to be a problem with the buffer or the conversion of it.

推荐答案

这里是生成的代码, 。

Here's the resulting code which renders the scene correctly.

首先创建一个有效的场景

First create a valid scene

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);
}

然后将场景渲染到屏幕缓冲区并将其转换为 QImage

Then render the scene into the Offscreen Buffer and convert it to a 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;
}

这篇关于将Coin3D SoOffscreenRenderer转换为QImage并使用OpenGL进行渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆