问题描述
我正在使用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的大小可在重新绘制之前缩放旧内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!