我正在学习金属和创建一个小应用程序在我的iPhone XR与XCode 13.4.1(iOS目标15.5)。
我渲染了一个简单的球体,并试图创建一个“发光”或“绽放”效果,如本文所述:https://weblog.jamisbuck.org/2016/2/27/bloom-effect-in-metal.html
我成功地使用金属性能着色器执行高斯模糊和渲染到一个纹理只有'模糊'的轮廓我的球体。纹理尺寸的输出这个过程匹配我目前的'可绘制'的尺寸以及。
我的问题是,当我稍后使用计算着色器将高斯纹理与我的场景纹理混合时,输出纹理被合并,但奇怪的是高斯输入纹理似乎被缩小到输入大小的25%,因此只覆盖了我的场景的左上角。请查看所附的屏幕截图以获得更好的描述。
为什么混合是这样工作的,只渲染在左上角象限?我该如何解决它?谢谢任何帮助。
我已经粘贴了相关的代码在这里的一切后,我的3d场景渲染,通过计算着色器混合,并介绍到屏幕上。
// Do the drawing of the 3d scene
commandEncoder.endEncoding()
print("Before Texture: \(drawable.texture.width) \(drawable.texture.height)")
if true {
// Now create a compute shader to blend the blurred mask texture
// with the framebuffer
let computeFunction = self.computeLibrary.makeFunction(name: "ComputeBlender")
// Setup compute encoder
let computePipelineState = try? device.makeComputePipelineState(function: computeFunction!)
let computeEncoder = commandBuffer.makeComputeCommandEncoder()
computeEncoder?.setComputePipelineState(computePipelineState!)
// input one -- primary texture
computeEncoder?.setTexture(drawable.texture, index: 0)
// input two -- mask texture
computeEncoder?.setTexture(self.debugImageA, index: 1)
// output texture
computeEncoder?.setTexture(drawable.texture, index: 2)
if false {
let threadsPerGroup = MTLSizeMake(1, 1, 1)
let w = Int(view.drawableSize.width)
let h = Int(view.drawableSize.height)
let threadsPerGrid = MTLSizeMake(w, h, 1)
computeEncoder?.dispatchThreads(threadsPerGrid, threadsPerThreadgroup: threadsPerGroup)
} else {
let viewWidth = Int(view.bounds.size.width)
let viewHeight = Int(view.bounds.size.height)
// set up an 8x8 group of threads
let threadGroupSize = MTLSize(width: 1, height: 1, depth: 1)
// define the number of such groups needed to process the textures
let numGroups = MTLSize(
width: viewWidth/threadGroupSize.width+1,
height: viewHeight/threadGroupSize.height+1,
depth: 1)
computeEncoder?.dispatchThreadgroups(numGroups,
threadsPerThreadgroup: threadGroupSize)
}
computeEncoder?.endEncoding()
}
// Capture debug texture
self.debugImageB = drawable.texture
// Present the final/blended image
commandBuffer.present(drawable)
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
print("After Texture: \(self.debugImageB.width) \(self.debugImageB.height)")
下面是与post匹配的着色器-请注意,我重新排列了颜色,使最终图像显示不正确的混合:
# include <metal_stdlib>
using namespace metal;
kernel void ComputeBlender(
texture2d<float, access::read> source [[ texture(0) ]],
texture2d<float, access::read> mask [[ texture(1) ]],
texture2d<float, access::write> dest [[ texture(2) ]],
uint2 gid [[ thread_position_in_grid ]])
{
float4 source_color = source.read(gid);
float4 mask_color = mask.read(gid);
float4 result_color = source_color + mask_color;
result_color = float4(result_color.g, result_color.b, result_color.r, 1.0);
dest.write(result_color, gid);
}
1条答案
按热度按时间zqdjd7g91#
您的线程位置逻辑在着色器中未正确实现。您应该考虑纹理的大小。