Announcement

Collapse
No announcement yet.

TUT: Creating Rain + Snow + Fog in DarkPlaces

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • TUT: Creating Rain + Snow + Fog in DarkPlaces

    Dear all,

    Inspired by the great tutorials at inside3D, I wanted to try something like this as well.

    The fact that DarkPlaces also has beautiful weather features, has been overlooked by many people for a long time. Even some experienced DP-users have not been aware of it.
    Reason for it is that rain and snow in DP is not only engine coded but also QC coded “hidden” inside dpmod.
    Fog is available out of the box in DarkPlaces (no need to have dpmod code !).

    1.) Rain+Snow QC code
    First of all you must implement LordHavoc´s rain and snow code into regular Quake 1.06 QC.
    The only file you have to edit is “misc.qc”
    Add this to the very end:
    Code:
    // ============================================================================
    /*  Rain effect from dpmod
    */
    
    void() rain_think =
    {
    	self.nextthink = time + 0.1;
    	te_particlerain(self.absmin, self.absmax, self.dest, self.count, self.cnt);
    //	te_particlesnow(self.absmin, self.absmax, self.dest * 0.25, self.count, self.cnt);
    //	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
    //	WriteByte (MSG_BROADCAST, TE_PARTICLERAIN);
    //	WriteVec (MSG_BROADCAST, self.absmin);
    //	WriteVec (MSG_BROADCAST, self.absmax);
    //	WriteVec (MSG_BROADCAST, self.dest);
    //	WriteShort (MSG_BROADCAST, self.count);
    //	WriteByte (MSG_BROADCAST, self.cnt);
    };
    
    /*QUAKED func_rain (0 .5 .8) ?
    This is an invisible area like a trigger, which rain falls inside of.
    
    Keys:
    "velocity"
     falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
    "cnt"
     sets color of rain (default 12 - white)
    "count"
     adjusts rain density, this many particles fall every second, experiment to see the effects (default is based on area size)
    */
    void() func_rain =
    {
    	self.dest = self.velocity;
    	self.velocity = '0 0 0';
    	if (!self.dest)
    		self.dest = '0 0 -700';
    	self.angles = '0 0 0';
    	self.movetype = MOVETYPE_NONE;
    	self.solid = SOLID_NOT;
    	setmodel(self, self.model);
    	setorigin(self, self.origin);
    	setsize(self, self.mins, self.maxs);
    	self.model = "";
    	if (!self.cnt)
    		self.cnt = 12;
    	if (!self.count)
    		self.count = (self.absmax_x - self.absmin_x)*(self.absmax_y - self.absmin_y)/8192;
    	if (self.count < 1)
    	{
    		remove(self);
    		return;
    	}
    	// convert from per second to per 0.1 sec,
    	self.count = ceil(self.count * 0.1);
    	self.think = rain_think;
    	self.nextthink = time + 0.5;
    };
    
    // ============================================================================
    /*  Snow effect from dpmod
    */
    
    void() snow_think =
    {
    	self.nextthink = time + 0.1;
    	te_particlesnow(self.absmin, self.absmax, self.dest, self.count, self.cnt);
    //	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
    //	WriteByte (MSG_BROADCAST, TE_PARTICLESNOW);
    //	WriteVec (MSG_BROADCAST, self.absmin);
    //	WriteVec (MSG_BROADCAST, self.absmax);
    //	WriteVec (MSG_BROADCAST, self.dest);
    //	WriteShort (MSG_BROADCAST, self.count);
    //	WriteByte (MSG_BROADCAST, self.cnt);
    };
    
    /*QUAKED func_snow (0 .5 .8) ?
    This is an invisible area like a trigger, which snow falls inside of.
    
    Keys:
    "velocity"
     falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
    "cnt"
     sets color of rain (default 12 - white)
    "count"
     adjusts snow density, this many particles fall every second, experiment to see the effects (default is based on area size)
    */
    void() func_snow =
    {
    	self.dest = self.velocity;
    	self.velocity = '0 0 0';
    	if (!self.dest)
    		self.dest = '0 0 -300';
    	self.angles = '0 0 0';
    	self.movetype = MOVETYPE_NONE;
    	self.solid = SOLID_NOT;
    	setmodel(self, self.model);
    	setorigin(self, self.origin);
    	setsize(self, self.mins, self.maxs);
    	self.model = "";
    	if (!self.cnt)
    		self.cnt = 12;
    	if (!self.count)
    		self.count = (self.absmax_x - self.absmin_x)*(self.absmax_y - self.absmin_y)/8192;
    	if (self.count < 1)
    	{
    		remove(self);
    		return;
    	}
    	// convert from per second to per 0.1 sec,
    	self.count = ceil(self.count * 0.1);
    	self.think = snow_think;
    	self.nextthink = time + 0.5;
    };
    Now copy the file "dpextensions.qc" (from either dpmod source or find it in regular DP builds as well) to your QC folder.
    Open "progs.src" and write: dpextensions.qc after "defs.qc".
    Compile it and you get your "progs.dat" file (which you put into your ID1 folder).

    Alternatively you can also use my “small mod compilation” (I included the code into it), if you are not familiar with QC editing or compiling.
    I also added beautiful rain and thunder sounds into it.

    Now we have the possibility to have rain and snow in DarkPlaces.
    The only thing that is left is telling DP were it should fall and how it shall look like (continue with point 2.)


    2.) Creating .ent files for the rain and snow effect in maps
    It is mandatory to use an .ent file to have rain and snow in the maps.
    Reason: There is no in-game option to enable / disable weather effects in DarkPlaces.
    We have to tell DarkPlaces via the .ent file where and how the rain and snow shall fall and how it shall look like.

    2a) Creating an .ent file
    You first have to create the .ent file, which we will modify with rain or snow later on.
    Start your map (example: e1m1.bsp) and type: sv_saveentfile in the console.
    The e1m1.ent file is now in your maps folder (be careful, existing files will be overwritten).

    2b) Finding the area (coordinates) for the rain or snow to fall
    Fortunately LordHavoc gave us the tool with which we can do this in no time as a gift in DarkPlaces.
    We will misuse his RTLIGHTS Editor for it
    Type: r_editlights 1 in the console.
    A cursor will appear which will tell you exactly the X/Y/Z coordinates of everything you want.
    The weather code in DP needs to have the cube coordinates in which the rain or snow shall fall.
    The cube is defined by 2 coordinates: its 2 opposite corners.
    What you want to do now is to fly (with noclip) to the roof cutout and detect one corner of it (X2/Y2/Z2).
    Now fly to the opposite corner and detect (X1/Y1). The Z1 value is the lowest point (=floor) beneath the cutout,
    So fly down to the ground again and detect the Z1 coordinate.
    I named the XYZ coordinates (1 and 2) with purpose !
    You must always enter the low corner first, then the opposite upper corner.
    The cube coordinates which we will add into the .ent files should be slightly taller:
    X1 / Y1 / Z1-50 (= min)
    X2 / Y2 / Z2+20 (= max)

    2c) Declare the rain / snow properties
    Now all that is left to do is to tell DarkPlaces how the rain / snow shall look like and how it shall fall.
    - Velocity = X / Y / Z (standard should be for rain: 0/0/-700 ; for snow: 0/0/-100 (sometimes you must use Z=-190 to spawn snowflakes !))
    You can simulate wind as well, by using X or Y values other than 0.
    - Visual of rain/snow and rainfall/snowfall rate
    You have the “count” parameter and the “cnt” parameter for it.
    “count” is directly related to the size of the cube and declares the rainfall/snowfall rate. Standard for a medium cube should be (for rain: “4”; for snow: "10").
    In a small cube value “4” will have heavier rain than in a big cube with “4”.
    “cnt” declares the visual. Such as: color, thickness and transparency.
    My “cnt” favorite for rain is: “2”. (A value of “2” is realistic rain). For snow: "11".
    The bigger the value gets (until around “15”), the thicker, opaque and whiter the rain/snow gets.
    Values bigger than “15” brings colored rain/snow (example: red), which is maybe interesting for some hellish maps.

    The beautiful rain splashes (when the rain touches the floor or water surface) is part of the code and follows the params automatically.

    2d) Edit the .ent file
    Now you have everything you need and can edit your .ent file, which you created in 2a).
    Each cube has one block in the .ent file.
    If you have a complicated map geometry like in e1m1, you will need a lot of cubes to have the weather effect in all corners,
    and avoid rain/snow in the inside areas. It took me around 60 minutes to have beautiful rain in e1m1.
    Add the rain/snow blocks after the first block in the .ent file ! (You DON’T need a special rain/snow block order then)

    One block looks like this (example):
    For rain in e1m1:
    {
    "classname" "info_notnull"
    "mins" "-460 1730 -230"
    "maxs" "-84 500 200"
    "absmin" "-460 1730 -230"
    "absmax" "-84 500 200"
    "nextthink" "0.1"
    "think" "rain_think"
    "dest" "0 0 -700"
    "count" "4"
    "cnt" "2"
    }
    For snow in start.ent:
    {
    "classname" "info_notnull"
    "mins" "604 2108 -704"
    "maxs" "1618 2760 360"
    "absmin" "604 2108 -704"
    "absmax" "1618 2760 360"
    "nextthink" "0.1"
    "think" "snow_think"
    "dest" "0 0 -100"
    "count" "10"
    "cnt" "11"
    }
    Save it and you are done. Next time DarkPlaces starts, the .ent file will be used and you see the result.

    With a little exercise (after 1-2 maps) you will be able to create the .ent file in 20 minutes per map.
    Depending on the geometry of the roof cutouts or the outside area geometry.
    As mentioned above, in complicated maps it can take up to 60 minutes (or more) due to many necessary cubes.


    3.) Fog in DarkPlaces
    Of course you can add fog in the .ent file as well (independent if you have rain/snow blocks or not).
    Fog must be included in the end of first block and needs only one line (command).
    You do NOT need the rain/snow code to have fog in DarkPlaces (fog can be used out of the box) !

    Fog syntax is as follows:
    fog : set global fog parameters (density red green blue [alpha [mindist [maxdist [top [fadedepth]]]]])
    Fog example (for start.ent):
    {
    "sounds" "4"
    "classname" "worldspawn"
    "wad" "gfx/start.wad"
    "message" "Introduction"
    "worldtype" "0"
    "fog" ".3 .3 .25 .2 .6 20 2000 1500 30"
    }
    You can also have fog in DarkPlaces without an .ent file.
    Just bind the fog command to a key and enable/disable it whenever you want (example):
    bind f "fog .3 .3 .25 .2 .6 20 2000 1500 30"


    Enjoy the beautiful weather effects in DarkPlaces.
    …dont forget your umbrella
    And dont worry, it is easier than you think. I only wrote so much because I wanted to leave no open questions.

    I will add my own .ent files in the following post.

    Kind regards,
    Seven


    Sample shots: (for more shots see post #5+#25+#112)









    Last edited by Seven; 03-25-2013, 04:36 AM. Reason: Added snow code + screenshots

  • #2
    In this post I will put my own .ent files.

    I included all combination of rain / snow / ground fog .ent files in my pack.
    Throw them into your maps folder to use them (detailed readme is included).

    If you want to enable or disable rain and/or snow, use these cvars:
    cl_particles_rain
    cl_particles_snow


    Or disable complete .ent file usage via (not recommended):
    sv_entpatch


    You can bind these cvars to a key for your convenience.
    Be sure to "restart" the map to take effect.

    Kind regards,
    Seven
    .

    DOWNLOADS:
    Episode1_+_Episode2_+_Start__ent_files_from_Seven
    Episode3__ent_files_from_Roy_Batty
    Episode4__ent_files_from_daniocampo1992
    Last edited by Seven; 02-27-2014, 10:03 AM. Reason: reuploaded .ent files for Episode 1 + 2 + 3 + 4 + start

    Comment


    • #3
      Thanks for this Seven. Looks well explained. I will have to try one map when I have time this weekend.
      Regards

      Comment


      • #4
        I got the fog working thanks to seanstar & seven. It looks good. Will work on rain soon!

        Thanks
        Originally posted by Magnus
        Apology accepted.

        Comment


        • #5
          Dear all,

          I created more rainy .ent files for you.

          Now we have:
          - start (screens see 1st post)
          - e1m1 (screens see 1st post)
          - e1m2 (screens see below)
          - e1m3 (screen see 1st post)
          - e1m4 (screens see below)

          Updated Download link with all .ent files is in post #2.

          Hoping you like them...
          I would be happy if you write some feedback.

          Kind regards,
          Seven






          Last edited by Seven; 05-07-2011, 02:54 AM.

          Comment


          • #6
            Looks good but i have not much time atm for testing.

            Comment


            • #7
              Thanks Seven! They look great and play fine on my system. I'm going to have to get brave enough to try this and change rain color. I'm going to experiment with your files first.
              Thanks for all of your time and work on this!!!!!
              Regards

              Comment


              • #8
                Loving the rain Seven - as you already know
                I've made separate folders for "vanilla Quake/MP1/2" and a separate folder to run your mods.
                hipnotic7 which just has yours progs.dat in it - -hipnotic -game hipnotic7
                rogue7 same thing - -rogue -game rogue7
                then id7 - -game id7
                Works nicely

                Comment


                • #9
                  what is the performance hit on frames a second for everyone, with and without rain or fog
                  Want to get into playing Quake again? Click here for the Multiplayer-Startup kit! laissez bon temps rouler!

                  Comment


                  • #10
                    None for me.

                    Comment


                    • #11
                      Nice Seven, but the snow function should be included too, since everything is pretty much the same for snow and rain.
                      Here's the code required to add it . Just put it under the rain function.

                      The settings are the same as rain, but...
                      "think" = "snow_think"
                      and velocity should be something around -100.



                      Code:
                      // - Snow from DPMod
                      
                      void() snow_think =
                      {
                      	self.nextthink = time + 0.1;
                      	te_particlesnow(self.absmin, self.absmax, self.dest, self.count, self.cnt);
                      //	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
                      //	WriteByte (MSG_BROADCAST, TE_PARTICLESNOW);
                      //	WriteVec (MSG_BROADCAST, self.absmin);
                      //	WriteVec (MSG_BROADCAST, self.absmax);
                      //	WriteVec (MSG_BROADCAST, self.dest);
                      //	WriteShort (MSG_BROADCAST, self.count);
                      //	WriteByte (MSG_BROADCAST, self.cnt);
                      };
                      
                      /*QUAKED func_snow (0 .5 .8) ?
                      This is an invisible area like a trigger, which snow falls inside of.
                      
                      Keys:
                      "velocity"
                       falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
                      "cnt"
                       sets color of rain (default 12 - white)
                      "count"
                       adjusts snow density, this many particles fall every second, experiment to see the effects (default is based on area size)
                      */
                      void() func_snow =
                      {
                      	self.dest = self.velocity;
                      	self.velocity = '0 0 0';
                      	if (!self.dest)
                      		self.dest = '0 0 -300';
                      	self.angles = '0 0 0';
                      	self.movetype = MOVETYPE_NONE;
                      	self.solid = SOLID_NOT;
                      	setmodel(self, self.model);
                      	setorigin(self, self.origin);
                      	setsize(self, self.mins, self.maxs);
                      	self.model = "";
                      	if (!self.cnt)
                      		self.cnt = 12;
                      	if (!self.count)
                      		self.count = (self.absmax_x - self.absmin_x)*(self.absmax_y - self.absmin_y)/8192;
                      	if (self.count < 1)
                      	{
                      		remove(self);
                      		return;
                      	}
                      	// convert from per second to per 0.1 sec,
                      	self.count = ceil(self.count * 0.1);
                      	self.think = snow_think;
                      	self.nextthink = time + 0.5;
                      };

                      Comment


                      • #12
                        @ silverjoel

                        Yes, OoPpEe wanted to have snow as well and asked me to implement it.
                        So I did it already.
                        But the new final release of my "small mod compilation" is not yet released due to other topics.

                        I will soon extend the 1st post with "snow" as well, cause its almost identical to "rain".


                        @ Mindf!3ldzX
                        Thank you for this important question.
                        It depends on the hardware you have I guess.
                        My FPS behaviour is same this:
                        - FOG: Absolutely no FPS change
                        - RAIN: Between 10% and 30% less FPS (depends on map)


                        Kind regards,
                        Seven

                        Comment


                        • #13
                          @Seven I will look into making the rain/snow a cvar. So having to re-do some maps won't be needed. I will use the temp1 cvar.
                          Temp1 is a cvar that can be changed and it's ONLY purpose was for testing the player death animations see "void() Player_Die"
                          There's a part that has:

                          Code:
                          i = cvar("temp1");
                          	if (!i)
                          		i = 1 + floor(random()*6);
                          	
                          	if (i == 1)
                          		player_diea1();
                          	else if (i == 2)
                          		player_dieb1();
                          	else if (i == 3)
                          		player_diec1();
                          	else if (i == 4)
                          		player_died1();
                          	else
                          		player_diee1();
                          Just simply make the "i = cvar("temp1"); to "i = 0;"

                          Now it doesn't use the cvar and you can now use it on something else. In this case (if you send me your current source) - I will try to make the func_rain be rain if "temp1 = 0" and if it's "temp1 = 1" it will be snow. That way your current edits will be capable of being either snow or rain

                          Comment


                          • #14
                            What does the snow look like in DP? I know what it looks like in Telejano. How do they compare?

                            Comment


                            • #15
                              @ OoPpEe

                              Thank you for your idea, but it would not work i guess.
                              Reason:
                              If you only change the "think" from "rain_think" to "snow_think", it would look terrible.
                              At least these values / params must be changed as well:
                              - velocity
                              - count
                              - cnt

                              Example:
                              If you take a look into my e1m1.ent or e1m2.ent or e1m4.ent, you will see that even with simple rain, almost every block has a different "count" value.
                              Due to the fact, that "count" is directly depending on the cube size.
                              Of course, in theory it should follow the same rules with snow, but as you know, I am not a friend of automatic processes.
                              Handmade things are nicer compared to automatic process.
                              Just look at engines, that simulate a normal/bump texture to have offsetmapping.
                              Their result can never reach an engine that uses real handmade normal/bump textures.
                              So creating your own snow values instead of using the same as rain will always be nicer I guess.

                              But your idea is of course very good !

                              Lets make it this way:
                              After I made a couple of snowy maps and I will encounter the fact, that the snow values follow the same trend/behaviour as rain values, I will come back to you.
                              In that case we will surely find a way to change all 4 (above mentioned) values/params to have automatic snow/rain switch.


                              @ gdiddy62
                              I dont know.
                              Reason:
                              Snowy maps dont fit to ID1 or mission pack 1 / 2 maps in my opinion, so I never tried snow.
                              I will do it shortly and give you the .ent file.
                              Remember, screenshots can never show the beauty of dynamic things (like rain/snow/effectinfo.txt).

                              Regards,
                              Seven

                              Comment

                              Working...
                              X