diff --git a/Effects/urban.eff b/Effects/urban.eff
new file mode 100644
index 000000000..f2ef243b6
--- /dev/null
+++ b/Effects/urban.eff
@@ -0,0 +1,90 @@
+
+
+ Effects/urban
+ Effects/terrain-default
+
+
+ Textures.high/Terrain/city1-relief.png
+ linear-mipmap-linear
+ repeat
+ repeat
+ normalized
+
+
+
+
+
+ /sim/rendering/urban-shader
+ /sim/rendering/shader-effects
+
+
+ 2.0
+
+
+
+ GL_ARB_shader_objects
+ GL_ARB_shading_language_100
+ GL_ARB_vertex_shader
+ GL_ARB_fragment_shader
+
+
+
+
+
+ true
+
+
+
+
+ ambient-and-diffuse
+
+
+
+ smooth
+ back
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ Shaders/urban.vert
+ Shaders/urban.frag
+
+
+ BaseTex
+ sampler-2d
+ 0
+
+
+ NormalTex
+ sampler-2d
+ 1
+
+
+ depth_factor
+ float
+ 0.005
+
+
+
+
diff --git a/Shaders/urban.frag b/Shaders/urban.frag
new file mode 100644
index 000000000..2c8c2d3e4
--- /dev/null
+++ b/Shaders/urban.frag
@@ -0,0 +1,85 @@
+#version 120
+
+varying vec4 rawpos;
+varying vec4 ecPosition;
+varying vec3 VNormal;
+varying vec3 VTangent;
+varying vec3 VBinormal;
+varying vec3 Normal;
+varying vec4 constantColor;
+
+uniform sampler2D BaseTex;
+uniform sampler2D NormalTex;
+uniform float depth_factor;
+
+const float scale = 1.0;
+
+float ray_intersect(sampler2D reliefMap, vec2 dp, vec2 ds)
+{
+ const int linear_search_steps = 10;
+
+ float size = 1.0 / float(linear_search_steps);
+ float depth = 0.0;
+ float best_depth = 1.0;
+
+ for(int i = 0; i < linear_search_steps - 1; ++i)
+ {
+ depth += size;
+ float t = texture2D(reliefMap, dp + ds * depth).a;
+ if(best_depth > 0.996)
+ if(depth >= t)
+ best_depth = depth;
+ }
+ depth = best_depth;
+
+ const int binary_search_steps = 5;
+
+ for(int i = 0; i < binary_search_steps; ++i)
+ {
+ size *= 0.5;
+ float t = texture2D(reliefMap, dp + ds * depth).a;
+ if(depth >= t)
+ {
+ best_depth = depth;
+ depth -= 2.0 * size;
+ }
+ depth += size;
+ }
+
+ return(best_depth);
+}
+
+void main (void)
+{
+ vec3 V = normalize(ecPosition.xyz);
+ vec3 s = vec3(dot(V, VTangent), dot(V, VBinormal), dot(VNormal, V));
+ vec2 ds = s.xy * depth_factor / s.z;
+ vec2 dp = gl_TexCoord[0].st;
+ float d = ray_intersect(NormalTex, dp, ds);
+
+ vec2 uv = dp + ds * d;
+ vec3 N = texture2D(NormalTex, uv).xyz * 2.0 - 1.0;
+
+ float fogFactor;
+ float fogCoord = ecPosition.z;
+ const float LOG2 = 1.442695;
+ fogFactor = exp2(-gl_Fog.density * gl_Fog.density * fogCoord * fogCoord * LOG2);
+ fogFactor = clamp(fogFactor, 0.0, 1.0);
+
+ vec4 c1 = texture2D(BaseTex, uv);
+
+ N = normalize(N.x * VTangent + N.y * VBinormal + N.z * VNormal);
+
+ vec3 l = gl_LightSource[0].position.xyz;
+ vec3 diffuse = gl_Color.rgb * max(0.0, dot(N, l));
+
+ vec4 ambient_light = constantColor + gl_LightSource[0].diffuse * vec4(diffuse, 1.0);
+
+ c1 *= ambient_light;
+ vec4 finalColor = c1;
+
+ if(gl_Fog.density == 1.0)
+ fogFactor=1.0;
+
+ gl_FragColor = mix(gl_Fog.color ,finalColor, fogFactor);
+}
diff --git a/Shaders/urban.vert b/Shaders/urban.vert
new file mode 100644
index 000000000..3a60d73a2
--- /dev/null
+++ b/Shaders/urban.vert
@@ -0,0 +1,26 @@
+varying vec4 rawpos;
+varying vec4 ecPosition;
+varying vec3 VNormal;
+varying vec3 Normal;
+varying vec3 VTangent;
+varying vec3 VBinormal;
+varying vec4 constantColor;
+
+void main(void)
+{
+ rawpos = gl_Vertex;
+ ecPosition = gl_ModelViewMatrix * gl_Vertex;
+ VNormal = normalize(gl_NormalMatrix * gl_Normal);
+ Normal = normalize(gl_Normal);
+
+ vec3 t = normalize(cross(gl_Normal, vec3(1.0,0.0,0.0)));
+ VTangent = gl_NormalMatrix * t;
+ vec3 b = normalize(cross(gl_Normal,t));
+ VBinormal = gl_NormalMatrix * b;
+
+ gl_FrontColor = gl_Color;
+ constantColor = gl_FrontMaterial.emission
+ + gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient);
+ gl_Position = ftransform();
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+}
diff --git a/gui/dialogs/rendering.xml b/gui/dialogs/rendering.xml
index dc00b13b1..90a4b9bad 100644
--- a/gui/dialogs/rendering.xml
+++ b/gui/dialogs/rendering.xml
@@ -261,6 +261,15 @@
dialog-apply
+
+
+ left
+
+ /sim/rendering/urban-shader
+
+ dialog-apply
+
+
diff --git a/materials.xml b/materials.xml
index 9e6548616..e9ab5d2d2 100644
--- a/materials.xml
+++ b/materials.xml
@@ -871,9 +871,12 @@ Shared parameters for various materials.
BuiltUpCover
Urban
+ Effects/urban
Terrain/city1.png
+
1024
1024
100000.0
diff --git a/preferences.xml b/preferences.xml
index acf24801a..4d4cc0c27 100644
--- a/preferences.xml
+++ b/preferences.xml
@@ -136,6 +136,7 @@ Started September 2000 by David Megginson, david@megginson.com
0
0
0
+ 0
120