如何根据金属视口清除颜色?
How to clear color according to viewport on Metal?
假设有一个 200 x 200 颜色的可绘制对象。我想清除屏幕的区域(0,0,100,100)以显示红色。代码如下:
- (void)drawInMTKView:(nonnull MTKView *)view
{
// Create a new command buffer for each render pass to the current drawable.
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"MyCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures.
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.0, 0.0, 1.0);
if(renderPassDescriptor != nil)
{
// Create a render command encoder.
id<MTLRenderCommandEncoder> renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyRenderEncoder";
// Set the region of the drawable to half.
NSUInteger renderAreaWidth = _drawableSize.x/2;
NSUInteger renderAreaHeight = _drawableSize.y/2;
[renderEncoder setViewport:(MTLViewport){0, 0, renderAreaWidth, renderAreaHeight}];
[renderEncoder setScissorRect:(MTLScissorRect){0, 0, renderAreaWidth, renderAreaHeight}];
[renderEncoder endEncoding];
// Schedule a present once the framebuffer is complete using the current drawable.
[commandBuffer presentDrawable:view.currentDrawable];
}
// Finalize rendering here & push the command buffer to the GPU.
[commandBuffer commit];
}
预期的结果应该是drawable 的左上部分清晰为红色,其余部分为黑色。
但是我发现整个drawable都是透明的红色。
怎么可能呢?我该如何解决?
正如您所确定的,Metal 不会将视口和剪刀应用到 renderpass 加载操作清除。
您必须手动清除子区域:
- 如果您已经在渲染通道中,则可以渲染适当的剪辑 -space 四边形。
- 如果渲染通道尚未启动,您可以选择使用计算通道,这可能会更快。
- 如果 renderpass 还没有开始,并且要清除的区域具有一致的大小(即 - 你总是逐帧清除相同的区域),你可以填充一个单独的纹理或缓冲区,并将其 BLIT 到目标区域。这可能是最有效的选择。
假设有一个 200 x 200 颜色的可绘制对象。我想清除屏幕的区域(0,0,100,100)以显示红色。代码如下:
- (void)drawInMTKView:(nonnull MTKView *)view
{
// Create a new command buffer for each render pass to the current drawable.
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"MyCommand";
// Obtain a renderPassDescriptor generated from the view's drawable textures.
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0, 0.0, 0.0, 1.0);
if(renderPassDescriptor != nil)
{
// Create a render command encoder.
id<MTLRenderCommandEncoder> renderEncoder =
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyRenderEncoder";
// Set the region of the drawable to half.
NSUInteger renderAreaWidth = _drawableSize.x/2;
NSUInteger renderAreaHeight = _drawableSize.y/2;
[renderEncoder setViewport:(MTLViewport){0, 0, renderAreaWidth, renderAreaHeight}];
[renderEncoder setScissorRect:(MTLScissorRect){0, 0, renderAreaWidth, renderAreaHeight}];
[renderEncoder endEncoding];
// Schedule a present once the framebuffer is complete using the current drawable.
[commandBuffer presentDrawable:view.currentDrawable];
}
// Finalize rendering here & push the command buffer to the GPU.
[commandBuffer commit];
}
预期的结果应该是drawable 的左上部分清晰为红色,其余部分为黑色。
但是我发现整个drawable都是透明的红色。
怎么可能呢?我该如何解决?
正如您所确定的,Metal 不会将视口和剪刀应用到 renderpass 加载操作清除。
您必须手动清除子区域:
- 如果您已经在渲染通道中,则可以渲染适当的剪辑 -space 四边形。
- 如果渲染通道尚未启动,您可以选择使用计算通道,这可能会更快。
- 如果 renderpass 还没有开始,并且要清除的区域具有一致的大小(即 - 你总是逐帧清除相同的区域),你可以填充一个单独的纹理或缓冲区,并将其 BLIT 到目标区域。这可能是最有效的选择。