具有金属的iOS渲染到纹理不会更新渲染纹理

时间:2019-04-17 15:04:29

标签: ios shader metal render-to-texture off-screen

我想使用片段着色器在屏幕外渲染纹理。完成此操作后,我想将其结果用作另一个片段着色器的输入。

我创建一个纹理并用红色清除它(知道已设置)。我使用连接到目标纹理并进行绘制的渲染通道。然后,我使用blit命令编码器将目标纹理的内容传输到缓冲区。缓冲区包含红色,所以我知道它正在正确读取纹理,但是绘图应使纹理变为绿色,所以出了点问题。

let textureDescriptor = MTLTextureDescriptor()
textureDescriptor.textureType = MTLTextureType.type2D
textureDescriptor.width = 2048
textureDescriptor.height = 1024
textureDescriptor.pixelFormat = .rgba8Unorm
textureDescriptor.storageMode = .shared
textureDescriptor.usage = [.renderTarget, .shaderRead, .shaderWrite]

bakeTexture = device.makeTexture(descriptor: textureDescriptor)

bakeRenderPass = MTLRenderPassDescriptor()
bakeRenderPass.colorAttachments[0].texture = bakeTexture
bakeRenderPass.colorAttachments[0].loadAction = .clear
bakeRenderPass.colorAttachments[0].clearColor = MTLClearColor(red:1.0,green:0.0,blue:0.0,alpha:1.0)
bakeRenderPass.colorAttachments[0].storeAction = .store

对于绘图,我这样做:

let bakeCommandEncoder = commandBuffer.makeRenderCommandEncode(descriptor: bakeRenderPass)
let vp = MTLViewport(originX:0, originY:0, width:2048, height:1024,znear:0.0,zfar:1.0)
bakeCommandEncoder.setViewport(vp)
bakeCommandEncoder.setCullMode(.none) // disable culling
// draw here.  Fragment shader sets final color to float4(0.0,1.0,0.0,1.0);
bakeCommandEncoder.endEncoding()

let blitEncoder = commandBuffer.makeBlitCommandEncoder()
blitEncoder!.copy(...) // this works as my buffer is all red
blitEncoder.endEncoding()

这里是顶点着色器-它基于OpenGL顶点着色器,用于转储纹理的uv布局:

struct VertexOutBake {
    float4 position [[position]];
    float3 normal;
    float3 tangent;
    float3 binormal;
    float3 worldPosition;
    float2 texCoords;
};

vertex VertexOutBake vertex_main_bake(VertexInBake vertexIn [[stage_in]],
                        constant VertexUniforms &uniforms [[buffer(1)]])
{
    VertexOutBake vertexOut;
    float4 worldPosition = uniforms.modelMatrix * float4(vertexIn.position, 1);
    vertexOut.worldPosition = worldPosition.xyz;
    vertexOut.normal = normalize(vertexIn.normal);
    vertexOut.tangent = normalize(vertexIn.tangent);
    vertexOut.binormal = normalize(vertexIn.binormal);
    vertexOut.texCoords = vertexIn.texCoords;
    vertexOut.texCoords.y = 1.0 - vertexOut.texCoords.y; // flip image

    // now use uv coordinates instead of 3D positions
    vertexOut.position.x = vertexOut.texCoords.x * 2.0 - 1.0;
    vertexOut.position.y = 1.0 - vertexOut.texCoords.y * 2.0;
    vertexOut.position.z = 1.0;
    vertexOut.position.w = 1.0;

    return vertexOut;
}

由于blit复制而填充的缓冲区应为绿色,但应为红色。这似乎意味着不是在片段着色器中写入bakeTexture或将其写入,但是在进行复制时缺少一些同步以使内容可用。

0 个答案:

没有答案