基于egl / osmesa 的VTK offscreen rendering (离屏渲染)方案

22 篇文章 0 订阅

 

Linux服务器(docker中),通常没有 x server,直接运行离屏渲染程序,报下列错误:

ERROR: In /home/whistler/Desktop/build/VTK-8.2.0/Rendering/OpenGL2/vtkXOpenGLRenderWindow.cxx, line 452
vtkXOpenGLRenderWindow (0x34ae140): bad X server connection.

简单解决办法如下:(虚拟 x server)

https://blog.csdn.net/Ericohe/article/details/108380926

上述方法存在速度问题,追求高性能绘制方案,只有基于(osmesa 或者OpenGL EGL)两个方案。

下列试验osmesa的方案。

Ubuntu系统安装必要的依赖包

apt-get update  
apt-get install -y build-essential libgl1-mesa-dev libglu1-mesa-dev libosmesa6-dev
apt-get install -y x11proto-gl-dev libdrm-dev libxxf86vm-dev libxt-dev xutils-dev flex bison xcb libx11-xcb-dev libxcb-glx0 libxcb-glx0-dev xorg-dev libxcb-dri3-dev libxcb-dri2-0-dev libxcb-xfixes0 libxcb-xfixes0-dev libxcb-present-dev libxcb-sync-dev libxshmfence-dev

apt-get install cmake
apt-get install software-properties-common
add-apt-repository ppa:ubuntu-x-swat/updates
apt-get update
apt-get dist-upgrade
apt install mesa-utils
glxinfo | grep "OpenGL version"
apt install nvidia-utils-390
nvidia-smi

vtk 8.2.0 编译源代码

VTK EGL (GPU加速 )

Dockerfile

FROM nvidia/opengl:1.2-glvnd-devel-ubuntu18.04
 
RUN apt-get update && \
apt-get install -y vim git cmake && \
apt-get install -y python3 python3-pip && \
apt-get install -y libz-dev && \
apt-get clean
RUN pip3 install conan==1.17.0
# RUN apt-get install -y build-essential libgl1-mesa-dev libglu1-mesa-dev libosmesa6-dev libglew-dev 
# RUN apt-get install -y libegl1-mesa-dev # for EGL

VTK OSMESA 为软件驱动

git clone https://gitlab.kitware.com/vtk/vtk.git
cd vtk
git checkout v8.2.0
git status

mkdir /app/vtk_install
mkdir build
cd build

# egl
cmake -DCMAKE_INSTALL_PREFIX=/app/vtk_install -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_Group_Views=ON -DModule_vtkRenderingParallel=ON -DVTK_Group_Rendering=ON -DVTK_Group_StandAlone=ON -DVTK_USE_X=OFF -DVTK_OPENGL_HAS_EGL=ON -DVTK_OPENGL_HAS_OSMESA=OFF -DVTK_RENDERING_BACKEND=OpenGL2 -DVTK_DEFAULT_RENDER_WINDOW_OFFSCREEN=ON ..

# osmesa
# cmake -DCMAKE_INSTALL_PREFIX=/app/vtk_install -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DVTK_Group_Views=ON -DModule_vtkRenderingParallel=ON -DVTK_Group_Rendering=ON -DVTK_Group_StandAlone=ON -DVTK_USE_X=OFF -DVTK_OPENGL_HAS_EGL=OFF -DVTK_OPENGL_HAS_OSMESA=ON  -DVTK_RENDERING_BACKEND=OpenGL2 -DVTK_DEFAULT_RENDER_WINDOW_OFFSCREEN=ON ..

make -j8
make install

 

vtk example

