I am trying to add blur capability to my application. I found this example of blur and am now trying to implement it using Metal. What the pipeline looks like in my case:
- I draw objects using raycast to offscreen texture;
- Then I take this texture and make a horizontal blur, and then write the result into
texture A; - I take that
texture Aand make a vertical blur, and write the result intotexture B; - I draw on the screen
texture B.
To write to textures A and B, I use the [[color(m)]] attribute as the return value from the fragment function. And then I ran into a problem, in OpenGL, in order to apply blur to a texture, for example 10 times, you can do it like this (using ping-pong framebuffers):
bool horizontal = true, first_iteration = true;
int amount = 10;
shaderBlur.use();
for (unsigned int i = 0; i < amount; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]);
shaderBlur.setInt("horizontal", horizontal);
glBindTexture(
GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongBuffers[!horizontal]
);
RenderQuad();
horizontal = !horizontal;
if (first_iteration)
first_iteration = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
But how can this be done in Metal? I tried it like this, but it didn't give any results (I mean that with loops, that without them, the result is the same, as if there is only one pass of the blur):
blur_pass_ = 1; // horizontal blur pass
[render_encoder setFragmentBytes:&blur_pass_ length:sizeof(blur_pass_) atIndex:0];
for (std::size_t x = 0; x < 9; ++x) { // how much times I want to apply blur
[render_encoder setFragmentTexture:render_target_texture_ atIndex:0];
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:num_vertices];
}
blur_pass_ = 0; // vertical blur pass
[render_encoder setFragmentBytes:&blur_pass_ length:sizeof(blur_pass_) atIndex:0];
for (std::size_t y = 0; y < 9; ++y) { // how much times I want to apply blur
[render_encoder setFragmentTexture:x_blurry_texture_ atIndex:0];
[render_encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:num_vertices];
}
[render_encoder endEncoding];
Can you tell me how to do this correctly in Metal? Yes, I also build for iphones, so performance is important to me.