Sign in to follow this  

glow effect using fbos

This topic is 3569 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been messing around with a glow effect and attempting to make it work the way I want. I'm following (I think) what seems to be the recognised pattern (mentioned in a thread somewhere here and fairly similar to the gamasutra article on glow). 1. Render scene normally. 2. Render glowing things to a framebuffer. 3. Render the new texture with the glowy stuff, blurring it horizontally to a smaller framebuffer. 4. Render the texture from 3 to another framebuffer of the same smaller size, blurring it vertically. 5. Use additive blending to render the texture from 4 onto the original scene. Now this works in a manner of speaking: The first image shows the result with framebuffers in 3. and 4. at 1/4 the screen size. The second with them at 1/8 of the screen size. (I've accentuated the effect somewhat by fiddling with my kernel values). My problem is how to expand the glowyness without the "blobbing". It seems to me that I could increase the size of my blurring kernel (resulting in a framerate drop). Or I could make the two glow textures smaller, which spreads out the glow, but forms the blobs. Is there another way to widen the blur / glow effect? (For added info here's the glsl blur fragment shaders (adapted from ozone3d.net:)
// HORIZONTAL!!!
#define KERNEL_SIZE 3

const float kernel[KERNEL_SIZE] = {
	1.0/2.0, 2.0/2.0, 1.0/2.0,
};

uniform sampler2D baseImage;
uniform float samplerWidth;

float step_w = 1.0/samplerWidth;

const vec2 offset[KERNEL_SIZE] = { 
	vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0),
};

void main() {
	vec4 sum = vec4(0.0);
	for(int i = 0; i < KERNEL_SIZE; i++) {
		vec4 tmp = texture2D(baseImage, gl_TexCoord[0].st + offset[i]);
		sum += vec4(tmp.rgb * kernel[i], 1.0);
   }

   gl_FragColor = sum;
}







///VERTICAL!!!
#define KERNEL_SIZE 3

const float kernel[KERNEL_SIZE] = {
	1.0/2.0,
	2.0/2.0,
	1.0/2.0,
};

uniform sampler2D baseImage;
uniform float samplerHeight;

float step_h = 1.0/samplerHeight;

const vec2 offset[KERNEL_SIZE] = {
	vec2(0.0, -step_h),
	vec2(0.0, 0.0),
	vec2(0.0, step_h),
};

void main() {
	vec4 sum = vec4(0.0);
	for(int i = 0; i < KERNEL_SIZE; i++) {
		vec4 tmp = texture2D(baseImage, gl_TexCoord[0].st + offset[i]);
		sum += vec4(tmp.rgb * kernel[i], 1.0);
   }

   gl_FragColor = sum;
}







[Edited by - sprite_hound on February 7, 2008 9:42:03 PM]

Share this post


Link to post
Share on other sites
u could do multiple pass eg

for ( int i=0; i<g_Program.options.glow_amount; i++ )
{
g_SC->windowglow_fbo[0].bind_fbo();

if ( i == 0 )
g_GL->bindTexture_rectangle_to_unit( 9, windowglow_original_textureID );
else
g_GL->bindTexture_rectangle_to_unit( 9, windowglow_textureID[1] );
g_GL->bindTexture_rectangle_to_unit( 0, windowglow_textureID[0] );

g_rm.umLIB.set_this_uniquematerial_pass_state( "glow3_material", MATERIAL_DIRLIGHT_0SM );

g_GL->draw_fullsize_quad_rectangle( texW, texH );

g_SC->windowglow_fbo[0].unbind_fbo();

g_SC->windowglow_fbo[1].bind_fbo();

g_GL->bindTexture_rectangle_to_unit( 9, windowglow_textureID[0] );
g_GL->bindTexture_rectangle_to_unit( 0, windowglow_textureID[1] );

g_rm.umLIB.set_this_uniquematerial_pass_state( "glow2_material", MATERIAL_DIRLIGHT_0SM );

g_GL->draw_fullsize_quad_rectangle( texW, texH );

g_SC->windowglow_fbo[1].unbind_fbo();
}


also with offsetting

instead of
vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0),
use a offset of 0.5 (so its between the pixels)
this way u get an extra blur sample for free

Share this post


Link to post
Share on other sites
Well, I've finally got round to taking another look at this. I've changed the blurring to the "simple glow" method in the OpenGL SDK from nVidia (adapted from cG with a couple of changes). This seems to run rather faster with a larger blur radius than before, and the downsizing of the framebuffers doesn't cause additional "blobs" as before.

It looks like with this I won't need to use anything else to increase the blur radius, but thanks for the suggestions zedz. :)

Here's the glsl vertical blur fragment shader for reference (the horizontal one is obviously similar...):


#define KERNEL_SIZE 9

float kernel[KERNEL_SIZE] = {
0.93, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1,
};
#define NORM_KERNEL (1.0 / (1.0 + 2.0*(0.93 + 0.8 + 0.7 + 0.6 + 0.5 + 0.4 + 0.3 + 0.2 + 0.1)) )

uniform sampler2D baseImage;

uniform float samplerHeight;
vec2 step = vec2(0.0, 1.0 / samplerHeight);

uniform float glowFactor;

void main() {
vec3 c = texture2D(baseImage, gl_TexCoord[0].st).rgb * NORM_KERNEL;

vec2 dir = step;
for(int i = 0; i < KERNEL_SIZE; ++i) {
vec3 c2 = texture2D(baseImage, gl_TexCoord[0].st + dir).rgb;
c += c2 * kernel[i] * NORM_KERNEL;

c2 = texture2D(baseImage, gl_TexCoord[0].st - dir).rgb;
c += c2 * kernel[i] * NORM_KERNEL;
dir += step;
}
gl_FragColor = vec4(c * glowFactor, 1.0);
}





However... I'm still getting "blobs". Fewer than before, and I'm not entirely sure what's causing them:


They only happen with near, but not exactly horizontal lines. This makes me think there's something dodgy with the lines being drawn (using GL_LINE_STRIP). I guess I need to look into line anti-aliasing and see if that solves the problem. Anyone experienced that problem or have any suggestions?

Share this post


Link to post
Share on other sites
Hi sprite_hound,
I ran into the same "blobs" problem the other day making a prototype energy beam out of a simple line. Antialiasing your lines will help. Wherever your line is 2-pixels-thick, you're putting twice as much light into your glow as where your line is 1-pixel-thick.

Appearance will also improve with thicker lines. For example, the ratio between 5-pixels-thick and 4-pixels-thick is 5:4, which is a lot less than 2:1.

My final energy beam will not be made out of lines, so it will be better. But I noticed that testing your glow filter with a rotating, aliased line is a good worst-case scenario with which to check for bad glow artifacts.

Share this post


Link to post
Share on other sites

This topic is 3569 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this