/*=========================================================================

  Program:   Visualization Toolkit
  Module:    SpecularSpheres.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
//
// This examples demonstrates the effect of specular lighting.
//
#include "vtkSmartPointer.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkLight.h"

#include <vtkPNGWriter.h>
#include <vtkWindowToImageFilter.h>
#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);

int main()
{
  // The following lines create a sphere represented by polygons.
  //
  vtkSmartPointer<vtkSphereSource> sphere =
    vtkSmartPointer<vtkSphereSource>::New();
  sphere->SetThetaResolution(100);
  sphere->SetPhiResolution(50);

  // The mapper is responsible for pushing the geometry into the graphics
  // library. It may also do color mapping, if scalars or other attributes
  // are defined.
  //
  vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  sphereMapper->SetInputConnection(sphere->GetOutputPort());

  // The actor is a grouping mechanism: besides the geometry (mapper), it
  // also has a property, transformation matrix, and/or texture map.
  // In this example we create eight different spheres (two rows of four
  // spheres) and set the specular lighting coefficients. A little ambient
  // is turned on so the sphere is not completely black on the back side.
  //
  vtkSmartPointer<vtkActor> sphere1 =
    vtkSmartPointer<vtkActor>::New();
  sphere1->SetMapper(sphereMapper);
  sphere1->GetProperty()->SetColor(1,0,0);
  sphere1->GetProperty()->SetAmbient(0.3);
  sphere1->GetProperty()->SetDiffuse(0.0);
  sphere1->GetProperty()->SetSpecular(1.0);
  sphere1->GetProperty()->SetSpecularPower(5.0);

  vtkSmartPointer<vtkActor> sphere2 =
    vtkSmartPointer<vtkActor>::New();
  sphere2->SetMapper(sphereMapper);
  sphere2->GetProperty()->SetColor(1,0,0);
  sphere2->GetProperty()->SetAmbient(0.3);
  sphere2->GetProperty()->SetDiffuse(0.0);
  sphere2->GetProperty()->SetSpecular(1.0);
  sphere2->GetProperty()->SetSpecularPower(10.0);
  sphere2->AddPosition(1.25,0,0);

  vtkSmartPointer<vtkActor> sphere3 =
    vtkSmartPointer<vtkActor>::New();
  sphere3->SetMapper(sphereMapper);
  sphere3->GetProperty()->SetColor(1,0,0);
  sphere3->GetProperty()->SetAmbient(0.3);
  sphere3->GetProperty()->SetDiffuse(0.0);
  sphere3->GetProperty()->SetSpecular(1.0);
  sphere3->GetProperty()->SetSpecularPower(20.0);
  sphere3->AddPosition(2.5,0,0);

  vtkSmartPointer<vtkActor> sphere4 =
    vtkSmartPointer<vtkActor>::New();
  sphere4->SetMapper(sphereMapper);
  sphere4->GetProperty()->SetColor(1,0,0);
  sphere4->GetProperty()->SetAmbient(0.3);
  sphere4->GetProperty()->SetDiffuse(0.0);
  sphere4->GetProperty()->SetSpecular(1.0);
  sphere4->GetProperty()->SetSpecularPower(40.0);
  sphere4->AddPosition(3.75,0,0);

  vtkSmartPointer<vtkActor> sphere5 =
    vtkSmartPointer<vtkActor>::New();
  sphere5->SetMapper(sphereMapper);
  sphere5->GetProperty()->SetColor(1,0,0);
  sphere5->GetProperty()->SetAmbient(0.3);
  sphere5->GetProperty()->SetDiffuse(0.0);
  sphere5->GetProperty()->SetSpecular(0.5);
  sphere5->GetProperty()->SetSpecularPower(5.0);
  sphere5->AddPosition(0.0,1.25,0);

  vtkSmartPointer<vtkActor> sphere6 =
    vtkSmartPointer<vtkActor>::New();
  sphere6->SetMapper(sphereMapper);
  sphere6->GetProperty()->SetColor(1,0,0);
  sphere6->GetProperty()->SetAmbient(0.3);
  sphere6->GetProperty()->SetDiffuse(0.0);
  sphere6->GetProperty()->SetSpecular(0.5);
  sphere6->GetProperty()->SetSpecularPower(10.0);
  sphere6->AddPosition(1.25,1.25,0);

  vtkSmartPointer<vtkActor> sphere7 =
    vtkSmartPointer<vtkActor>::New();
  sphere7->SetMapper(sphereMapper);
  sphere7->GetProperty()->SetColor(1,0,0);
  sphere7->GetProperty()->SetAmbient(0.3);
  sphere7->GetProperty()->SetDiffuse(0.0);
  sphere7->GetProperty()->SetSpecular(0.5);
  sphere7->GetProperty()->SetSpecularPower(20.0);
  sphere7->AddPosition(2.5,1.25,0);

  vtkSmartPointer<vtkActor> sphere8 =
    vtkSmartPointer<vtkActor>::New();
  sphere8->SetMapper(sphereMapper);
  sphere8->GetProperty()->SetColor(1,0,0);
  sphere8->GetProperty()->SetAmbient(0.3);
  sphere8->GetProperty()->SetDiffuse(0.0);
  sphere8->GetProperty()->SetSpecular(0.5);
  sphere8->GetProperty()->SetSpecularPower(40.0);
  sphere8->AddPosition(3.75,1.25,0);

  // Create the graphics structure. The renderer renders into the
  // render window. The render window interactor captures mouse events
  // and will perform appropriate camera or actor manipulation
  // depending on the nature of the events.
  //
  vtkSmartPointer<vtkRenderer> ren1 =
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin =
    vtkSmartPointer<vtkRenderWindow>::New();
  renWin->SetOffScreenRendering( 1 ); //for offscreen rendering
  renWin->AddRenderer(ren1);

  /*vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renWin);
*/

  // Add the actors to the renderer, set the background and size.
  //
  ren1->AddActor(sphere1);
  ren1->AddActor(sphere2);
  ren1->AddActor(sphere3);
  ren1->AddActor(sphere4);
  ren1->AddActor(sphere5);
  ren1->AddActor(sphere6);
  ren1->AddActor(sphere7);
  ren1->AddActor(sphere8);
  ren1->SetBackground(0.1, 0.2, 0.4);
  renWin->SetSize(400, 200);

  // Set up the lighting.
  //
  vtkSmartPointer<vtkLight> light =
    vtkSmartPointer<vtkLight>::New();
  light->SetFocalPoint(1.875,0.6125,0);
  light->SetPosition(0.875,1.6125,1);
  ren1->AddLight(light);

  // We want to eliminate perspective effects on the apparent lighting.
  // Parallel camera projection will be used. To zoom in parallel projection
  // mode, the ParallelScale is set.
  //
  ren1->GetActiveCamera()->SetFocalPoint(0,0,0);
  ren1->GetActiveCamera()->SetPosition(0,0,1);
  ren1->GetActiveCamera()->SetViewUp(0,1,0);
  ren1->GetActiveCamera()->ParallelProjectionOn();
  ren1->ResetCamera();
  ren1->GetActiveCamera()->SetParallelScale(1.5);

  // This starts the event loop and invokes an initial render.
  //
  
  vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter =
    vtkSmartPointer<vtkWindowToImageFilter>::New();
  windowToImageFilter->SetInput(renWin);
  windowToImageFilter->Update();

  vtkSmartPointer<vtkPNGWriter> writer =
    vtkSmartPointer<vtkPNGWriter>::New();
  writer->SetFileName("screenshot.png");
  writer->SetInputConnection(windowToImageFilter->GetOutputPort());
  writer->Write();

