• Home
  • Projects
  • About
  • Contact

The Old Snow Trick – In the Third Dimension

Devon O. · February 13, 2008 · Actionscript, Flash · 0 comments
2

While working on a little Valentine’s Day ecard for the most wonderful wife in the world, I suddenly had an idea…

Snow effects have been done in Flash since at least Flash 5 (maybe even Flash 4 if I think back hard enough), but I have yet to see a Flash snow storm in “true 3d”. Well, at least not until now. Seemed the new Particle API in Papervision3d was just the way to go for such a thing. Probably one of the oldest and nicest looking examples of snow in Flash, is the one presented on Kirupa.com. I really like the motion of that version, so borrowed a bit of the math for my own updated version. Also, I like the idea of using depth of field with papervision, so whilst borrowing, I boosted a bit of mrdoob’s “brute force” approach for depth of field. I didn’t go crazy with 200 textures though. I figured 4 were enough. No blur, a light blur, a medium blur, and a heavy blur. To be honest, you can’t really even notice the DOF anyway, but it’s there, and that’s all that matters. Add a little panorama and suddenly it’s snowing everywhere you look. Now, if I could just figure out how to keep the flakes from “sticking” to the camera, I’d have it made in the shade. I’m not sure if this is a clipping problem or what. If anyone knows why that happens, post a comment here and let me know.

The code for some snow:

ActionScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Snow in the Third Dimension (with some math from Kirupa.com)
* @author Devon O.
* @version 0.1
*/  
 
package {  
 
    import flash.display.BitmapData;
    import flash.display.GradientType;
    import flash.display.Sprite;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import org.papervision3d.cameras.FreeCamera3D;
    import org.papervision3d.materials.special.BitmapParticleMaterial;
    import org.papervision3d.view.BasicView;  
 
    import flash.events.Event;  
 
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.core.geom.Particles;
    import org.papervision3d.core.geom.renderables.Particle;  
 
    public class Snow3d extends BasicView  {  
 
        private var snowHolder:DisplayObject3D;
        private var flakes:Array;
        private const NUM_FLAKES:int = 300;
        private var cam:FreeCamera3D;  
 
        private var noBlurFlake:BitmapData;
        private var ltBlurFlake:BitmapData;
        private var medBlurFlake:BitmapData;
        private var heavyBlurFlake:BitmapData;  
 
        public function Snow3d() {
            super(stage.stageWidth, stage.stageHeight, true, false, FreeCamera3D.TYPE);
            init();
        }  
 
        private function init():void {
            cam = cameraAsFreeCamera3D;
            cam.zoom = 1;
            cam.focus = 400;
            cam.z = 10;  
 
            createBitmaps();  
 
            snowHolder = new DisplayObject3D("snow_holder");
            flakes = new Array();  
 
            for(var i:int = 0; i < NUM_FLAKES; i++) {  
 
                var mat:BitmapParticleMaterial = new BitmapParticleMaterial(noBlurFlake);
                mat.smooth = true;  
 
                var flakeHolder:Particles = new Particles("flake" + i);
                var flake:Particle = new Particle(mat, 10, 0, 0, 0);  
 
                flakeHolder.addParticle(flake);  
 
                flakeHolder.x = randRange(-2000, 2000);
                flakeHolder.y = randRange(-2000, 2000);
                flakeHolder.z = randRange( -2000, 2000);  
 
                flakeHolder.extra = { radians: 0, I:randRange(2, 8), K: (-Math.PI + Math.random() * Math.PI), noblur: new BitmapParticleMaterial(noBlurFlake), blur1: new BitmapParticleMaterial(ltBlurFlake),  blur2: new BitmapParticleMaterial(medBlurFlake), blur3: new BitmapParticleMaterial(heavyBlurFlake) };  
 
                snowHolder.addChild(flakeHolder);
                flakes.push(flakeHolder);
            }  
 
            scene.addChild(snowHolder);  
 
            singleRender();  
 
            addEventListener(Event.ENTER_FRAME, enterFrame);
        }  
 
        private function createBitmaps():void {
            var lightBlur:BlurFilter = new BlurFilter(4, 4, 1);
            var medBlur:BlurFilter = new BlurFilter (8, 8, 1);
            var heavyBlur:BlurFilter = new BlurFilter(16, 16, 1);  
 
            var type:String = GradientType.RADIAL;
            var colors:Array = [0xFFFFFF, 0xFFFFFF, 0xFFFFFF];
            var alphas:Array = [1, .1, 0];
            var ratios:Array = [0, 200, 255];
            var mat:Matrix = new Matrix();
            mat.createGradientBox(10, 10);  
 
            var baseFlake:Sprite = new Sprite();
            baseFlake.graphics.beginGradientFill(type, colors, alphas, ratios, mat);
            baseFlake.graphics.drawCircle(5, 5, 5);
            baseFlake.graphics.endFill();  
 
            noBlurFlake = new BitmapData(10, 10, true, 0x00000000);
            noBlurFlake.draw(baseFlake);  
 
            ltBlurFlake = new BitmapData(10, 10, true, 0x00000000);
            ltBlurFlake.draw(baseFlake);
            ltBlurFlake.applyFilter(ltBlurFlake, baseFlake.getBounds(baseFlake), new Point(), lightBlur);  
 
            medBlurFlake = new BitmapData(10, 10, true, 0x00000000);
            medBlurFlake.draw(baseFlake);
            medBlurFlake.applyFilter(medBlurFlake, baseFlake.getBounds(baseFlake), new Point(), medBlur);  
 
            heavyBlurFlake = new BitmapData(10, 10, true, 0x00000000);
            heavyBlurFlake.draw(baseFlake);
            heavyBlurFlake.applyFilter(heavyBlurFlake, baseFlake.getBounds(baseFlake), new Point(), heavyBlur);
        }  
 
        function enterFrame(e:Event):void {  
 
            var pan:Number = cam.rotationY - 210 * stage.mouseX / (stage.stageWidth/2);
            pan = Math.max( -100, Math.min( pan, 100 ) );
            cam.rotationY -= pan / 12;  
 
            var len:int = flakes.length;  
 
            for(var i:int = 0; i < len; i++) {
                var p:Particles = flakes[i];  
 
                if (Math.abs(p.sceneZ) <= 100) {
                        p.particles[0].material = p.extra["noblur"]
                }
                if (Math.abs(p.sceneZ) >= 101 && Math.abs(p.z) <= 200) {
                    p.particles[0].material = p.extra["blur1"]
                }
                if (Math.abs(p.sceneZ) >= 201 && Math.abs(p.z) <= 300) {
                    p.particles[0].material = p.extra["blur2"]
                }
                if (Math.abs(p.sceneZ) >= 301) {
                    p.particles[0].material = p.extra["blur3"]
                }  
 
                p.extra["radians"] += (p.extra["K"] / 180) * Math.PI;
                p.x -= 3 * (Math.cos(p.extra["radians"]));
                p.z -= 3 * (Math.sin(p.extra["radians"]));
                p.y -= p.extra["I"];
                if (p.y < -2000) {
                    p.y = 2000;
                    p.x = randRange(-2000, 2000);
                    p.z = randRange( -2000, 2000);  
 
                    p.extra["I"] = randRange(2, 8);
                }
            }  
 
            singleRender();
        }  
 
        private function randRange(min:Number, max:Number):Number {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        }
    }
}

