macos - 如何在 NSScrollView 中显示非常大的基于 Metal 的纹理?
问题描述
我有一个程序可以在NSScrollView
. 我正在使用 Metal 来渲染图像,所以NSClipView
'sdocumentView
是MTKView
. 我支持放大/缩小图像的能力。我的渲染管道的最后一步将我的金属纹理包装到CIImage
我应用CIAffineTransform
过滤器进行缩放的地方。我将图像渲染drawRect
成这样的drawable:
CIImage *image = ...;
CIRenderDestination *renderDest = [[CIRenderDestination alloc] initWithWidth:image.extent.size.width
height:image.extent.size.height
pixelFormat:self.colorPixelFormat
commandBuffer:commandBuffer
mtlTextureProvider:^id<MTLTexture> _Nonnull{
return drawable.texture;
}];
[self.ciContext startTaskToRender:image
toDestination:renderDest
error:&error];
当文档视图大小发生变化时,我会更新视图的drawableSize
属性。这很好用,滚动条和滚动条按预期工作。问题是当放大系数变得太大时,drawable的底层纹理超过了GPU内存:
validateTextureDimensions, line 1081: error 'MTLTextureDescriptor has width (18798) greater than the maximum allowed size of 16384.'
validateTextureDimensions:1081: failed assertion `MTLTextureDescriptor has width (18798) greater than the maximum allowed size of 16384.'
所以将裁剪的图像绘制到可绘制对象的一部分中是行不通的(不是我知道如何从 a 中做到这一点CIImage
)。即使我没有在视图中绘制任何图像(即仅设置预期的可绘制大小)也会发生这种情况,这表明MTKView
' 的可绘制是问题所在。当然,我不需要绘制完整的图像;只是在剪辑视图中可见的部分。我可以限制drawableSize
/document 视图,但是我必须手动有效地实现滚动并丢失滚动条。
在仍然显示超大图像的同时,标准滚动视图的最佳路径是什么?或者,是否有使用CATiledLayer
Metal 之类的方法?
解决方案
我在开发者论坛上收到了一位 Apple 工程师的建议MTKView
,该建议是在 的文档视图中放置一个NSScrollView
,即:
NSScrollView
NSClipView
NSView <-- document view
MTKView
这是有道理的,因为 Metal 和 AppKit 并没有真正相互交流。使用这种方案,可以操纵文档视图大小以使滚动条正确反映并手动将其设置MTKView
为不大于剪辑视图中可见的大小。不是理想的解决方案,因为涉及到很多 NSRect 数学,但肯定是可行的。(我还没有时间实现它,但如果它出现,我会用任何有用的信息更新这个答案。)
论坛上的回复建议查看同步两个滚动视图的代码作为一个很好的起点。
推荐阅读
- python - 如何交换一个数组中的两个元素?
- c# - 在 VSTO 插件中获取 Word 进程的键盘输入
- android - 如何为此 JSON 响应生成 POJO 文件以进行自动反序列化?
- reactjs - How to How to fix "No 'Access-Control-Allow-Origin' header is present on the requested resource" in post call in reactJS using Fetch method
- asp.net-mvc - 更新时扩展 Azure Map 标记
- c# - 如何从具有不同角色的用户中插入不同的 user_id
- node.js - 尝试发布到 Web API 时如何修复错误“交通控制违规”
- python - 是否有可能将输出的长向量切割成特定的部分并将它们保存在 excel 的不同单元格中?
- c# - Azure Cosmos db 引发套接字异常
- java - 如何在spring-batch步骤中使用不同的线程进行读取、处理和写入?