使用rdyncall软件包和SDL/OpenGL调用快速显示光栅图像的R中高性能2D OpenGL图形

ckocjqey  于 2022-12-12  发布在  其他
关注(0)|答案(1)|浏览(163)

bounty将在6天后过期。回答此问题可获得+400声望奖励。Tom Wenseleers正在寻找标准答案:我们诚邀SDL和OpenGL领域的任何Maven尝试回答这个问题,这对R社区非常有用...

对于一个实时交互式Mandelbrot查看器,我在R中制作,我正在寻找一种高性能的方式来显示1920 x1080原始十六进制颜色矩阵作为光栅图像,希望能够达到约5-10 fps(calculating the Mandelbrot images themselves now achieves ca. 20-30 fps at moderate zooms,当然滚动应该很快)(当然,在R中可能存在许多访问 swift2 D图形的应用程序)。使用image()和选项useRaster=TRUEplot.raster或甚至grid.raster()都不能解决这个问题,因为显示光栅图像比实际计算要慢得多(最好的情况下大约1/4秒),所以我在寻找一个性能更高的选项,最好使用OpenGL加速。
我注意到应该可以使用rdyncall包从R中调用SDL、SDL_image和GL/OpenGL函数,这应该有更好的性能。
虽然此软件包存档在CRAN上,但它仍然具有完整的功能。请参阅白皮书here和Mercurial资源库here
要安装存档版本,请执行以下操作:

library(devtools)
install_version("rdyncall",
                version="0.7.5",
                repos="http://cran.us.r-project.org")

SDLSDL_imageSDL_mixer DLL(版本1.2)(在Windows上)必须首先从https://libsdl.org/release/https://www.libsdl.org/projects/SDL_image/release/https://www.libsdl.org/projects/SDL_mixer/release/安装)(the 64 bit DLLs are to be put under R-4.2.1/bin/x64“)。在Ubuntu上,它们可以使用

sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2

有关如何调用SDL和OpenGL的一些演示可在https://dyncall.org/demos/soulsalicious/index.html(20世纪80年代计算机游戏风格的starfield,包括音乐)上获得。
我说这个软件包应该可以使用SDLopengl加速来显示2D图像光栅,对吗?如果是,有人有什么想法吗?(我这么问是因为我没有使用SDLOpenGL的经验)
要打开一个1920 x 1080的SDL窗口,我想我必须使用(来自https://dyncall.org/demos/soulsalicious/soulsalicious.tar.gz中的windowed.R脚本,全屏也是可能的,请参见fullscreen.R

init <- function()
{
  require(rdyncall)
  dynport(SDL)
  SDL_Init(SDL_INIT_VIDEO)
  dynport(GL)
  dynport(GLU)
  dynport(SDL_image)
  
  SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8)
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8)
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8)
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1)
  s <<- SDL_SetVideoMode(1920,1080,32,SDL_HWSURFACE+SDL_OPENGL+SDL_DOUBLEBUF)
  SDL_WM_SetCaption("SDL window",NULL)
}
init()

再次关闭该窗口是SDL_Quit()
我想我应该能够传递一个原始十六进制颜色矩阵,并将其作为OpenGL 2D纹理绑定到这个SDL表面。在windowed.R演示中,它有一个loadTexture函数,看起来接近我所需要的,尽管它加载了一个PNG图像,而我想传递一个原始十六进制颜色矩阵。有人知道如何完成吗?
非OpenGL选项的某些计时对我的应用程序来说太慢:

# some example data & desired colour mapping of [0-1] ranged data matrix
library(RColorBrewer)
ncol=1080
cols=colorRampPalette(RColorBrewer::brewer.pal(11, "RdYlBu"))(ncol)
colfun=colorRamp(RColorBrewer::brewer.pal(11, "RdYlBu"))
col = rgb(colfun(seq(0,1, length.out = ncol)), max = 255)
mat=matrix(seq(1:1080)/1080,nrow=1920,ncol=1080,byrow=TRUE)
mat2rast = function(mat, col) {
  idx = findInterval(mat, seq(0, 1, length.out = length(col)))
  colors = col[idx]
  rastmat = t(matrix(colors, ncol = ncol(mat), nrow = nrow(mat), byrow = TRUE))
  class(rastmat) = "raster"
  return(rastmat)
}
system.time(mat2rast(mat, col)) # 0.24s

# plot.raster method - one of the best?
par(mar=c(0, 0, 0, 0))
system.time(plot(mat2rast(mat, col), asp=NA)) # 0.26s

# grid graphics - tie with plot.raster?
library(grid)
system.time(grid.raster(mat2rast(mat, col),interpolate=FALSE)) # 0.28s

# base R image()
par(mar=c(0, 0, 0, 0))
system.time(image(mat,axes=FALSE,useRaster=TRUE,col=cols)) # 0.74s # note Y is flipped to compared to 2 options above - but not so important as I can fill matrix the way I want

# ggplot2 - just for the record...
df=expand.grid(y=1:1080,x=1:1920)
df$z=seq(1,1080)/1080
library(ggplot2)
system.time({q <- qplot(data=df,x=x,y=y,fill=z,geom="raster") + 
                scale_x_continuous(expand = c(0,0)) + 
                scale_y_continuous(expand = c(0,0)) +
                scale_fill_gradientn(colours = cols) + 
                theme_void() + theme(legend.position="none"); print(q)}) # 11s
kupeojn6

kupeojn61#

根据RGL package introduction,它是:
R的可视化设备系统,使用OpenGL作为渲染后端。其核心的rgl设备是用C++编写的实时3D引擎。它提供交互式视点导航工具(鼠标+滚轮支持)和R编程接口。
由于RGL是一个真实的的3D引擎,我希望使用RGL的2D将给予你一个快速的显示。

  • 请注意,这是一个旧项目,因此我不确定它是否符合您的要求。*

您可以查看this paper,并看到一些结果图像in this gallery

相关问题