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