And an example (with panorama):

  Facebook   Pinterest   Twitter   Google+
  • Active Window(S) Blur
    July 06, 2008 · 12 comments
    2592
    2
    Read more
  • Update to Website Generation Tool
    May 03, 2009 · 7 comments
    1652
    2
    Read more
  • Digging into the Microphone in Flash Player 10.1
    January 30, 2010 · 39 comments
    8927
    5
    Read more

Sorry, the comment form is closed at this time.

Devon O. Wolfgang

AIR | Unity3D | AR/VR

Unity Certified Developer

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development” and “Starling Game Development Essentials”

Reviewer of “The Starling Handbook”

Unity Engineer at Touch Press.

Categories
  • Actionscript (95)
  • AIR (16)
  • Flash (99)
  • Games (7)
  • Liberty (13)
  • Life (52)
  • Shaders (20)
  • Unity3D (19)
Recent Comments
  • onebyonedesign » Custom Post Processing with the LWRP on Unity Ripple or Shock Wave Effect
  • Devon O. on Unity Ripple or Shock Wave Effect
  • Elias on Unity Ripple or Shock Wave Effect
  • math games on Particle Editor for Starling Framework
  • Sean on Unity Ripple or Shock Wave Effect
Archives
  • September 2019 (1)
  • February 2019 (2)
  • December 2018 (1)
  • July 2018 (1)
  • June 2018 (1)
  • May 2018 (2)
  • January 2018 (1)
  • December 2017 (2)
  • October 2017 (1)
  • September 2017 (2)
  • January 2017 (1)
  • July 2016 (1)
  • December 2015 (2)
  • March 2015 (1)
  • September 2014 (1)
  • January 2014 (1)
  • August 2013 (1)
  • July 2013 (1)
  • May 2013 (1)
  • March 2013 (2)
  • December 2012 (1)
  • November 2012 (1)
  • September 2012 (3)
  • June 2012 (2)
  • May 2012 (1)
  • April 2012 (1)
  • December 2011 (2)
  • October 2011 (3)
  • September 2011 (1)
  • August 2011 (1)
  • July 2011 (1)
  • May 2011 (2)
  • April 2011 (2)
  • March 2011 (1)
  • February 2011 (1)
  • January 2011 (2)
  • December 2010 (3)
  • October 2010 (5)
  • September 2010 (1)
  • July 2010 (2)
  • May 2010 (5)
  • April 2010 (2)
  • March 2010 (7)
  • February 2010 (5)
  • January 2010 (5)
  • December 2009 (3)
  • November 2009 (1)
  • October 2009 (5)
  • September 2009 (5)
  • August 2009 (1)
  • July 2009 (1)
  • June 2009 (2)
  • May 2009 (6)
  • April 2009 (4)
  • March 2009 (2)
  • February 2009 (4)
  • January 2009 (1)
  • December 2008 (5)
  • November 2008 (2)
  • September 2008 (1)
  • August 2008 (6)
  • July 2008 (6)
  • June 2008 (9)
  • May 2008 (4)
  • April 2008 (3)
  • March 2008 (4)
  • February 2008 (9)
  • January 2008 (7)
  • December 2007 (6)
Copyright © 2017 Devon O. Wolfgang