如何在 R 中使用 OpenGL 加速有效地为图像栅格设置动画?

Posted

技术标签:

【中文标题】如何在 R 中使用 OpenGL 加速有效地为图像栅格设置动画?【英文标题】:How to efficiently animate image rasters using OpenGL acceleration in R? 【发布时间】:2019-05-05 23:30:01 【问题描述】:

这是对这些问题的后续问题:

Performant 2D OpenGL graphics in R for fast display of raster image using qtpaint (qt) or rdyncall (SDL/OpenGL) packages? Most efficient way of drawing a heatmap from matrix with OpenGL?

我想以交互方式查看二维元胞自动机空间离散模拟的输出。所以我从简单开始,试图了解绘制整数值矩阵的速度有多快。我在这里尝试使用rgl 包,据我所知,该包是在 R 中提供(理论上)最快(?)图形设备的包。

我正在使用rgl 尝试这种方法,但帧速率是每秒 30 帧,我发现它相当低(参见下面的代码)。我的示例是从仅 100x100 的 R 矩阵绘制光栅图像。而且,我在闪烁,我不知道为什么。

这是我的方法(遵循@ben-bolker 的回答),现在使用来自@user2554330 的反馈。

library(viridisLite)
library(rgl)

n_colours <- 100
n_row <- 500
n_col <- 500
vv <- viridis(n_colours)

setup <- function() 
  view3d(theta=0, phi=0)  ## head-on view
  #par3d(zoom=0.65, windowRect = c(0,0, n_col, n_row), viewport = c(0,0, n_col, n_row))
  par3d(zoom=0.65, windowRect = c(0,0, n_col, n_row), viewport = c(0,0, n_col, n_row))


# draw <- function(m) 
#   d <- dim(m)
#   surface3d(x = 1:d[1], y = 1:d[2], z = matrix(0, d[1], d[2]), 
#             color = vv[m],
#             smooth=FALSE, lit=FALSE  ## turn off smoothing/lights
#   )
# 

# draw2 <- function(m) 
#   par3d(skipRedraw = TRUE)  # but skip blank update
#   clear3d()
#   
#   d <- dim(m)
#   surface3d(x = 1:d[1], y = 1:d[2], z = matrix(0, d[1], d[2]), 
#             color = vv[m],
#             smooth=FALSE, lit=FALSE  ## turn off smoothing/lights
#   )
#   par3d(skipRedraw = FALSE) # Make sure image is shown
# 

draw3 <- function(colours) 
  par3d(skipRedraw = TRUE)  # but skip blank update
  clear3d()

  d <- dim(m)
  surface3d(x = 1:d[1], y = 1:d[2], z = matrix(0, d[1], d[2]), 
            color = colours,
            smooth=FALSE, lit=FALSE  ## turn off smoothing/lights
  )
  par3d(skipRedraw = FALSE) # Make sure image is shown


nframes <- 100

n_matrices <- list()
for(i in 1:nframes) 
  n_matrices[[i]] <- vv[matrix(sample(1:n_colours, n_row*n_col, replace = TRUE), nrow = n_row)]


setup()
# time <- system.time(
#   for (i in 1:nframes) 
#     draw(n_matrices[[i]])
#     par3d(skipRedraw = FALSE) # Make sure image is shown
#     
#     par3d(skipRedraw = TRUE)  # but skip blank update
#     pop3d()
#   
#   par3d(skipRedraw = FALSE)
# )

time <- system.time(
  for (i in 1:nframes) 
    draw3(n_matrices[[i]])
  
)


fps <- nframes/time[3]
fps

【问题讨论】:

【参考方案1】:

闪烁的原因也会减慢您的显示速度。您的pop3d() 电话要求rgl 重绘没有显示表面的图像。通过告诉rgl 跳过重绘,您可以获得大约两倍的速度:

time <- system.time(
  for (i in 1:nframes) 
    draw(n_matrices[[i]])
    par3d(skipRedraw = FALSE) # Make sure image is shown

    par3d(skipRedraw = TRUE)  # but skip blank update
    pop3d()
  
  par3d(skipRedraw = FALSE)
)

【讨论】:

谢谢@user2554330!这确实加快了速度。您是否知道如何使窗口大小使一个矩阵元素精确对应一个像素? 我已将pop3d()clear3d() 交换,并将绘图/清除功能移至draw3()。另外,我现在才将颜色传递给draw3d(),看看是否会有任何性能改进,但它似乎是微不足道的。现在,由于某种原因,最后一帧总是被移动和放大(像素看起来更大)。你知道为什么吗?另外,如何使用缩放参数?如何让窗口完全被纹理填满,周围没有任何空白?你也知道为什么我不能在 for 循环结束之前杀死窗口吗? 似乎这种for循环的方法使窗口无法与鼠标交互。是不是因为计算太忙于绘制新帧,以至于几乎没有时间从鼠标捕获事件?

以上是关于如何在 R 中使用 OpenGL 加速有效地为图像栅格设置动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Opengl ES 裁剪图像?

在Haskell中使用OpenGL渲染PNG图像

如何在 Opengl windows 上加速使用 Cairo 绘图?

如何在 GameplayKit/SpriteKit 中有效地为实体和组件建模

如何有效地为列表列表中的多个补丁设置动画

讯游加速器可以加速海外抖音吗