Motion Blur
BlitzMax Forums/BlitzMax Beginners Area/Motion Blur
| ||
Does anyone have a code example of creating a motion blur overlay effect? Thanks |
| ||
I guess you could just draw the sprite multiple times at incremental alpha transparancies towards the direction of the motion (so you see one sharp solid object, and some faded smears in the direction it came from) |
| ||
Would it work to copy everything within GraphicsWidth() and GraphicsHeight() into an image and draw with 0.75 alpha? If this is possible could someone show me how? |
| ||
If you want fullscreen motion blur, just replace your Cls call with a full screen DrawRect drawn with alpha. For example, a black rect that is full screen at .1 alpha will take ten frames to clear a given pixel. |
| ||
If you want fullscreen motion blur, just replace your Cls call with a full screen DrawRect drawn with alpha. For example, a black rect that is full screen at .1 alpha will take ten frames to clear a given pixel. Except that you can't count on wha tthe screen will look like without clearing it: some video adapters double-buffer, other tripple- or even quad buffer, meaning that your 'old' grpahicsd may jump back and forth or flash between old content and a black screen. You may even see a 'random' memory dump flash by. If you want to re-use/modify existing image data, you will *have* to redraw it to ensure it shows up correctly on all systems. |
| ||
Here's a quick and dirty example for giving motion blur to a specific sprite... 5 different steps, or for a smoother appearance average out the in-between steps for 9 total. Move the mouse to see the blur. Hold down the left mouse button to enable the additional in-between steps.SuperStrict Graphics 1024,768 Local backgroundimg:Timage=LoadImage("j:\monkey4.jpg") Local spriteimg:Timage=LoadImage("C:\Code\BlitzMax\samples\digesteroids\graphics\Digestive.png") Global oldcoord:Int[5,2] ' Array with 5 slots to remember old positions. [n,0]=X, [n,1]=Y Local t:Int ' Temporary counter variable Local Average:Int ' Whether or not we want to smooth the movements. For t=0 To 4 'We have an array of 5 positions (0 through 4) which hold the previous locations of the sprite 'that we want to follow. first pre-populate all slots to the beginning position of the sprite, 'so that we start out with no trail. using mousex and mousey since those are the sprite position. oldcoord[t,0]=MouseX() oldcoord[t,1]=MouseY() Next SetBlend alphablend DrawImage(backgroundimg:Timage,0,0) While Not KeyDown(key_escape) For t=3 To 0 Step -1 ' Move the old positions each one spot down the line in the array, overwriting the last spot oldcoord[t+1,0]=oldcoord[t,0] oldcoord[t+1,1]=oldcoord[t,1] Next oldcoord[0,0]=MouseX() ' and store the current position at the first slot oldcoord[0,1]=MouseY() SetAlpha 1.0 ' Set the alpha to full DrawImage(backgroundimg:timage,0,0) ' draw the current background image SetAlpha 0.2 ' Set the alpha to 0.2 for the final, weakest copy in the trail, and draw at the ' oldest remembered coordinates DrawImage(spriteimg:timage,oldcoord[4,0],oldcoord[4,1]) If average=True Then ' If average is enabled, then draw an intermediate fade on the location SetAlpha 0.3 ' in between the oldest and second-oldest locations DrawImage(spriteimg:timage,(oldcoord[4,0]+oldcoord[3,0])/2,(oldcoord[4,1]+oldcoord[3,1])/2) End If SetAlpha 0.4 ' draw a stronger copy on the next position in line DrawImage(spriteimg:timage,oldcoord[3,0],oldcoord[3,1]) If average=True Then ' ETC. SetAlpha 0.5 DrawImage(spriteimg:timage,(oldcoord[3,0]+oldcoord[2,0])/2,(oldcoord[3,1]+oldcoord[2,1])/2) End If SetAlpha 0.6 DrawImage(spriteimg:timage,oldcoord[2,0],oldcoord[2,1]) If average=True Then SetAlpha 0.7 DrawImage(spriteimg:timage,(oldcoord[2,0]+oldcoord[1,0])/2,(oldcoord[2,1]+oldcoord[1,1])/2) End If SetAlpha 0.8 DrawImage(spriteimg:timage,oldcoord[1,0],oldcoord[1,1]) If average=True Then SetAlpha 0.9 DrawImage(spriteimg:timage,(oldcoord[1,0]+oldcoord[0,0])/2,(oldcoord[1,1]+oldcoord[0,1])/2) End If SetAlpha 1.0 ' Set the alpha to full again and draw the DrawImage(spriteimg:timage,oldcoord[0,0],oldcoord[0,1]) ' active sprite on top of the faded trail Flip ' Show everything If MouseDown(1) Then average=True ' Draw the averaged intermediate fades when the left mousebutton is held Else average=False ' Or don't draw them if the left mouse button is not pressed End If Wend |
| ||
Use the accumulation buffer in OpenGL, or grab the screen into a texture and then draw it with a 0.1 level of alpha in the next frame. |
| ||
I used what Raph suggested and I like the way it looks. I haven't found anything wrong with it yet either. |
| ||
As xlsior said, it might work fine for you, but some computers WILL have problems with it. |
| ||
Use the accumulation buffer in OpenGL, or grab the screen into a texture and then draw it with a 0.1 level of alpha in the next frame Which one is faster regarding performance? |
| ||
I used what Raph suggested and I like the way it looks. I haven't found anything wrong with it yet either. Not on your computer, but many others will have issues -- you'll get out-of-order flashing back between screens on some computers (e.g. rather than always seeing the previous screen, you may alternate between 1, 2 and 3 screens ago giving a really annoying flickering effect) or you may flicker between the previous screen and a black screen, etc. If you do want that method, you would need one more step to guarantee it works for everyone: createimage(background:TImage,graphicswidth(), graphicsheight()) ' Create an image to hold the current screen in setclscolor (0,0,0) while not keydown(key_escape) cls SetAlpha 0.8 DrawImage (background:Timage,0,0) SetAlpha 1.0 Drawimage MySprite,mousex(),mousey()' draw all your real current images now, and do the rest of your stuff ' GrabImage(background:Timage,0,0) ' Store a copy of the current screen in its final state, so we can redraw it later at a lower alpha flip wend This should look the same as what Ralph suggested, except that it will work on every computer since you make sure that you save and redraw the old content, rather than hoping that the video card saves it for you, and hoping that it only uses a single buffer to do so. The OpenGL and DX specs specifically state you cannot count on this being the case. |
| ||
xlsior: Is that supposed to be really slow? Because on my computer there almost isn't any movement. |
| ||
Thanks @xlsior for this! |