【问题标题】:Fast way to clear background快速清除背景的方法
【发布时间】:2015-03-18 06:24:04
【问题描述】:

我目前正在分析我的 Java-2d-Application(用于学习目的的游戏引擎)。 由于我不能保证每一帧都被完全覆盖,所以我必须将每一帧的背景清除为纯色(即 Color.BLACK)。

我这样做的方式很慢(我的环境中大约 40% 的绘图时间用于清除背景)。

首先我从 bufferStrategy 中获取图形上下文,然后在绘制实际内容之前在其上以全分辨率绘制 [PickYourColor]-Rectangle。

// fill background with solid color
graphics.setColor(Color.BLACK);
graphics.fillRect(
                0,
                0,
                (int) bounds.getWidth(),
                (int) bounds.getHeight());

有没有一种更高效、独立于平台的方法来使用 Java-2D 将每帧的背景清除为纯色(这不是 LWJGL 问题)?

我正在寻找的是 graphics.clearBackgroundToSolidColor(Color color) - 方法...

根据要求:这里是完整的渲染方法(它不是 SSCCE,但它非常简短且一目了然)

/**
 * Create a new graphics context to draw on and
 * notify all RenderListeners about rendering.
 */
public void render() {

    ///// abort drawing if we don't have focus /////
    if (!this.windowJFrame.hasFocus()) {
        return;
    }


    ///// draw and create new graphics context /////
    Graphics2D graphics = null;
    do {

        try {
            graphics = (Graphics2D) this.bufferStrategy.getDrawGraphics();
            Rectangle2 bounds = this.getBounds();

            // set an inexpensive, yet pretty nice looking, rendering directives
            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);



            // fill background with solid color
            graphics.setColor(Color.BLACK);
            graphics.fillRect(
                    0,
                    0,
                    (int) bounds.getWidth(),
                    (int) bounds.getHeight());


            // notify all listeners that they can draw now
            synchronized (this.renderListeners) {
                for (RenderInterface r : this.renderListeners) {
                    r.render(graphics, bounds);
                }
            }

            // show buffer
            graphics.dispose();
            this.bufferStrategy.show();


        } catch (Exception e) {

            Logger.saveMessage("window", Logger.WARNING, "Caught exception while drawing frame. Exception: " + e.toString());
        }

    } while (this.bufferStrategy.contentsLost());

}

【问题讨论】:

  • 我在所有应用程序中都使用了fillRect,我从来没有遇到过性能问题。
  • setBackground(Color)clearRect(int,int,int,int) 有什么改进吗?
  • 你确定它的fillRect 很慢吗?你能发布你的完整渲染方法吗?
  • @RealSkeptic:这是贬义的,我不想使用它(除了它具有完全相同的性能)stackoverflow.com/questions/2367365/…
  • @DimaMaligin:100% 肯定,因为如果我注释掉上面的行,我会得到一个大约。 40% 的性能提升。当然,在其他环境或应用程序中,百分比可能或多或少(@TameHog:这可能是您没有问题的原因),但在高分辨率(全高清及更高)上,填充算法很慢(在 4 个 Windows 上测试)

标签: java java-2d


【解决方案1】:

我不能说为什么fillRect 很慢,但是您可以尝试创建一个Image 并将其绘制为背景。不知道它是否会更快。

尝试:

BufferedImage bi = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
int[] imageData =((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
Arrays.fill(imageData, 0);

然后画Image,而不是fillRect

graphics.drawImage(bi, 0, 0, null);

告诉我进展如何(我对此表示怀疑)。

【讨论】:

  • 所以...你基本上在做的是覆盖图形上下文的内部 int[]-array?
  • 只画一个Image 而不是fillRect
  • oh... ok ;-) 在您的代码中,我们必须在绘制(或预先转换它)时将图像拉伸到帧的宽度和高度。拉伸是一项昂贵的操作,特别是如果您使用插值双线性或双三次。因此,在您的示例中,缓冲图像必须使用我在发布此问题之前测试的 frame 的维度创建。它大约是 fillRect 速度的一半。也许 fillRect 是 Java2D 中最有效的方式 sigh
  • @Florian 我仍然不知道你得到的 FPS,我之前在 1080p Canvas 上使用了 fillRect,并且仅在 bg 填充时获得了大约 900fps。
  • @Florian 如果您决定使用 openGL,请确保使用 openGL3+ 而不是带有蹩脚GL.begin() 方法的旧版本。使用 VAO 而不是直接从 VertexArrays 绘制,并花时间编写自己的 SLDL 着色器,它们可以大大加快速度。
【解决方案2】:

如果您想清除整个背景,请尝试canvas.drawColor(color, PorterDuff.Mode.CLEAR)。应该会快一点

【讨论】:

    猜你喜欢
    • 2017-10-31
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多