Rain effect

hey guys … just wanna know what are the ways/ideas to implement rain without using particle systems …  :?

Like the menu here:

http://rollarama.captiveimagination.com/

???

Instead of showing off, you could confess that you used a particle system for that too 

duenez said:

Instead of showing off, you could confess that you used a particle system for that too 


hahaha ! Seriously looks awesome your game Darkfrog. I like the way you browse through the menu  8)

oh yeah…I forgot I actually did end up using particles on that…I had another version that had rendered textures falling in layers in front of the camera…it looked pretty good but I never took the time to make it look really good.  Decided to give particles a shot and never went back.  I think layered textures would probably be more performant, but a much more manual process.

haha … no no … i meant instead of using particle systems to do the rain … any other ways ? can roughly give or suggest the idea of how it is done? the whole idea … haha please …  XD

I think darkfrog just gave you the idea 

ooppss … textures rendered in front of camera?!! cool … haha thankz darkfrag and orelero  :wink:



*btw the main menu plus the raining behind in the rollarama really looks nice!!!  :-o

Thanks…now if only the game was cooler. :o



Actually you can't even play the game anymore…the only reason I even leave it up is because of the cool menu. :slight_smile:

Hi wakaoz,



When you implemented this idea, can you give me some screenshot about that!



I really care of rain effect!



Thanks a lot!

if you hava source code  rain effect .please give me .

darkfrog said:

Like the menu here:
http://rollarama.captiveimagination.com/
???



I want to make rain effect.I use particle system .but do not same rain effect.can  you  give me idea of you.can you help me.thanks.



import javax.swing.ImageIcon;

import jmetest.curve.TestBezierCurve;
import jmetest.effects.RenParticleEditor;
import jmetest.terrain.TestTerrain;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.bounding.BoundingVolume;
import com.jme.curve.BezierCurve;
import com.jme.curve.CurveController;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.light.LightNode;
import com.jme.light.PointLight;
import com.jme.math.Plane;
import com.jme.math.Ring;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.scene.Controller;
import com.jme.scene.Skybox;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Cylinder;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;
import com.jme.util.geom.Debugger;
import com.jmex.effects.LensFlare;
import com.jmex.effects.LensFlareFactory;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleGeometry;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.effects.particles.SimpleParticleInfluenceFactory;
import com.jmex.effects.water.ProjectedGrid;
import com.jmex.effects.water.WaterHeightGenerator;
import com.jmex.effects.water.WaterRenderPass;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
import com.sun.corba.se.spi.legacy.connection.GetEndPointInfoAgainException;

public class hieuungparticle extends SimpleGame
{
   
    public static ParticleGeometry particleGeom;
   
       
   public static void main(String[] args)
   {
      hieuungparticle app=new hieuungparticle();
      app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
      app.start();
      
   }
   
      
   @Override
   protected void simpleInitGame()
   {
          Vector3f temp=new Vector3f();
          temp.x=cam.getLocation().x;
          temp.y=cam.getLocation().y;
          temp.z=cam.getLocation().z+100;
          cam.setLocation(temp);
   
      buildRain();

   }
private void buildRain()
   {
       particleGeom = ParticleFactory.buildParticles("Rain effect",1000);
         
         
           ZBufferState zbuff = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
          zbuff.setWritable(false);
          zbuff.setEnabled(true);
           zbuff.setFunction(ZBufferState.CF_LEQUAL);
           particleGeom.setRenderState(zbuff);
         
         
      
       
          

           AlphaState as = (AlphaState) particleGeom
                   .getRenderState(RenderState.RS_ALPHA);
           if (as == null) {
               as = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
               as.setBlendEnabled(true);
               as.setSrcFunction(AlphaState.SB_SRC_ALPHA);
               as.setTestEnabled(true);
               as.setTestFunction(AlphaState.TF_GREATER);
               particleGeom.setRenderState(as);
               particleGeom.updateRenderState();
           }
           as.setDstFunction(AlphaState.DB_ONE);
           TextureState ts = display.getRenderer().createTextureState();
           ts.setTexture(TextureManager.loadTexture(RenParticleEditor.class
                   .getClassLoader().getResource(
                           "jmetest/data/texture/flaresmall.jpg"),
                   Texture.FM_LINEAR, Texture.FM_LINEAR));
           particleGeom.setRenderState(ts);
          
          
           particleGeom.setEmissionDirection(new Vector3f(0.0f, 1.0f, 0.0f));
            particleGeom.setMaximumAngle(3.1415927f);
            particleGeom.setMinimumAngle(0);
            particleGeom.getParticleController().setSpeed(0.2f);
            particleGeom.setMinimumLifeTime(1626.0f);
            particleGeom.setMaximumLifeTime(2400.0f);
            particleGeom.setStartSize(10);
            particleGeom.setEndSize(15);
            particleGeom.setStartColor(new ColorRGBA(255.0f, 255.0f, 255.0f, 1.0f));
            particleGeom.setEndColor(new ColorRGBA(255.0f, 255.0f, 255.0f, 1.0f));
            particleGeom.getParticleController().setControlFlow(false);
         
          
            particleGeom.setInitialVelocity(0.2f);
          
            particleGeom.warmUp(120);
           particleGeom.addInfluence(SimpleParticleInfluenceFactory.createBasicGravity(new Vector3f(0, -40f, 0), true));
         
           Ring disk = new Ring(new Vector3f(500, 500, 200), Vector3f.UNIT_Y, 1, 1000);
           particleGeom.setGeometry(disk);
          
          
           rootNode.attachChild(particleGeom);
           particleGeom.updateRenderState();
   
   }
}


In my first approach I used textures in layers as well which looked OK for outdoor scenes. Then I had more and more buildings and it was so obvious when you entered a building or an open area under a roof because you can only switch on or off the effect for the whole screen.

Finally I used particles emitted by a ring above the camera and deleted the particles as soon as there is a collision. That way I stopped rain drops going through roofs. The diameter of the emitter and the speed of the rain drops need some tweaking but I found out that a relatively small radius is OK and you can hardly see that there is not really rain at a distance.

Sounds like the way i would like to make my own work - can you perhaps post a code-snippet to get me started? :slight_smile:

Yeah it would be great !  :stuck_out_tongue:

This is the class I used.



A word of warning though: I just copy and paste it. This is about two years old so it might not compile as is.



/*
 * Copyright (c) 2005-2006 World of Mystery Project Team
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package de.worldofmystery.client.effects;

import java.util.Properties;
import java.util.logging.Logger;

import com.jme.bounding.BoundingSphere;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Ring;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.effects.particles.Particle;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleInfluence;
import com.jmex.effects.particles.ParticleMesh;
import com.jmex.effects.particles.SimpleParticleInfluenceFactory;

import de.worldofmystery.client.Config;
import de.worldofmystery.client.world.Environment;

/**
 * a point particle effect for rain
 * @author galun
 * @version $Id: Rain.java,v 1.4 2006/11/11 22:23:29 galun Exp $
 */
public class Rain extends Node {

   private static final long serialVersionUID = -1057124936652689175L;
   private static Logger log = Logger.getLogger(Rain.class.getCanonicalName());
   private ParticleMesh points;
   private SimpleParticleInfluenceFactory.BasicGravity gravity;
   private boolean useGravity = false;

   public Rain(Properties prop) {
      super("rain");
      points = ParticleFactory.buildParticles("rainPoints", 1000, ParticleMesh.PT_QUAD);
      applyParameters(prop);
      if (useGravity) {
         gravity = (SimpleParticleInfluenceFactory.BasicGravity)SimpleParticleInfluenceFactory.createBasicGravity(new Vector3f(0, -1, 0), false);
         points.getParticleController().addInfluence(gravity);
      }
      points.addInfluence(new BoundInfluence());
      TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
        ts.setTexture(
                TextureManager.loadTexture(
                        Config.TEXTUREPATH + "/rain.dds",
                        Texture.MM_LINEAR,
                        Texture.FM_LINEAR));
        ts.setEnabled(true);
        points.setRenderState(ts);
      points.warmUp(10);
      attachChild(points);
        AlphaState as1 = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
        as1.setBlendEnabled(true);
        as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);
        as1.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
        as1.setTestEnabled(true);
        as1.setTestFunction(AlphaState.TF_GREATER);
        as1.setEnabled(true);
        points.setRenderState(as1);
        points.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
        points.setModelBound(new BoundingSphere());
        points.updateModelBound();
        points.setIsCollidable(false);
        ZBufferState zstate = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
      zstate.setEnabled(false);
//      setRenderState(zstate);
        setIsCollidable(false);
        updateRenderState();
   }

   public void applyParameters(Properties prop) {
        points.setGeometry(new Ring(new Vector3f(0, 0, 0), new Vector3f(0, 1, 0), 100,
              Float.parseFloat(prop.getProperty("radius", "1000"))));
      points.setNumParticles(Integer.parseInt(prop.getProperty("particles", "1000")));
      points.setEmissionDirection(new Vector3f(0, -1, 0));
      points.setOriginOffset(new Vector3f(0, 0, 0));
        points.setInitialVelocity(Float.parseFloat(prop.getProperty("velocity", "0.75f")));
        points.setParticleMass(Float.parseFloat(prop.getProperty("mass", "0.5f")));
        points.setStartSize(Float.parseFloat(prop.getProperty("startSize", "3")));
        points.setEndSize(Float.parseFloat(prop.getProperty("endSize", "3")));
        points.setMinimumLifeTime(Float.parseFloat(prop.getProperty("minLifeTime", "3500")));
        points.setMaximumLifeTime(Float.parseFloat(prop.getProperty("maxLifeTime", "5000")));
        points.setStartColor(parseColor(prop.getProperty("startColor", "0.6, 0.6, 0.6, 1")));
        points.setEndColor(parseColor(prop.getProperty("endColor", "0.6, 0.6, 0.6, 1")));
        points.setMaximumAngle(Float.parseFloat(prop.getProperty("maxAngle", "5f")) * FastMath.DEG_TO_RAD);
        points.getParticleController().setControlFlow(false);
        points.setLightCombineMode(LightState.OFF);
        if (gravity != null)
           gravity.setGravityForce(new Vector3f(0, Float.parseFloat(prop.getProperty("gravity", "-1")), 0));
        points.updateRenderState();
   }

   private ColorRGBA parseColor(String s) {
      ColorRGBA color = new ColorRGBA(ColorRGBA.white);
      try {
         float r = 1;
         float g = 1;
         float b = 1;
         float a = 1;
         String[] p = s.split(",\s+");
         r = Float.parseFloat(p[0]);
         if (p.length > 1)
            g = Float.parseFloat(p[1]);
         if (p.length > 2)
            b = Float.parseFloat(p[2]);
         if (p.length > 3)
            a = Float.parseFloat(p[3]);
         color.set(r, g, b, a);
      } catch (Exception ex) {
         log.warning("unparsable color: " + s + " (" + ex.toString() + ")");
      }
      return color;
   }

   class BoundInfluence extends ParticleInfluence {

      public void apply(float dt, Particle particle, int index) {
         if (Environment.getInstance().collides(particle.getPosition()))
            particle.setStatus(Particle.DEAD);
      }
      
   }
}

Never post code snippets without screenshots…that's just mean.  :stuck_out_tongue:

I noticed that out by the rain is nothing more than a visual effect for the camera. I wanted to see if it would be possible to make particles fall to the ground that to simulate erosion or the like. Anyone have any ideas to help me?

Erosion you mean like if you leave the game on for millions of years there will be a grand canyon? </irony>

Well, if you use physical simulated raindrops, and a terrain as surface, you could automatically lower it with every raindrop taht apsses a point on it there, however this will use with current hardware so much power, that not much more than a bucket of water is possible. (So either you find some intresting trick to do this, or you forget about this.)

Empire Phoenix said:

Erosion you mean like if you leave the game on for millions of years there will be a grand canyon?


have no idea if u intended that to be funny :D, but there is juice all over my monitor now...............thank you very much for that :x