Page 1 of 2

Quake Motion Blur

Posted: Thu Apr 16, 2009 4:54 pm
by mh
This somewhere in gl_rmain.c:

Code: Select all

extern cvar_t r_motionblur;

void DrawAccumBlur (void)
{
	static int blurstate = 0;
	float accblur;
	static float damagetime = -1.0f;

	if (!r_motionblur.value) return;

	// evaluate blur conditions
	if (cl.stats[STAT_HEALTH] <= 0)
	{
		// being dead always overrides everything else
		accblur = 0.75f;
	}
	else if (cl.cshifts[CSHIFT_DAMAGE].percent)
	{
		// initial damage blur
		accblur = 0.75f;
		damagetime = 0.5f;
	}
	else if (damagetime >= 0.0f)
	{
		// persist damage blur
		damagetime -= r_frametime;
		accblur = 0.75f;
	}
	else if (cl.cshifts[CSHIFT_CONTENTS].percent)
	{
		// blur less if underwater
		accblur = 0.666f;
	}
	else accblur = -1.0f;

	if (accblur <= 0.0f)
	{
		// reinit if we're not blurring so that the contents of the
		// accumulation buffer are valid for the frame
		blurstate = 0;
		return;
	}

	if (!blurstate)
	{
		// load the scene into the accumulation buffer
		glAccum (GL_LOAD, 1.0f);
	}
	else
	{
		glAccum (GL_MULT, accblur); // scale contents of accumulation buffer
		glAccum (GL_ACCUM, 1.0f - accblur); // add screen contents
		glAccum (GL_RETURN, 1.0f); // read result back
	}

	blurstate = 1;
}
(Declare and register the r_motionblur cvar somewhere too, and you may also need to have a global called r_frametime, so just set it up the same way as frametime in R_DrawParticles...)

Call it like this, at the end of R_RenderView, after everything else is drawn:

Code: Select all

	// draw motion blur effects on the full 3D view
	DrawAccumBlur ();
Finally, in gl_vidnt.c, when setting up your PIXELFORMATDESCRIPTOR, just set the cAccumBits member to 64.

There's no need to clear the accumulation buffer between frames, should work just fine on any engine out of the box.

Posted: Thu Apr 16, 2009 5:47 pm
by MeTcHsteekle
sweet 8)

Re: Quake Motion Blur

Posted: Thu Jun 05, 2014 9:05 pm
by leileilol
Just chiming in that this can also be applied to Q3A as well (though replacing the whole stat/damage checking with some variable framerate smoothing thing, since you can't access player stats from the renderer module anyway).

Thanks!

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 8:24 am
by r00k
works!

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 12:44 pm
by leileilol
By the way and FYI - accumulation buffers in consumer videogaming video hardware only begin their support starting from shader model 2.0 hardware, despite this predating the whole programmable shader thing for ages.

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 9:41 pm
by toneddu2000
I can't understand the last step.
Finally, in gl_vidnt.c, when setting up your PIXELFORMATDESCRIPTOR, just set the cAccumBits member to 64.
I use quakespasm and there's no gl_vidnt.c but gl_vidsdl.c. I hope it's the same. Now what should I set?
thanks

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 9:57 pm
by hogsy
Rather than doing that I'd suppose you'd set the following in the case of SDL.

Code: Select all

SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,8);

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 10:37 pm
by toneddu2000
thanks hogsy but where should I put those functions?

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 10:42 pm
by hogsy
I haven't touched QuakeSpasm but if you take a look in gl_vidsdl there should be a bunch of the same functions where the SDL window is created and you can just plop it in with those, shouldn't be too hard to find if you just do a quick search :wink:

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 10:51 pm
by toneddu2000
the only SDL_GL_SetAttribute() function I found it's in VID_SetMode () int gl_vidsdl.c and it's called like this:

Code: Select all

if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vid_vsync.value) ? 1 : 0) == -1)
		gl_swap_control = false;
There's no bunch of SDL functions

thanks

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 10:56 pm
by hogsy
Just plop it under those two lines then.

Re: Quake Motion Blur

Posted: Sat Jun 07, 2014 11:17 pm
by toneddu2000
It worked! Thanks a lot hogsy and of course mh for this great addition!

For the QuakeSpasm lovers:
declare at the start of the gl_rmain.c

Code: Select all

float  r_frametime;
put at the start of the DrawAccumBlur() function

Code: Select all

r_frametime = cl.time - cl.oldtime;
in gl_vidsdl.c, in VID_SetMode function,after:

Code: Select all

if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vid_vsync.value) ? 1 : 0) == -1)
		gl_swap_control = false;
put those lines as hogsy stated

Code: Select all

SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8);
I avoided the

Code: Select all

if (!r_motionblur.value) return;
line because I still didn't understand how send the cvars to quakec, so in my case motion blur is on by default.

There's a chance to mimic that cool Doom3 pain rotating head effect?

Re: Quake Motion Blur

Posted: Sun Jun 08, 2014 12:37 am
by leileilol
You could do something derivative of v_idlescale in view.c to make that scale from damagetime.

Re: Quake Motion Blur

Posted: Sun Jun 08, 2014 1:09 pm
by toneddu2000
thanks leilei, I tried in V_AddIdle:

Code: Select all

void V_AddIdle (void)
{
	r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
	r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
	r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value;
	//code below added by me
	if (cl.cshifts[CSHIFT_DAMAGE].percent)
	{
		cl.viewent.angles[ROLL] -= v_idlescale.value * 250.0f;
		cl.viewent.angles[PITCH] -= v_idlescale.value * 250.0f;
		cl.viewent.angles[YAW] -= v_idlescale.value * 250.0f;
	}
}
Then I set cvar r_idlescale to 1 but nothing. I exagerated roll,pitch and yaw movements to maximum just to test if it could work but it doesn't do anything

Re: Quake Motion Blur

Posted: Sun Jun 08, 2014 7:23 pm
by leileilol
Because you have to alter the refdef's angles not the viewent itself. IIRC, viewent is the gun. The gun gets its origin and angles calculated in another function that comes after addidle. iirc