iOS рендеринг в текстуру с металлом не обновляет рендер текстуру - PullRequest
2 голосов
/ 17 апреля 2019

Я хотел бы использовать фрагментный шейдер для рендеринга в текстуру вне экрана. Как только это будет сделано, я хочу использовать результат этого в качестве входных данных для другого фрагментного шейдера.

Я создаю текстуру и очищаю ее красным (чтобы знать, что она установлена). Я использую проход рендеринга, связанный с моей целевой текстурой, и рисую. Затем я использую кодировщик команды 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;
}

Буфер, который заполняется в результате слепой копии, должен быть зеленым, но красным. Похоже, это означает, что либо bakeTexture не записывается в фрагментный шейдер, либо это так, но отсутствует некоторая синхронизация, чтобы сделать содержимое доступным во время создания копии.

...