本文介绍了调整MTKView的大小可在重新绘制之前缩放旧内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MTKView绘制金属内容。它的配置如下:

I'm using a MTKView to draw Metal content. It's configured as follows:

    mtkView = MTKView(frame: self.view.frame, device: device)
    mtkView.colorPixelFormat = .bgra8Unorm
    mtkView.delegate=self
    mtkView.sampleCount=4
    mtkView.isPaused=true
    mtkView.enableSetNeedsDisplay=true

setFrameSize 被覆盖以触发重新显示。

setFrameSize is overriden to trigger a redisplay.

只要视图调整大小,它就会在重新绘制所有内容之前缩放其旧内容。

Whenever the view resizes it scales its old content before it redraws everything. This gives a jittering feeling.

我尝试将MTKView图层的 contentGravity 属性设置为非调整大小的值。 ,但这完全弄乱了内容的规模和位置。

I tried setting the contentGravity property of the MTKView's layer to a non-resizing value, but that totally messes up the scale and position of the content. It seems MTKView doesn't want me to fiddle with that parameter.

如何确保在调整大小期间始终正确重绘内容?

How can I make sure that during a resize the content is always properly redrawn?

推荐答案

在我使用Metal和 MTKView 的过程中,我尝试了<$ c $的各种组合c> presentsWithTransaction 和 waitUntilScheduled 没有成功。在实时调整大小期间,我仍然偶尔会在适当渲染的帧之间遇到拉伸内容的帧。

In my usage of Metal and MTKView, I tried various combinations of presentsWithTransaction and waitUntilScheduled without success. I still experienced occasional frames of stretched content in between frames of properly rendered content during live resize.

最后,我完全放弃了 MTKView ,使我自己的NSView子类使用 CAMetalLayer 并调整大小现在看起来不错(不使用任何 presentsWithTransaction waitUntilScheduled )。一个关键点是我需要设置图层的 autoresizingMask 来获取 displayLayer 方法,以便在窗口中每一帧调用调整大小。

Finally, I dropped MTKView altogether and made my own NSView subclass that uses CAMetalLayer and resize looks good now (without any use of presentsWithTransaction or waitUntilScheduled). One key bit is that I needed to set the layer's autoresizingMask to get the displayLayer method to be called every frame during window resize.

以下是头文件:

#import <Cocoa/Cocoa.h>

@interface MyMTLView : NSView<CALayerDelegate>
@end

这里是实现:

#import <QuartzCore/CAMetalLayer.h>
#import <Metal/Metal.h>

@implementation MyMTLView

- (id)initWithFrame:(NSRect)frame
{
    if (!(self = [super initWithFrame:frame])) {
        return self;
    }

    // We want to be backed by a CAMetalLayer.
    self.wantsLayer = YES;

    // We want to redraw the layer during live window resize.
    self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;

    // Not strictly necessary, but in case something goes wrong with live window
    // resize, this layer placement makes it more obvious what's going wrong.
    self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;

    return self;
}

- (CALayer*)makeBackingLayer
{
    CAMetalLayer* metalLayer = [CAMetalLayer layer];
    metalLayer.device = MTLCreateSystemDefaultDevice();
    metalLayer.delegate = self;

    // *Both* of these properties are crucial to getting displayLayer to be
    // called during live window resize.
    metalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
    metalLayer.needsDisplayOnBoundsChange = YES;

    return metalLayer;
}

- (CAMetalLayer*)metalLayer
{
    return (CAMetalLayer*)self.layer;
}

- (void)setFrameSize:(NSSize)newSize
{
    [super setFrameSize:newSize];

    self.metalLayer.drawableSize = newSize;
}

- (void)displayLayer:(CALayer*)layer
{
    // Do drawing with Metal.
}

@end

作为参考,我将所有的金属制图MTKView的 drawRect 方法。

For reference, I do all my Metal drawing in MTKView's drawRect method.

这篇关于调整MTKView的大小可在重新绘制之前缩放旧内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 04:06