对于一个实时交互式Mandelbrot查看器,我在R中制作,我正在寻找一种高性能的方式来显示1920 x1080原始十六进制颜色矩阵作为光栅图像,希望能够达到约5-10 fps(calculating the Mandelbrot images themselves now achieves ca. 20-30 fps at moderate zooms,当然滚动应该很快)(当然,在R中可以有许多访问 swift2 D图形的应用)。使用带有选项useRaster=TRUE
的image()
,plot.raster
甚至grid.raster()
都不能解决这个问题,因为显示光栅图像比实际计算要慢得多(最好的情况下大约是1/4秒),所以我在寻找一个性能更好的选项,最好是使用SDL或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")
SDL
、SDL_image
和SDL_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,包括音乐)上获得。
我说的这个软件包应该可以使用SDL
和opengl
加速来显示2D图像光栅,对吗?如果是这样,有没有人想过如何做到这一点(我问是因为我没有使用SDL或OpenGL的经验)?
要打开一个1920 x 1080 SDL窗口,我想我必须使用(从https://dyncall.org/demos/soulsalicious/soulsalicious.tar.gz中的一些OpenGL示例和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)
x_res <- 1920
y_res <- 1080
win <- SDL_SetVideoMode(x_res, y_res, 32,
SDL_HWSURFACE + SDL_OPENGL + SDL_DOUBLEBUF)
SDL_WM_SetCaption("SDL surface",NULL)
glEnable(GL_TEXTURE_2D)
# Set the projection matrix for the image
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
x_min=1
x_max=x_res
y_min=1
y_max=y_res
glOrtho(x_min, x_max, y_min, y_max, -1, 1)
# Set the modelview matrix for the image
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
}
init()
我收集我应该然后设置一些像素转移图使用的东西,
glPixelMapfv(GL_PIXEL_MAP_I_TO_R, nb_colors, map_colors)
glPixelMapfv(GL_PIXEL_MAP_I_TO_G, nb_colors, map_colors)
glPixelMapfv(GL_PIXEL_MAP_I_TO_B, nb_colors, map_colors)
然后使用另一个pixels <- glPixelMapfv
调用为像素数据创建一个缓冲区,使用glDrawPixels
将像素数据绘制到屏幕上,使用SDL_GL_SwapBuffers(win)
交换前后缓冲区以显示图像,然后等待用户关闭窗口,然后使用SDL_Quit()
等进行清理。问题是我没有OpenGL或SDL经验,那么有谁知道如何执行最后几个步骤吗?(我在这里使用的是SDL 1. 2版)
非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
2条答案
按热度按时间t1rydlwq1#
根据RGL package introduction,它是:
R的可视化设备系统,使用OpenGL作为渲染后端。其核心的rgl设备是用C++编写的实时3D引擎。它提供了交互式视点导航工具(鼠标+滚轮支持)和R编程接口。
由于RGL是一个真实的的3D引擎,我希望使用RGL的2D将给予你一个快速的显示。
您可以查看一下this paper并看到一些结果图像in this gallery
au9on6nz2#
不是基于SDL或OpenGL的解决方案(应该更快),但在https://github.com/coolbutuseless/nara中实现的nativeRaster格式显示640x480图像光栅的速度似乎比
grid.raster()
快10倍。要显示栅格,只需调用
其中
ras
是规则栅格光栅。有几个很好的演示,包括一个R版本的pacman,https://github.com/coolbutuseless/pacman和游戏Anotherworld,https://github.com/coolbutuseless/anotherworld。
还有一个演示,我使用
nara
来做实时Mandelbrot分形缩放,参见https://github.com/tomwenseleers/mandelExplorer中的zoom()
函数。参见视频here。