//  iren->Initialize();
//  iren->Start();

  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(Test)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(SpecularSpheres SpecularSpheres.cxx)
target_link_libraries(SpecularSpheres ${VTK_LIBRARIES})

编译example代码

-DVTK_DIR=/app/vtk/build 一定要设置

rm -rf build && mkdir build && cd build 
cmake -DVTK_DIR=/app/vtk/build ..
make -j8

运行结果

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在OpenGL中进行离屏渲染通常使用EGL来实现。EGL是一个跨平台的图形库,可以在不同的操作系统和图形硬件上运行。以下是一个简单的示例代码,说明如何使用EGL进行离屏渲染: ```c++ #include <EGL/egl.h> #include <GLES2/gl2.h> void RenderOffscreen() { // 创建EGLDisplay EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint major, minor; eglInitialize(eglDisplay, &major, &minor); // 配置EGLContext属性 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; // 创建EGLContext EGLConfig config; EGLint numConfigs; EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; eglChooseConfig(eglDisplay, attribs, &config, 1, &numConfigs); EGLSurface eglSurface = eglCreatePbufferSurface(eglDisplay, config, NULL); EGLContext eglContext = eglCreateContext(eglDisplay, config, NULL, contextAttribs); // 绑定EGLContext和EGLSurface eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // 在离屏上下文中进行渲染 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 将渲染结果保存到文件或内存中 // ... // 解绑EGLContext和EGLSurface eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // 销毁EGLContext和EGLSurface eglDestroySurface(eglDisplay, eglSurface); eglDestroyContext(eglDisplay, eglContext); // 终止EGLDisplay eglTerminate(eglDisplay); } int main() { // 在主上下文中进行渲染 // ... // 在离屏上下文中进行渲染 RenderOffscreen(); return 0; } ``` 在上面的示例代码中,我们使用EGL创建一个离屏上下文和表面,使用glClear()函数在离屏上下文中进行渲染,然后将渲染结果保存到文件或内存中。最后,我们销毁离屏上下文和表面,终止EGLDisplay。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值