Alright I've gotten the desired result:
[attachment=4862:Bloom2.jpg]
However the way in which I got this result is not very desirable:
Step #1: Render my scene to a texture.
Step #2: Render a fullscreen quad to another texture to make a copy of the first texture.
Step #3: Extract the pixels which are above my threshold with a fragment shader and render to first texture.
Step #4: Blur horizontally with another fragment shader and render to first texture.
Step #5: Blur Vertically with another fragment shader and render to first texture.
Step #6: Add first texture and the second texture with yet another fragment shader and render it to the screen...
As you can see that's a lot of steps and a lot of code as well. Is there anyway I can do this simpler?
My bloom effect looks good but is very inefficient.
Often step 2 will copy to a smaller texture than the screen resolution. The lower resolution isn't noticed, as you're blurring it anyway, and it makes the blur steps run much, much faster (and also increases your blur radius).
An other trick to speed it up is to utilize the filtering capability of the GPU, that's instead of taking samples at .. -3,-2,-1,0,1,2,3.. , take them between two pixels:
...-3.5,-1.5,0,1.5,3.5,5.5,..
With linear filtering enabled the result will be
pixel(1.5) = (pixel(1)+pixel(2)) * 0.5
pixel(3.5) = (pixel(3)+pixel(4)) * 0.5
This way you can get a higher radius for less samples,thought a 100% accurate gaussian blur will not be possible, but as long as it looks good it will be ok
PS: Although you could combine step 2+3 in a single step.
...-3.5,-1.5,0,1.5,3.5,5.5,..
With linear filtering enabled the result will be
pixel(1.5) = (pixel(1)+pixel(2)) * 0.5
pixel(3.5) = (pixel(3)+pixel(4)) * 0.5
This way you can get a higher radius for less samples,thought a 100% accurate gaussian blur will not be possible, but as long as it looks good it will be ok
PS: Although you could combine step 2+3 in a single step.
This way you can get a higher radius for less samples,thought a 100% accurate gaussian blur will not be possible, but as long as it looks good it will be ok
Hmmm... it could be possible...
When g0,g1,g2,... are the gaussian weights, and p0,p1,p2... the pixel values you want something like this:
final = g0*p0 + g1*p1+g2*p2+..
To utilize linear filtering better we could do something like this:
// normalize g1+g2
n1_2 = 1/(g1+g2)
=>
g1 * n1_2 + g2 * n1_2 = 1 = g1 * n1_2 + (1- (g1 * n1_2))
// now sample the pixel values with the normalized value of g1,g3,..
p0 = texture(0)
p1_2 = texture(1+(g1*n1_2))
p3_4 = textrue(3+(g3*n3_4))
// this results in
p1_2 = p1 * (g1*n1_2) + p2*(1-(g1*n1_2))
<=>
p1_2 = p1 * (g1*n1_2) + p2*(g2*n1_2)
// now multiply it with the inverted normalisation factor
p1_2 / n1_2 = p1 * g1 + p2 * g2
voila !
Screenshot is looking much better than the previous one now
That's pretty much how many steps it takes. Ironically, sometimes adding more steps can help make things faster though. The main cost in bloom isn't the the number of passes, but instead the number of pixels you are operating on.
Food for thought: you don't need to run all of that code for bloom in areas that are below the threshold (doesn't matter how much you blur black, its still black). The trick to splitting up your display to work out where the bloom needs to go is an exercise left up to you though.
As you can see that's a lot of steps and a lot of code as well. Is there anyway I can do this simpler?
That's pretty much how many steps it takes. Ironically, sometimes adding more steps can help make things faster though. The main cost in bloom isn't the the number of passes, but instead the number of pixels you are operating on.
Food for thought: you don't need to run all of that code for bloom in areas that are below the threshold (doesn't matter how much you blur black, its still black). The trick to splitting up your display to work out where the bloom needs to go is an exercise left up to you though.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement