diff --git a/src/Environment/Makefile.am b/src/Environment/Makefile.am
index a16996170..3661e5041 100644
--- a/src/Environment/Makefile.am
+++ b/src/Environment/Makefile.am
@@ -8,6 +8,6 @@ libEnvironment_a_SOURCES = \
 	environment.cxx environment.hxx \
 	environment_mgr.cxx environment_mgr.hxx \
 	environment_ctrl.cxx environment_ctrl.hxx \
-	fgmetar.cxx fgmetar.hxx
+	fgmetar.cxx fgmetar.hxx fgclouds.cxx fgclouds.hxx
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
diff --git a/src/Environment/environment.cxx b/src/Environment/environment.cxx
index 2448ec3ed..6a607bba0 100644
--- a/src/Environment/environment.cxx
+++ b/src/Environment/environment.cxx
@@ -36,6 +36,7 @@
 #include <simgear/constants.h>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/interpolater.hxx>
+#include <simgear/environment/visual_enviro.hxx>
 
 #include <Main/fg_props.hxx>
 #include "environment.hxx"
@@ -297,6 +298,9 @@ FGEnvironment::get_wind_from_down_fps () const
 double
 FGEnvironment::get_turbulence_magnitude_norm () const
 {
+  if( sgEnviro.get_turbulence_enable_state() )
+    if (fgGetBool("/environment/params/real-world-weather-fetch") == true)
+      return sgEnviro.get_cloud_turbulence();
   return turbulence_magnitude_norm;
 }
 
diff --git a/src/Environment/environment_ctrl.cxx b/src/Environment/environment_ctrl.cxx
index 4a7b24732..9872c6d0c 100644
--- a/src/Environment/environment_ctrl.cxx
+++ b/src/Environment/environment_ctrl.cxx
@@ -494,6 +494,7 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
         result_queue.pop();
         if ( result.m != NULL ) {
             update_metar_properties( result.m );
+            fgSetString("/environment/metar/last-metar", result.m->getData());
             delete result.m;
             update_env_config();
             env->reinit();
diff --git a/src/Environment/environment_mgr.cxx b/src/Environment/environment_mgr.cxx
index 9dc036242..dc56ec0e8 100644
--- a/src/Environment/environment_mgr.cxx
+++ b/src/Environment/environment_mgr.cxx
@@ -31,7 +31,7 @@
 #include "environment.hxx"
 #include "environment_ctrl.hxx"
 #include "environment_mgr.hxx"
-
+#include "fgclouds.hxx"
 
 class SGSky;
 extern SGSky *thesky;
@@ -49,12 +49,14 @@ FGEnvironmentMgr::FGEnvironmentMgr ()
 
   _controller->setEnvironment(_environment);
   set_subsystem("controller", _controller, 0.5);
+  fgClouds = new FGClouds;
 }
 
 FGEnvironmentMgr::~FGEnvironmentMgr ()
 {
   delete _environment;
   delete _controller;
+  delete fgClouds;
 }
 
 void
@@ -171,6 +173,15 @@ FGEnvironmentMgr::bind ()
   fgTie("/sim/rendering/precipitation-enable", &sgEnviro,
 	  &SGEnviro::get_precipitation_enable_state,
 	  &SGEnviro::set_precipitation_enable_state);
+  fgTie("/environment/rebuild_layers", fgClouds,
+      &FGClouds::get_update_event,
+      &FGClouds::set_update_event);
+  fgTie("/sim/rendering/lightning-enable", &sgEnviro,
+      &SGEnviro::get_lightning_enable_state,
+      &SGEnviro::set_lightning_enable_state);
+  fgTie("/environment/turbulence/use-cloud-turbulence", &sgEnviro,
+      &SGEnviro::get_turbulence_enable_state,
+      &SGEnviro::set_turbulence_enable_state);
 }
 
 void
@@ -200,6 +211,15 @@ FGEnvironmentMgr::unbind ()
     sprintf(buf, "/environment/clouds/layer[%d]/type", i);
     fgUntie(buf);
   }
+  fgUntie("/sim/rendering/clouds3d-enable");
+  fgUntie("/sim/rendering/clouds3d-vis-range");
+  fgUntie("/sim/rendering/clouds3d-density");
+  fgUntie("/sim/rendering/clouds3d-cache-size");
+  fgUntie("/sim/rendering/clouds3d-cache-resolution");
+  fgUntie("/sim/rendering/precipitation-enable");
+  fgUntie("/environment/rebuild_layers");
+  fgUntie("/sim/rendering/lightning-enable");
+  fgUntie("/environment/turbulence/use-cloud-turbulence");
 }
 
 void
diff --git a/src/Environment/environment_mgr.hxx b/src/Environment/environment_mgr.hxx
index abef848f5..ff0111afe 100644
--- a/src/Environment/environment_mgr.hxx
+++ b/src/Environment/environment_mgr.hxx
@@ -34,7 +34,7 @@
 
 class FGEnvironment;
 class FGEnvironmentCtrl;
-
+class FGClouds;
 
 /**
  * Manage environment information.
@@ -87,6 +87,7 @@ private:
   FGEnvironment * _environment;	// always the same, for now
   FGEnvironmentCtrl * _controller; // always the same, for now
 
+  FGClouds *fgClouds;
 };
 
 #endif // _ENVIRONMENT_MGR_HXX
diff --git a/src/Environment/fgclouds.cxx b/src/Environment/fgclouds.cxx
new file mode 100644
index 000000000..022a1a4bc
--- /dev/null
+++ b/src/Environment/fgclouds.cxx
@@ -0,0 +1,442 @@
+// Build a cloud layer based on metar
+//
+// Written by Harald JOHNSEN, started April 2005.
+//
+// Copyright (C) 2005  Harald JOHNSEN - hjohnsen@evc.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+//
+//
+
+#include <Main/fg_props.hxx>
+
+#include <simgear/constants.h>
+#include <simgear/sound/soundmgr_openal.hxx>
+#include <simgear/scene/sky/sky.hxx>
+#include <simgear/environment/visual_enviro.hxx>
+#include <simgear/scene/sky/cloudfield.hxx>
+#include <simgear/scene/sky/newcloud.hxx>
+#include <simgear/math/sg_random.h>
+#include <Main/globals.hxx>
+#include <Airports/simple.hxx>
+#include <Main/util.hxx>
+
+#include "environment_mgr.hxx"
+#include "fgmetar.hxx"
+#include "fgclouds.hxx"
+
+extern SGSky *thesky;
+
+
+FGClouds::FGClouds() :
+	station_elevation_ft(0.0),
+	snd_lightning(NULL)
+{
+	update_event = 0;
+	fgSetString("/environment/weather-scenario", "METAR");
+}
+FGClouds::~FGClouds() {
+}
+
+int FGClouds::get_update_event(void) const {
+	return update_event;
+}
+void FGClouds::set_update_event(int count) {
+	update_event = count;
+	build();
+}
+
+void FGClouds::init(void) {
+	if( snd_lightning == NULL ) {
+		snd_lightning = new SGSoundSample(globals->get_fg_root().c_str(), "Sounds/thunder.wav", true);
+		snd_lightning->set_max_dist(7000.0f);
+		snd_lightning->set_reference_dist(3000.0f);
+		SGSoundMgr *soundMgr = globals->get_soundmgr();
+		soundMgr->add( snd_lightning, "thunder" );
+		sgEnviro.set_soundMgr( soundMgr );
+	}
+}
+
+SGNewCloud *FGClouds::buildCloud(SGPropertyNode *cloud_def_root, string name) {
+	SGPropertyNode *cld_def=NULL;
+
+	cld_def = cloud_def_root->getChild(name.c_str());
+	string base_name = name.substr(0,2);
+	if( !cld_def ) {
+		if( name[2] == '-' ) {
+			cld_def = cloud_def_root->getChild(base_name.c_str());
+		}
+		if( !cld_def )
+			return NULL;
+	}
+	string familly = cld_def->getStringValue("familly", base_name.c_str());
+	SGNewCloud *cld = new SGNewCloud(familly);
+	for(int i = 0; i < cld_def->nChildren() ; i++) {
+		SGPropertyNode *abox = cld_def->getChild(i);
+		if( strcmp(abox->getName(), "box") == 0) {
+			double x = abox->getDoubleValue("x");
+			double y = abox->getDoubleValue("y");
+			double z = abox->getDoubleValue("z");
+			double size = abox->getDoubleValue("size");
+			int type = abox->getIntValue("type", SGNewCloud::CLbox_standard);
+			cld->addContainer(x, y, z, size, (SGNewCloud::CLbox_type) type);
+		}
+	}
+	cld->genSprites();
+	return cld;
+}
+
+void FGClouds::buildLayer(SGCloudField *layer, string name, double alt, double coverage) {
+	struct {
+		string name;
+		double count;
+	} tCloudVariety[20];
+	int CloudVarietyCount = 0;
+	double totalCount = 0.0;
+
+	SGPropertyNode *cloud_def_root = fgGetNode("/environment/config/cloudlayers/clouds", false);
+	SGPropertyNode *layer_def_root = fgGetNode("/environment/config/cloudlayers/layers", false);
+
+	layer->clear();
+	// when we don't generate clouds the layer is rendered in 2D
+	if( coverage == 0.0 )
+		return;
+	if( layer_def_root == NULL || cloud_def_root == NULL)
+		return;
+	if( name == "ci" || name == "sc" || name == "st")
+		return;
+
+	SGPropertyNode *layer_def=NULL;
+
+	layer_def = layer_def_root->getChild(name.c_str());
+	if( !layer_def ) {
+		if( name[2] == '-' ) {
+			string base_name = name.substr(0,2);
+			layer_def = layer_def_root->getChild(base_name.c_str());
+		}
+		if( !layer_def )
+			return;
+	}
+
+	double grid_x_size = layer_def->getDoubleValue("grid-x-size", 1000.0);
+	double grid_y_size = layer_def->getDoubleValue("grid-y-size", 1000.0);
+	double grid_x_rand = layer_def->getDoubleValue("grid-x-rand", grid_x_size);
+	double grid_y_rand = layer_def->getDoubleValue("grid-y-rand", grid_y_size);
+	double grid_z_rand = layer_def->getDoubleValue("grid-z-rand");
+
+	for(int i = 0; i < layer_def->nChildren() ; i++) {
+		SGPropertyNode *acloud = layer_def->getChild(i);
+		if( strcmp(acloud->getName(), "cloud") == 0) {
+			string cloud_name = acloud->getStringValue("name");
+			tCloudVariety[CloudVarietyCount].name = cloud_name;
+			double count = acloud->getDoubleValue("count", 1.0);
+			tCloudVariety[CloudVarietyCount].count = count;
+			int variety = 0;
+			cloud_name = cloud_name + "-%d";
+			char variety_name[50];
+			do {
+				variety++;
+				snprintf(variety_name, sizeof(variety_name), cloud_name.c_str(), variety);
+			} while( cloud_def_root->getChild(variety_name, 0, false) );
+
+			totalCount += count;
+			if( CloudVarietyCount < 20 )
+				CloudVarietyCount++;
+		}
+	}
+	totalCount = 1.0 / totalCount;
+	double currCoverage = 0.0;
+
+	for(double px = 0.0; px < SGCloudField::fieldSize; px += grid_x_size) {
+		for(double py = 0.0; py < SGCloudField::fieldSize; py += grid_y_size) {
+			double x = px + grid_x_rand * (sg_random() - 0.5);
+			double y = py + grid_y_rand * (sg_random() - 0.5);
+			double z = alt + grid_z_rand * (sg_random() - 0.5);
+			double choice = sg_random();
+			currCoverage += coverage;
+			if( currCoverage < 1.0 )
+				continue;
+			currCoverage -= 1.0;
+
+			for(int i = 0; i < CloudVarietyCount ; i ++) {
+				choice -= tCloudVariety[i].count * totalCount;
+				if( choice <= 0.0 ) {
+					SGNewCloud *cld = buildCloud(cloud_def_root, tCloudVariety[i].name);
+					sgVec3 pos={x,z,y};
+					if( cld )
+						layer->addCloud(pos, cld);
+
+					break;
+				}
+			}
+		}
+	}
+
+}
+
+// TODO:call this after real metar updates
+void FGClouds::buildMETAR(void) {
+	SGPropertyNode *metar_root = fgGetNode("/environment", true);
+
+	double wind_speed_kt	 = metar_root->getDoubleValue("wind-speed-kt");
+	double temperature_degc  = metar_root->getDoubleValue("temperature-sea-level-degc");
+	double dewpoint_degc	 = metar_root->getDoubleValue("dewpoint-sea-level-degc");
+	double pressure_mb		= metar_root->getDoubleValue("pressure-sea-level-inhg") * SG_INHG_TO_PA / 100.0;
+
+	double dewp = pow(10.0, 7.5 * dewpoint_degc / (237.7 + dewpoint_degc));
+	double temp = pow(10.0, 7.5 * temperature_degc / (237.7 + temperature_degc));
+	double rel_humidity = dewp * 100 / temp;
+
+	// formule d'Epsy, base d'un cumulus
+	double cumulus_base = 122.0 * (temperature_degc - dewpoint_degc);
+	double stratus_base = 100.0 * (100.0 - rel_humidity) * SG_FEET_TO_METER;
+
+	bool cu_seen = false;
+
+	for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {
+		SGPropertyNode *cloud_root = fgGetNode("/environment/clouds/layer", iLayer, true);
+
+		double alt_ft = cloud_root->getDoubleValue("elevation-ft");
+		double alt_m = alt_ft * SG_FEET_TO_METER;
+		string coverage = cloud_root->getStringValue("coverage");
+		double coverage_norm = 0.0;
+		if( coverage == "few" )
+			coverage_norm = 2.0/8.0;	// <1-2
+		else if( coverage == "scattered" )
+			coverage_norm = 4.0/8.0;	// 3-4
+		else if( coverage == "broken" )
+			coverage_norm = 6.0/8.0;	// 5-7
+		else if( coverage == "overcast" )
+			coverage_norm = 8.0/8.0;	// 8
+
+		string layer_type = "nn";
+		if( coverage == "cirrus" ) {
+			layer_type = "ci";
+		} else if( alt_ft > 16500 ) {
+//			layer_type = "ci|cs|cc";
+			layer_type = "ci";
+		} else if( alt_ft > 6500 ) {
+//			layer_type = "as|ac|ns";
+			layer_type = "ac";
+			if( pressure_mb < 1005.0 && coverage_norm >= 5.5 )
+				layer_type = "ns";
+		} else {
+//			layer_type = "st|cu|cb|sc";
+			// +/- 20% from stratus probable base
+			if( stratus_base * 0.80 < alt_m && stratus_base * 1.40 > alt_m )
+				layer_type = "st";
+			// +/- 20% from cumulus probable base
+			else if( cumulus_base * 0.80 < alt_m && cumulus_base * 1.20 > alt_m )
+				layer_type = "cu";
+			else {
+				// above formulae is far from perfect
+				if ( alt_ft < 2000 )
+					layer_type = "st";
+				else if( alt_ft < 4500 )
+					layer_type = "cu";
+				else
+					layer_type = "sc";
+			}
+		}
+
+		SGCloudField *layer3D = thesky->get_cloud_layer(iLayer)->get_layer3D();
+		buildLayer(layer3D, layer_type, alt_m, coverage_norm);
+	}
+}
+
+// copy from FGMetarEnvironmentCtrl until better
+void
+FGClouds::update_metar_properties( FGMetar *m )
+{
+    int i;
+    double d;
+    char s[128];
+
+    fgSetString("/environment/metar/station-id", m->getId());
+    fgSetDouble("/environment/metar/min-visibility-m",
+                m->getMinVisibility().getVisibility_m() );
+    fgSetDouble("/environment/metar/max-visibility-m",
+                m->getMaxVisibility().getVisibility_m() );
+
+    SGMetarVisibility *dirvis = m->getDirVisibility();
+    for (i = 0; i < 8; i++, dirvis++) {
+        const char *min = "/environment/metar/visibility[%d]/min-m";
+        const char *max = "/environment/metar/visibility[%d]/max-m";
+
+        d = dirvis->getVisibility_m();
+
+        snprintf(s, 128, min, i);
+        fgSetDouble(s, d);
+        snprintf(s, 128, max, i);
+        fgSetDouble(s, d);
+    }
+
+    fgSetInt("/environment/metar/base-wind-range-from",
+             m->getWindRangeFrom() );
+    fgSetInt("/environment/metar/base-wind-range-to",
+             m->getWindRangeTo() );
+    fgSetDouble("/environment/metar/base-wind-speed-kt",
+                m->getWindSpeed_kt() );
+    fgSetDouble("/environment/metar/gust-wind-speed-kt",
+                m->getGustSpeed_kt() );
+    fgSetDouble("/environment/metar/temperature-degc",
+                m->getTemperature_C() );
+    fgSetDouble("/environment/metar/dewpoint-degc",
+                m->getDewpoint_C() );
+    fgSetDouble("/environment/metar/rel-humidity-norm",
+                m->getRelHumidity() );
+    fgSetDouble("/environment/metar/pressure-inhg",
+                m->getPressure_inHg() );
+
+    vector<SGMetarCloud> cv = m->getClouds();
+    vector<SGMetarCloud>::iterator cloud;
+
+    const char *cl = "/environment/clouds/layer[%i]";
+    for (i = 0, cloud = cv.begin(); cloud != cv.end(); cloud++, i++) {
+        const char *coverage_string[5] = 
+            { "clear", "few", "scattered", "broken", "overcast" };
+        const double thickness[5] = { 0, 65, 600,750, 1000};
+        int q;
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/coverage", 128);
+        q = cloud->getCoverage();
+        fgSetString(s, coverage_string[q] );
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/elevation-ft", 128);
+        fgSetDouble(s, cloud->getAltitude_ft() + station_elevation_ft);
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/thickness-ft", 128);
+        fgSetDouble(s, thickness[q]);
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/span-m", 128);
+        fgSetDouble(s, 40000.0);
+    }
+
+    for (; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
+        snprintf(s, 128, cl, i);
+        strncat(s, "/coverage", 128);
+        fgSetString(s, "clear");
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/elevation-ft", 128);
+        fgSetDouble(s, -9999);
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/thickness-ft", 128);
+        fgSetDouble(s, 0);
+
+        snprintf(s, 128, cl, i);
+        strncat(s, "/span-m", 128);
+        fgSetDouble(s, 40000.0);
+    }
+
+    fgSetDouble("/environment/metar/rain-norm", m->getRain());
+    fgSetDouble("/environment/metar/hail-norm", m->getHail());
+    fgSetDouble("/environment/metar/snow-norm", m->getSnow());
+    fgSetBool("/environment/metar/snow-cover", m->getSnowCover());
+}
+
+void
+FGClouds::update_env_config ()
+{
+    fgSetupWind( fgGetDouble("/environment/metar/base-wind-range-from"),
+                 fgGetDouble("/environment/metar/base-wind-range-to"),
+                 fgGetDouble("/environment/metar/base-wind-speed-kt"),
+                 fgGetDouble("/environment/metar/gust-wind-speed-kt") );
+
+    fgDefaultWeatherValue( "visibility-m",
+                           fgGetDouble("/environment/metar/min-visibility-m") );
+#if 0
+    set_temp_at_altitude( fgGetDouble("/environment/metar/temperature-degc"),
+                          station_elevation_ft );
+    set_dewpoint_at_altitude( fgGetDouble("/environment/metar/dewpoint-degc"),
+                              station_elevation_ft );
+#endif
+    fgDefaultWeatherValue( "pressure-sea-level-inhg",
+                           fgGetDouble("/environment/metar/pressure-inhg") );
+}
+
+
+void FGClouds::setLayer( int iLayer, float alt_ft, string coverage, string layer_type ) {
+	double coverage_norm = 0.0;
+	if( coverage == "few" )
+		coverage_norm = 2.0/8.0;	// <1-2
+	else if( coverage == "scattered" )
+		coverage_norm = 4.0/8.0;	// 3-4
+	else if( coverage == "broken" )
+		coverage_norm = 6.0/8.0;	// 5-7
+	else if( coverage == "overcast" )
+		coverage_norm = 8.0/8.0;	// 8
+
+	SGCloudField *layer3D = thesky->get_cloud_layer(iLayer)->get_layer3D();
+	buildLayer(layer3D, layer_type, station_elevation_ft + alt_ft * SG_FEET_TO_METER, coverage_norm);
+}
+
+void FGClouds::buildScenario( string scenario ) {
+	string fakeMetar="";
+	string station = fgGetString("/environment/metar/station-id", "XXXX");
+
+	// fetch station elevation if exists
+    FGAirport a = globals->get_airports()->search( station );
+    station_elevation_ft = a.getElevation();
+
+	for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {
+		thesky->get_cloud_layer(iLayer)->get_layer3D()->clear();
+	}
+
+	station += " 011000Z ";
+	if( scenario == "Fair weather" ) {
+		fakeMetar = "15003KT 12SM SCT033 FEW200 20/08 Q1015 NOSIG";
+		setLayer(0, 3300.0, "scattered", "cu");
+	} else if( scenario == "Thunderstorm" ) {
+		fakeMetar = "15012KT 08SM TSRA SCT040 BKN070 20/12 Q0995";
+		setLayer(0, 4000.0, "scattered", "cb");
+		setLayer(1, 7000.0, "scattered", "ns");
+	} else 
+		return;
+	FGMetar *m = new FGMetar( station + fakeMetar );
+	update_metar_properties( m );
+	update_env_config();
+	fgSetString("/environment/metar/last-metar", m->getData());
+	// TODO:desactivate real metar updates
+	if( scenario == "Fair weather" ) {
+		fgSetString("/environment/clouds/layer[1]/coverage", "cirrus");
+	}
+}
+
+
+void FGClouds::build(void) {
+	string scenario = fgGetString("/environment/weather-scenario", "METAR");
+
+	if( scenario == "METAR" ) {
+		string realMetar = fgGetString("/environment/metar/last-metar", "");
+		if( realMetar != "" ) {
+			FGMetar *m = new FGMetar( realMetar );
+			update_metar_properties( m );
+			update_env_config();
+		}
+		buildMETAR();
+	}
+	else
+		buildScenario( scenario );
+
+	// ...
+	if( snd_lightning == NULL )
+		init();
+}
diff --git a/src/Environment/fgclouds.hxx b/src/Environment/fgclouds.hxx
new file mode 100644
index 000000000..dee821c1d
--- /dev/null
+++ b/src/Environment/fgclouds.hxx
@@ -0,0 +1,75 @@
+// Build a cloud layer based on metar
+//
+// Written by Harald JOHNSEN, started April 2005.
+//
+// Copyright (C) 2005  Harald JOHNSEN - hjohnsen@evc.net
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+//
+//
+#ifndef _FGCLOUDS_HXX
+#define _FGCLOUDS_HXX
+
+#ifdef HAVE_CONFIG
+#  include <config.h>
+#endif
+
+#include <simgear/compiler.h>
+#include <simgear/sound/soundmgr_openal.hxx>
+#include <Main/fg_props.hxx>
+
+#include STL_STRING
+
+SG_USING_STD(string);
+
+class SGNewCloud;
+class SGCloudField;
+class FGMetar;
+
+class FGClouds {
+
+private:
+	SGNewCloud *buildCloud(SGPropertyNode *cloud_def_root, string name);
+	void buildLayer(SGCloudField *layer, string name, double alt, double coverage);
+
+	void buildMETAR(void);
+
+	void buildScenario( string scenario );
+
+	void setLayer( int iLayer, float alt_m, string coverage, string layer_type );
+
+	void update_metar_properties( FGMetar *m );
+
+	void FGClouds::update_env_config ();
+
+	int update_event;
+	SGSoundSample *snd_lightning;
+
+	float station_elevation_ft;
+
+public:
+	FGClouds();
+	~FGClouds();
+
+	void build(void);
+
+	void init(void);
+
+	int get_update_event(void) const;
+	void set_update_event(int count);
+
+};
+
+#endif // _FGCLOUDS_HXX
\ No newline at end of file
diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx
index 7316d4206..afc92a537 100644
--- a/src/Main/renderer.cxx
+++ b/src/Main/renderer.cxx
@@ -53,6 +53,7 @@
 #  include <simgear/scene/sky/clouds3d/SkySceneLoader.hpp>
 #  include <simgear/scene/sky/clouds3d/SkyUtil.hpp>
 #endif
+#include <simgear/environment/visual_enviro.hxx>
 
 #include <Scenery/tileentry.hxx>
 #include <Time/light.hxx>
@@ -249,8 +250,10 @@ FGRenderer::update( bool refresh_camera_settings ) {
     bool skyblend = fgGetBool("/sim/rendering/skyblend");
     bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
     bool distance_attenuation = fgGetBool("/sim/rendering/distance-attenuation");
+    bool volumetric_clouds = sgEnviro.get_clouds_enable_state();
 #ifdef FG_ENABLE_MULTIPASS_CLOUDS
     bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") && 
+                                !volumetric_clouds &&
                                 !SGCloudLayer::enable_bump_mapping;  // ugly artefact now
 #else
     bool multi_pass_clouds = false;
@@ -490,6 +493,8 @@ FGRenderer::update( bool refresh_camera_settings ) {
     ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
     ssgGetLight( 0 ) -> setColour( GL_SPECULAR, l->scene_specular() );
 
+    sgEnviro.setLight(l->adj_fog_color());
+
     // texture parameters
     // glEnable( GL_TEXTURE_2D );
     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
@@ -509,6 +514,13 @@ FGRenderer::update( bool refresh_camera_settings ) {
 
     setNearFar( scene_nearplane, scene_farplane );
 
+    sgEnviro.startOfFrame(current__view->get_view_pos(), 
+        current__view->get_world_up(),
+        current__view->getLongitude_deg(),
+        current__view->getLatitude_deg(),
+        current__view->getAltitudeASL_ft() * SG_FEET_TO_METER,
+        delta_time_sec);
+
     if ( draw_otw && skyblend ) {
         // draw the sky backdrop
 
@@ -538,7 +550,8 @@ FGRenderer::update( bool refresh_camera_settings ) {
 
             // Disable depth buffer update, draw the clouds
             glDepthMask( GL_FALSE );
-            thesky->drawUpperClouds();
+            if( !volumetric_clouds )
+                thesky->drawUpperClouds();
             if ( multi_pass_clouds ) {
                 thesky->drawLowerClouds();
             }
@@ -692,6 +705,8 @@ FGRenderer::update( bool refresh_camera_settings ) {
         glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
     }
 
+    sgEnviro.drawLightning();
+
     if ( draw_otw && draw_clouds ) {
         if ( multi_pass_clouds ) {
             // Disable depth buffer update, draw the clouds where the
@@ -706,10 +721,19 @@ FGRenderer::update( bool refresh_camera_settings ) {
             glDisable( GL_STENCIL_TEST );
         } else {
             glDepthMask( GL_FALSE );
+            if( volumetric_clouds )
+                thesky->drawUpperClouds();
             thesky->drawLowerClouds();
             glDepthMask( GL_TRUE );
         }
     }
+    sgEnviro.drawPrecipitation(
+        fgGetDouble("/environment/metar/rain-norm", 0.0),
+        fgGetDouble("/environment/metar/snow-norm", 0.0),
+        fgGetDouble("/environment/metar/hail-norm", 0.0),
+        fgGetDouble("/orientation/pitch-deg", 0.0),
+        fgGetDouble("/orientation/roll-deg", 0.0),
+        fgGetDouble("/velocities/airspeed-kt", 0.0));
 
     if ( draw_otw ) {
         FGTileMgr::set_tile_filter( false );
@@ -904,6 +928,7 @@ void FGRenderer::setFOV( float w, float h ) {
     ssgSetFOV( w, h );
     ssgSetNearFar( fov_near, fov_far );
     fgHackFrustum();
+    sgEnviro.setFOV( w, h );
 }
 
 
@@ -922,4 +947,5 @@ void FGRenderer::setNearFar( float n, float f ) {
     fgHackFrustum();
 }
 
+
 // end of renderer.cxx