From 3071cdd0ac483e1506b450e82bf9949c6de6b7c4 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Fri, 21 Mar 2014 02:16:58 +0100
Subject: [PATCH 1/5] fx: add OffscreenRenderer

---
 .../oscim/android/test/S3DBMapActivity.java   |  11 +-
 .../org/oscim/layers/tile/s3db/S3DBLayer.java |   8 +-
 .../layers/tile/s3db/S3DBTileLoader.java      |  33 +-
 .../org/oscim/renderer/OffscreenRenderer.java | 401 ++++++++++++++++++
 4 files changed, 444 insertions(+), 9 deletions(-)
 create mode 100644 vtm/src/org/oscim/renderer/OffscreenRenderer.java

diff --git a/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java b/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
index 2f655620..8d234ac0 100644
--- a/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
@@ -1,8 +1,10 @@
 package org.oscim.android.test;
 
 import org.oscim.android.cache.TileCache;
+import org.oscim.layers.GenericLayer;
+import org.oscim.layers.tile.TileLayer;
 import org.oscim.layers.tile.s3db.S3DBLayer;
-import org.oscim.layers.tile.vector.labeling.LabelLayer;
+import org.oscim.renderer.OffscreenRenderer;
 import org.oscim.theme.VtmThemes;
 import org.oscim.tiling.TileSource;
 import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
@@ -28,8 +30,13 @@ public class S3DBMapActivity extends BaseMapActivity {
 			mS3dbCache.setCacheSize(512 * (1 << 10));
 			ts.setCache(mS3dbCache);
 		}
+		TileLayer tl = new S3DBLayer(mMap, ts);
+		OffscreenRenderer or = new OffscreenRenderer(mMap.getWidth(),
+		                                             mMap.getHeight());
+		or.setRenderer(tl.getRenderer());
+		mMap.layers().add(tl);
 
-		mMap.layers().add(new S3DBLayer(mMap, ts));
+		mMap.layers().add(new GenericLayer(mMap, or));
 		mMap.layers().add(new LabelLayer(mMap, mBaseLayer));
 	}
 
diff --git a/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java b/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
index 6df7ecd5..4f7db87a 100644
--- a/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
+++ b/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
@@ -39,7 +39,7 @@ public class S3DBLayer extends TileLayer {
 		return new S3DBTileLoader(getManager(), mTileSource);
 	}
 
-	static class S3DBRenderer extends TileRenderer {
+	public static class S3DBRenderer extends TileRenderer {
 		ExtrusionRenderer mExtRenderer;
 
 		public S3DBRenderer() {
@@ -57,6 +57,10 @@ public class S3DBLayer extends TileLayer {
 		protected synchronized void render(GLViewport v) {
 			mExtRenderer.render(v);
 		}
+
+		public synchronized void render2(GLViewport v) {
+			mExtRenderer.render2(v);
+		}
 	}
 
 	static int getColor(String color, boolean roof) {
@@ -97,7 +101,7 @@ public class S3DBLayer extends TileLayer {
 			return Color.LTGRAY;
 
 		if ("transparent" == color)
-			return Color.get(64, 64, 64, 64);
+			return Color.get(128, 128, 128, 128);
 
 		Integer css = ColorsCSS.get(color);
 
diff --git a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
index 66ad95f7..92c1abc8 100644
--- a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
+++ b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
@@ -3,9 +3,11 @@ package org.oscim.layers.tile.s3db;
 import static org.oscim.layers.tile.s3db.S3DBLayer.getMaterialColor;
 
 import org.oscim.backend.canvas.Color;
+import org.oscim.core.GeometryBuffer;
 import org.oscim.core.GeometryBuffer.GeometryType;
 import org.oscim.core.MapElement;
 import org.oscim.core.MercatorProjection;
+import org.oscim.core.Tag;
 import org.oscim.layers.tile.MapTile;
 import org.oscim.layers.tile.TileLoader;
 import org.oscim.layers.tile.TileManager;
@@ -27,9 +29,25 @@ class S3DBTileLoader extends TileLoader {
 
 	private float mGroundScale;
 
+	static MapElement mTilePlane = new MapElement();
+
+	static {
+		mTilePlane = new MapElement();
+		GeometryBuffer g = mTilePlane;
+		g.type = GeometryType.TRIS;
+		g.points = new float[] {
+		        0, 0, 0,
+		        4096, 0, 0,
+		        0, 4096, 0,
+		        4096, 4096, 0 };
+		g.index = new short[] { 0, 1, 2, 2, 1, 3 };
+		mTilePlane.tags.add(new Tag("c", "transparent"));
+	}
+
 	public S3DBTileLoader(TileManager tileManager, TileSource tileSource) {
 		super(tileManager);
 		mTileDataSource = tileSource.getDataSource();
+
 	}
 
 	@Override
@@ -45,15 +63,18 @@ class S3DBTileLoader extends TileLoader {
 		mGroundScale = (float) MercatorProjection
 		    .groundResolution(lat, 1 << mTile.zoomLevel);
 
+		mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(247, 249, 250));
+
 		mLayers = new ExtrusionLayer(0, mGroundScale, Color.get(255, 254, 252));
 		//mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(207, 209, 210));
-		mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(247, 249, 250));
-		mLayers.next = mRoofs;
+		mRoofs.next = mLayers;
 
 		ElementLayers layers = new ElementLayers();
-		layers.setExtrusionLayers(mLayers);
+		layers.setExtrusionLayers(mRoofs);
 		tile.data = layers;
 
+		process(mTilePlane);
+
 		try {
 			/* query database, which calls process() callback */
 			mTileDataSource.query(mTile, this);
@@ -109,16 +130,18 @@ class S3DBTileLoader extends TileLoader {
 		}
 		ExtrusionLayer l = new ExtrusionLayer(0, mGroundScale, c);
 
-		l.next = mRoofs.next;
-		mRoofs.next = l;
+		l.next = mLayers.next;
+		mLayers.next = l;
 
 		l.add(element);
 	}
 
 	@Override
 	public void completed(QueryResult result) {
+
 		mLayers = null;
 		mRoofs = null;
+
 		super.completed(result);
 	}
 }
diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
new file mode 100644
index 00000000..9fedec68
--- /dev/null
+++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
@@ -0,0 +1,401 @@
+package org.oscim.renderer;
+
+import java.nio.IntBuffer;
+
+import org.oscim.backend.GL20;
+import org.oscim.layers.tile.s3db.S3DBLayer.S3DBRenderer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OffscreenRenderer extends LayerRenderer {
+	final static Logger log = LoggerFactory.getLogger(OffscreenRenderer.class);
+
+	int fb;
+	//int depthRb;
+	int renderTex;
+	int renderDepth;
+
+	int texW;
+	int texH;
+
+	public OffscreenRenderer(int w, int h) {
+		texW = w;
+		texH = h;
+		//texW = nearestPowerOf2(texW);
+		//texH = nearestPowerOf2(texH);
+	}
+
+	int nearestPowerOf2(int x) {
+		--x;
+		x |= x >> 1;
+		x |= x >> 2;
+		x |= x >> 4;
+		x |= x >> 8;
+		x |= x >> 16;
+		return ++x;
+	}
+
+	boolean initialized;
+
+	protected boolean setup1(GLViewport viewport) {
+		IntBuffer buf = MapRenderer.getIntBuffer(1);
+
+		texW = (int) viewport.getWidth();
+		texH = (int) viewport.getHeight();
+		//texW = nearestPowerOf2(texW);
+		//texH = nearestPowerOf2(texH);
+
+		GL.glGenFramebuffers(1, buf);
+		fb = buf.get(0);
+
+		//		buf.clear();
+		//		GL.glGenRenderbuffers(1, buf);
+		//		depthRb = buf.get(0);
+
+		buf.clear();
+		GL.glGenTextures(1, buf);
+		renderTex = buf.get(0);
+
+		buf.clear();
+		GL.glGenTextures(1, buf);
+		renderDepth = buf.get(0);
+
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
+
+		// generate color texture
+		GL.glBindTexture(GL20.GL_TEXTURE_2D, renderTex);
+		GLUtils.checkGlError("0");
+
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_LINEAR);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_LINEAR);
+
+		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA,
+		                texW, texH, 0, GL20.GL_RGBA,
+		                GL20.GL_UNSIGNED_BYTE, null);
+
+		GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
+		                          GL20.GL_COLOR_ATTACHMENT0,
+		                          GL20.GL_TEXTURE_2D,
+		                          renderTex, 0);
+
+		GLUtils.checkGlError("00");
+
+		GL.glBindTexture(GL20.GL_TEXTURE_2D, renderDepth);
+
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
+		GLUtils.checkGlError("1");
+
+		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT,
+		                texW, texH, 0, GL20.GL_DEPTH_COMPONENT,
+		                GL20.GL_UNSIGNED_SHORT, null);
+
+		GLUtils.checkGlError("11 " + texW + "  / " + texH);
+
+		GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
+		                          GL20.GL_DEPTH_ATTACHMENT,
+		                          GL20.GL_TEXTURE_2D,
+		                          renderDepth, 0);
+
+		GLUtils.checkGlError("111");
+		// create render buffer and bind 16-bit depth buffer
+		//GL.glBindRenderbuffer(GL20.GL_RENDERBUFFER, depthRb);
+
+		//GL.glRenderbufferStorage(GL20.GL_RENDERBUFFER,
+		//                         GL20.GL_DEPTH_COMPONENT16,
+		//                         texW,
+		//                         texH);
+
+		GLUtils.checkGlError("2");
+
+		GLUtils.checkGlError("3");
+
+		//GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
+		//                          GL20.GL_COLOR_ATTACHMENT0,
+		//                          GL20.GL_TEXTURE_2D,
+		//                          renderTex, 0);
+		//
+		//GL.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER,
+		//                             GL20.GL_DEPTH_ATTACHMENT,
+		//                             GL20.GL_RENDERBUFFER,
+		//                             depthRb);
+
+		int status = GL.glCheckFramebufferStatus(GL20.GL_FRAMEBUFFER);
+		if (status != GL20.GL_FRAMEBUFFER_COMPLETE) {
+			log.debug("invalid framebuffer!!! " + status);
+			return false;
+		}
+
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
+
+		//shader = GLUtils.createProgram(vShader, fShader);
+		shader = GLShader.createProgram(vShader, fSSAO);
+
+		hTex = GL.glGetUniformLocation(shader, "u_tex");
+		hTexColor = GL.glGetUniformLocation(shader, "u_texColor");
+		//hScreen = GL.glGetUniformLocation(shader, "u_screen");
+		hPixel = GL.glGetUniformLocation(shader, "u_pixel");
+		hPos = GL.glGetAttribLocation(shader, "a_pos");
+
+		return true;
+	}
+
+	int shader;
+	int hPos;
+	int hTex;
+	int hTexColor;
+	//int hScreen;
+	int hPixel;
+
+	public void enable(boolean on) {
+		if (on)
+			GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
+		else
+			GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
+	}
+
+	public void begin() {
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
+		GL.glDepthMask(true);
+		GL.glClear(GL20.GL_DEPTH_BUFFER_BIT);
+	}
+
+	LayerRenderer mRenderer;
+
+	public void setRenderer(LayerRenderer renderer) {
+		mRenderer = renderer;
+	}
+
+	@Override
+	protected void update(GLViewport viewport) {
+		if (!initialized) {
+			setup1(viewport);
+			initialized = true;
+		}
+		mRenderer.update(viewport);
+		//log.debug(">>> ist ready " + mRenderer.isReady());
+		setReady(mRenderer.isReady());
+	}
+
+	@Override
+	protected void render(GLViewport viewport) {
+		//begin();
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
+		GL.glViewport(0, 0, texW, texH);
+		GL.glDepthMask(true);
+		//GL.glViewport(0, 0, this.texW, this.texH);
+		GL.glClearColor(0, 0, 0, 0);
+		//GL.glDepthRangef(0, 1);
+		//GL.glClearDepthf(1);
+		GL.glClear(GL20.GL_DEPTH_BUFFER_BIT | GL20.GL_COLOR_BUFFER_BIT);
+		//GL.glClear(GL20.GL_DEPTH_BUFFER_BIT);
+
+		GLUtils.checkGlError("-----");
+		((S3DBRenderer) mRenderer).render2(viewport);
+		GLUtils.checkGlError("----");
+
+		GL.glViewport(0, 0, (int) viewport.getWidth(), (int) viewport.getHeight());
+
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
+
+		GLUtils.checkGlError("--");
+
+		GLState.useProgram(shader);
+		GLUtils.checkGlError("-0");
+
+		// bind the framebuffer texture
+		GL.glActiveTexture(GL20.GL_TEXTURE1);
+		GLUtils.checkGlError("-1");
+
+		//GL.glBindTexture(GL20.GL_TEXTURE_2D, renderTex);
+		//GL.glBindTexture(GL20.GL_TEXTURE_2D, renderDepth);
+
+		GLState.bindTex2D(renderDepth);
+		GL.glUniform1i(hTex, 1);
+
+		GLUtils.checkGlError("-2");
+
+		GL.glActiveTexture(GL20.GL_TEXTURE0);
+		GLState.bindTex2D(renderTex);
+		GL.glUniform1i(hTexColor, 0);
+
+		MapRenderer.bindQuadVertexVBO(hPos, true);
+
+		//GL.glUniform2f(hScreen, texW, texH);
+		GL.glUniform2f(hPixel, (float) (1.0 / texW * 0.5), (float) (1.0 / texH * 0.5));
+
+		GLState.enableVertexArrays(hPos, -1);
+		GLUtils.checkGlError("-3");
+
+		GLState.test(false, false);
+		GLState.blend(true);
+		GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
+		GLUtils.checkGlError("-4");
+
+		//GL.glDepthRangef(1, -1);
+		//GL.glClearDepthf(1);
+
+		//GL.glActiveTexture(GL20.GL_TEXTURE1);
+
+	}
+
+	private final static String vShader = ""
+	        + "precision highp float;"
+	        + "uniform vec2 u_pixel;"
+	        + "attribute vec4 a_pos;"
+	        + "varying vec2 tex_pos;"
+
+	        + "void main() {"
+	        + "  gl_Position = a_pos;"
+	        + "  tex_pos = (a_pos.xy + 1.0) * 0.5;"
+	        + "}";
+
+	private final static String fSSAO = ""
+	        + "precision highp float;"
+	        // Depth texture
+	        + "uniform sampler2D u_tex;"
+	        // Depth texture
+	        + "uniform sampler2D u_texColor;"
+	        // Random texture
+	        //+ "uniform sampler2D rand;"  
+	        //+ "uniform vec2 u_screen;"
+	        + "uniform vec2 u_pixel;"
+
+	        + "varying vec2 tex_pos;"
+	        //
+	        // gauss bell center	
+	        + "const float gdisplace = 0.2;"
+	        //
+	        // "vec2 camerarange = vec2(1.0, 8.0);"
+	        + "const float nearZ = 1.0;"//camerarange.x;"
+	        + "const float farZ = 4.0;" //camerarange.y;"
+	        //
+	        + "float getDepth(float posZ){"
+	        + "	 return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));"
+	        + "}"
+	        //
+	        + "float compareDepths(in float depth1, in float posZ, inout float far) {"
+	        + "  float depth2 = getDepth(posZ);"
+	        //   depth difference (0-100)
+	        + "	 float diff = (depth1 - depth2) * 100.0;"
+	        //   set 'far == 1.0' when 'diff' > 'gdisplace'
+	        + "	 far = step(diff, gdisplace);"
+	        //   gauss bell width 2, reduce left bell width to avoid self-shadowing
+	        + "  float garea = max((1.0 - far) * 2.0, 0.01);"
+	        + "	 return pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));"
+	        + "}"
+	        //
+	        + "float addAO(float depth, float x1, float y1, float x2, float y2) {"
+	        + "    float ao = 0.0;"
+
+	        + "    float f_11;"
+	        + "    float z_11 = texture2D(u_tex, vec2(x1, y1)).x;"
+	        + "    float d_11 = compareDepths(depth, z_11, f_11);"
+
+	        + "    float f_12;"
+	        + "    float z_12 = texture2D(u_tex, vec2(x1, y2)).x;"
+	        + "    float d_12 = compareDepths(depth, z_12, f_12);"
+
+	        + "    float f_21;"
+	        + "    float z_21 = texture2D(u_tex, vec2(x2, y1)).x;"
+	        + "    float d_21 = compareDepths(depth, z_21, f_21);"
+
+	        + "    float f_22;"
+	        + "    float z_22 = texture2D(u_tex, vec2(x2, y2)).x;"
+	        + "    float d_22 = compareDepths(depth, z_22, f_22);"
+
+	        + "    ao += (1.0 - step(1.0, x1)) * (1.0 - step(1.0, y1))"
+	        + "          * (d_11 + f_11 * (1.0 - d_11) * d_22);"
+
+	        + "    ao += (1.0 - step(1.0, x1)) * step(0.0, y2)"
+	        + "          * (d_12 + f_12 * (1.0 - d_12) * d_21);"
+
+	        + "    ao += step(0.0, x2) * (1.0 - step(1.0, y1))"
+	        + "          * (d_21 + f_21 * (1.0 - d_21) * d_12);"
+
+	        + "    ao += step(0.0, x2) * step(0.0, y2)"
+	        + "          * (d_22 + f_22 * (1.0 - d_22) * d_11);"
+
+	        + "    return ao;"
+	        + "}"
+
+	        + "void main(void) {"
+	        //   randomization texture:
+	        //+ "	 vec2 fres = vec2(20.0, 20.0);"
+	        //+ "	vec3 random = texture2D(rand, gl_TexCoord[0].st * fres.xy);"
+	        //+ "	random = random * 2.0 - vec3(1.0);"
+
+	        //   initialize stuff:
+	        + "  vec4 color = texture2D(u_texColor, tex_pos);"
+
+	        //+ "  vec2 tex_pos = gl_FragCoord.xy / u_screen;"
+	        + "	 float depth = getDepth(texture2D(u_tex, tex_pos).x);"
+	        +
+	        "	 float ao = 0.0;"
+	        + "  float x = tex_pos.x;"
+	        + "  float y = tex_pos.y;"
+	        //   'lookup range in screen pixel'
+	        //+ "  float pw = 1.0 / u_screen.x * 0.5;"
+	        //+ "  float ph = 1.0 / u_screen.y * 0.5;"
+
+	        + "  float pw = u_pixel.x;"
+	        + "  float ph = u_pixel.y;"
+
+	        + "	 for (int i = 0; i < 4; i++) {"
+	        + "    float pwByDepth = pw / depth;"
+	        + "    float phByDepth = ph / depth;"
+
+	        //      calculate color bleeding and ao:
+
+	        + "    ao += addAO(depth, x + pwByDepth, y + phByDepth,x - pwByDepth, y - phByDepth);"
+
+	        + "    pwByDepth *= 1.2;"
+	        + "    phByDepth *= 1.2;"
+
+	        + "    ao += addAO(depth, x + pwByDepth, y, x, y - phByDepth);"
+
+	        //      sample jittering:
+	        //+ "		pw += random.x * 0.0007;"
+	        //+ "		ph += random.y * 0.0007;"
+	        //      increase sampling area:
+	        //+ "		pw *= 1.7;"
+	        //+ "		ph *= 1.7;"
+	        + "		pw *= 1.7;"
+	        + "		ph *= 1.7;"
+
+	        + "	 }"
+	        //	        //   final values, some adjusting
+	        //+ "if ((ao / 32.0) > 1.0){"
+	        //+ "	gl_FragColor = vec4(1.0,1.0,ao / 32.0 - 1.0,1.0);"
+	        //+ ""
+	        //+ "} else {"
+	        + "	 vec3 finalAO = vec3(0.25 * pow((ao / 32.0),1.2));"
+	        + "	 gl_FragColor = vec4(1.0 - finalAO, 1.0);"
+	        //+ "	 gl_FragColor = color - vec4(finalAO, 0.0);"
+	        //+ " }"
+	        //+ "	 gl_FragColor = vec4(finalAO, 1.0) * texture2D(u_texColor, tex_pos.xy);"
+	        //+ "	gl_FragColor = vec4(gl_TexCoord[0].xy,0.0,1.0);"
+	        //+ "	gl_FragColor = vec4(tex_pos.xy,0.0,1.0);"
+	        //+ "	 gl_FragColor = vec4(gl_FragCoord.xy / u_screen, 0.0, 1.0);"
+
+	        + "}";
+
+	//	private final static String fShader = ""
+	//	        + "precision mediump float;"
+	//	        + "uniform sampler2D u_tex;"
+	//	        + "uniform sampler2D u_texColor;"  // Depth texture 
+	//	        + "uniform vec2 u_screen;"
+	//	        + "varying vec2 tex_pos;"
+	//	        + "void main() {"
+	//	        //+ "  vec2 tex_pos = gl_FragCoord.xy / u_screen;"
+	//	        + " vec4 c = texture2D(u_tex, tex_pos.xy);"
+	//	        + "   gl_FragColor = c * texture2D(u_texColor, tex_pos.xy);"
+	//	        + "}";
+
+	//+ "#version 120\n"
+
+}

From cc95c485cec912c553c7edbf1308926ef8ac82e7 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Mon, 17 Mar 2014 06:30:05 +0100
Subject: [PATCH 2/5] fx: add fxaa post-process shader

---
 vtm/resources/assets/shaders/post_fxaa.h      | 116 +++++++++
 .../layers/tile/s3db/S3DBTileLoader.java      |   2 +-
 vtm/src/org/oscim/renderer/MapRenderer.java   |  10 +-
 .../org/oscim/renderer/OffscreenRenderer.java | 238 ++++--------------
 4 files changed, 171 insertions(+), 195 deletions(-)
 create mode 100644 vtm/resources/assets/shaders/post_fxaa.h

diff --git a/vtm/resources/assets/shaders/post_fxaa.h b/vtm/resources/assets/shaders/post_fxaa.h
new file mode 100644
index 00000000..a519b51b
--- /dev/null
+++ b/vtm/resources/assets/shaders/post_fxaa.h
@@ -0,0 +1,116 @@
+precision mediump float;
+uniform vec2 u_pixel;
+attribute vec4 a_pos;
+varying vec2 tex_pos;
+
+void
+main()
+{
+  gl_Position = a_pos;
+  tex_pos = (a_pos.xy + 1.0) * 0.5;
+  //tex_pos.zw = tex_pos.xz - u_pixel * vec2 (0.5);
+}
+§
+precision mediump float;
+//uniform sampler2D m_Texture;
+//uniform vec2 g_Resolution;
+//uniform vec2 g_Resolution;
+uniform sampler2D u_texColor;
+uniform vec2 u_pixel;
+varying vec2 tex_pos;
+
+//uniform float m_VxOffset;
+//uniform float m_SpanMax;
+//uniform float m_ReduceMul;
+
+const vec2 m_SpanMax = vec2(2.5, 2.5);
+const float m_ReduceMul = 0.15;
+
+//varying vec2 texCoord;
+//varying vec4 pos;
+
+//#define FxaaTex(t, p) texture2D(t, p)
+//#define OffsetVec(a, b) vec2(a, b)
+//#define FxaaTexOff(t, p, o, r) texture2D(t, p + o * r)
+// Output of FxaaVertexShader interpolated across screen.
+// Input texture.
+// Constant {1.0/frameWidth, 1.0/frameHeight}.
+
+#define FXAA_REDUCE_MIN   (1.0/128.0)
+
+//float FxaaLuma(float3 rgb) {
+//  return rgb.g * (0.587/0.299) + rgb.b;
+//}
+
+vec4
+FxaaPixelShader(vec2 pos, sampler2D tex, vec2 pixel){
+
+  //#define FXAA_REDUCE_MUL   (1.0/8.0)
+  //#define FXAA_SPAN_MAX     8.0
+
+  vec3 rgbNW = texture2D(tex, pos + vec2(-1.0, -1.0) * pixel).xyz;
+//	vec3 rgbNE = FxaaTexOff(tex, pos.zw, OffsetVec(1,0), pixel.xy).xyz;
+//	vec3 rgbSW = FxaaTexOff(tex, pos.zw, OffsetVec(0,1), pixel.xy).xyz;
+//	vec3 rgbSE = FxaaTexOff(tex, pos.zw, OffsetVec(1,1), pixel.xy).xyz;
+
+  vec3 rgbNE = texture2D(tex, pos + vec2(1.0, -1.0) * pixel).xyz;
+  vec3 rgbSW = texture2D(tex, pos + vec2(-1.0, 1.0) * pixel).xyz;
+  vec3 rgbSE = texture2D(tex, pos + vec2(1.0, 1.0) * pixel).xyz;
+
+  vec3 rgbM = texture2D(tex, pos).xyz;
+
+  //return vec4(rgbM - (rgbNW + rgbNE)*0.25,1.0);
+
+  vec3 luma = vec3(0.299, 0.587, 0.114);
+  float lumaNW = dot(rgbNW, luma);
+  float lumaNE = dot(rgbNE, luma);
+  float lumaSW = dot(rgbSW, luma);
+  float lumaSE = dot(rgbSE, luma);
+  float lumaM = dot(rgbM, luma);
+
+  float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+  float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+  //vec4 rgb = texture2D (tex, pos);
+  //return vec4(0.5 + lumaM - lumaMin, lumaM, 0.5 + lumaM - lumaMax, 1.0) * rgb.a;
+
+  vec2 dir;
+  dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+  dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+  //return vec4(dir*0.5, 0.5, 1.0);
+
+  float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), FXAA_REDUCE_MIN);
+
+  float rcpDirMin = 1.0 / (dirReduce + min(abs(dir.x), abs(dir.y)));
+
+  dir = min(m_SpanMax, max(-m_SpanMax, dir * rcpDirMin)) * pixel;
+
+  vec4 rgbA = 0.5 * (texture2D(tex, pos + dir * vec2(1.0 / 3.0 - 0.5))
+                   + texture2D(tex, pos + dir * vec2(2.0 / 3.0 - 0.5)));
+
+  vec4 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, pos + dir * vec2(0.0 / 3.0 - 0.5))
+                                 + texture2D(tex, pos + dir * vec2(3.0 / 3.0 - 0.5)));
+
+  float lumaB = dot(rgbB.xyz, luma.xyz);
+
+  float d = step(lumaB, lumaMin) + step(lumaMax, lumaB);
+
+  return (1.0 - d) * rgbB + d * rgbA;
+
+  //  if ((lumaB < lumaMin) || (lumaB > lumaMax))
+  //    { return rgbA; } else { return rgbB; }
+}
+
+void
+main(){
+  //vec2 rcpFrame = vec2(1.0) / g_Resolution;
+  //gl_FragColor = vec4(FxaaPixelShader(pos, m_Texture, rcpFrame), 1.0);
+  gl_FragColor = FxaaPixelShader(tex_pos, u_texColor, u_pixel * 3.15);
+  //gl_FragColor = FxaaPixelShader (tex_pos, u_texColor, u_pixel * 2.35);
+
+  //vec4 c = texture2D (u_texColor, tex_pos);
+  //gl_FragColor = vec4 (c.rgb * 0.5, 1.0) + vec4(FxaaPixelShader (tex_pos, u_texColor, u_pixel * 3.15).rgb - c.rgb, 1.0) * 2.0;
+
+  //gl_FragColor = 0.2*c + (FxaaPixelShader (tex_pos, u_texColor, u_pixel * 1.2)) * 0.8;
+}
diff --git a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
index 92c1abc8..9cc9f211 100644
--- a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
+++ b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
@@ -73,7 +73,7 @@ class S3DBTileLoader extends TileLoader {
 		layers.setExtrusionLayers(mRoofs);
 		tile.data = layers;
 
-		process(mTilePlane);
+		//process(mTilePlane);
 
 		try {
 			/* query database, which calls process() callback */
diff --git a/vtm/src/org/oscim/renderer/MapRenderer.java b/vtm/src/org/oscim/renderer/MapRenderer.java
index 0b38a18d..cc9c17a0 100644
--- a/vtm/src/org/oscim/renderer/MapRenderer.java
+++ b/vtm/src/org/oscim/renderer/MapRenderer.java
@@ -178,11 +178,11 @@ public class MapRenderer {
 
 	private void draw() {
 
-		if (mUpdateColor) {
-			float cc[] = mClearColor;
-			GL.glClearColor(cc[0], cc[1], cc[2], cc[3]);
-			mUpdateColor = false;
-		}
+		//if (mUpdateColor) {
+		float cc[] = mClearColor;
+		GL.glClearColor(cc[0], cc[1], cc[2], cc[3]);
+		mUpdateColor = false;
+		//}
 
 		GL.glDepthMask(true);
 		GL.glStencilMask(0xFF);
diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
index 9fedec68..8b14b461 100644
--- a/vtm/src/org/oscim/renderer/OffscreenRenderer.java
+++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
@@ -37,6 +37,8 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	boolean initialized;
 
+	private boolean useDepthTexture = false;
+
 	protected boolean setup1(GLViewport viewport) {
 		IntBuffer buf = MapRenderer.getIntBuffer(1);
 
@@ -56,10 +58,6 @@ public class OffscreenRenderer extends LayerRenderer {
 		GL.glGenTextures(1, buf);
 		renderTex = buf.get(0);
 
-		buf.clear();
-		GL.glGenTextures(1, buf);
-		renderDepth = buf.get(0);
-
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
 
 		// generate color texture
@@ -68,8 +66,8 @@ public class OffscreenRenderer extends LayerRenderer {
 
 		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
 		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_LINEAR);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_LINEAR);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
+		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
 
 		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA,
 		                texW, texH, 0, GL20.GL_RGBA,
@@ -82,24 +80,43 @@ public class OffscreenRenderer extends LayerRenderer {
 
 		GLUtils.checkGlError("00");
 
-		GL.glBindTexture(GL20.GL_TEXTURE_2D, renderDepth);
+		if (useDepthTexture) {
+			buf.clear();
+			GL.glGenTextures(1, buf);
+			renderDepth = buf.get(0);
 
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
-		GLUtils.checkGlError("1");
+			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
+			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
+			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
+			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
+			GLUtils.checkGlError("1");
 
-		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT,
-		                texW, texH, 0, GL20.GL_DEPTH_COMPONENT,
-		                GL20.GL_UNSIGNED_SHORT, null);
+			GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT,
+			                texW, texH, 0, GL20.GL_DEPTH_COMPONENT,
+			                GL20.GL_UNSIGNED_SHORT, null);
 
-		GLUtils.checkGlError("11 " + texW + "  / " + texH);
+			GLUtils.checkGlError("11 " + texW + "  / " + texH);
 
-		GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
-		                          GL20.GL_DEPTH_ATTACHMENT,
-		                          GL20.GL_TEXTURE_2D,
-		                          renderDepth, 0);
+			GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
+			                          GL20.GL_DEPTH_ATTACHMENT,
+			                          GL20.GL_TEXTURE_2D,
+			                          renderDepth, 0);
+		} else {
+			buf.clear();
+			GL.glGenRenderbuffers(1, buf);
+			int depthRenderbuffer = buf.get(0);
+
+			GL.glBindRenderbuffer(GL20.GL_RENDERBUFFER, depthRenderbuffer);
+
+			GL.glRenderbufferStorage(GL20.GL_RENDERBUFFER,
+			                         GL20.GL_DEPTH_COMPONENT16,
+			                         texW, texH);
+
+			GL.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER,
+			                             GL20.GL_DEPTH_ATTACHMENT,
+			                             GL20.GL_RENDERBUFFER,
+			                             depthRenderbuffer);
+		}
 
 		GLUtils.checkGlError("111");
 		// create render buffer and bind 16-bit depth buffer
@@ -132,10 +149,12 @@ public class OffscreenRenderer extends LayerRenderer {
 
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
 
-		//shader = GLUtils.createProgram(vShader, fShader);
-		shader = GLShader.createProgram(vShader, fSSAO);
+		//shader = GLShader.createProgram(vShader, fShader);
+		//shader = GLShader.createProgram(vShader, fSSAO);
+		//shader = GLShader.createProgram(vShader, fShaderFXAA);
+		shader = GLShader.loadShader("post_fxaa");
 
-		hTex = GL.glGetUniformLocation(shader, "u_tex");
+		//hTex = GL.glGetUniformLocation(shader, "u_tex");
 		hTexColor = GL.glGetUniformLocation(shader, "u_texColor");
 		//hScreen = GL.glGetUniformLocation(shader, "u_screen");
 		hPixel = GL.glGetUniformLocation(shader, "u_pixel");
@@ -146,8 +165,9 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	int shader;
 	int hPos;
-	int hTex;
+	//int hTex;
 	int hTexColor;
+
 	//int hScreen;
 	int hPixel;
 
@@ -208,16 +228,12 @@ public class OffscreenRenderer extends LayerRenderer {
 		GLUtils.checkGlError("-0");
 
 		// bind the framebuffer texture
-		GL.glActiveTexture(GL20.GL_TEXTURE1);
-		GLUtils.checkGlError("-1");
+		//GL.glActiveTexture(GL20.GL_TEXTURE1);
+		//GLUtils.checkGlError("-1");
 
-		//GL.glBindTexture(GL20.GL_TEXTURE_2D, renderTex);
-		//GL.glBindTexture(GL20.GL_TEXTURE_2D, renderDepth);
-
-		GLState.bindTex2D(renderDepth);
-		GL.glUniform1i(hTex, 1);
-
-		GLUtils.checkGlError("-2");
+		//GLState.bindTex2D(renderDepth);
+		//GL.glUniform1i(hTex, 1);
+		//GLUtils.checkGlError("-2");
 
 		GL.glActiveTexture(GL20.GL_TEXTURE0);
 		GLState.bindTex2D(renderTex);
@@ -242,160 +258,4 @@ public class OffscreenRenderer extends LayerRenderer {
 		//GL.glActiveTexture(GL20.GL_TEXTURE1);
 
 	}
-
-	private final static String vShader = ""
-	        + "precision highp float;"
-	        + "uniform vec2 u_pixel;"
-	        + "attribute vec4 a_pos;"
-	        + "varying vec2 tex_pos;"
-
-	        + "void main() {"
-	        + "  gl_Position = a_pos;"
-	        + "  tex_pos = (a_pos.xy + 1.0) * 0.5;"
-	        + "}";
-
-	private final static String fSSAO = ""
-	        + "precision highp float;"
-	        // Depth texture
-	        + "uniform sampler2D u_tex;"
-	        // Depth texture
-	        + "uniform sampler2D u_texColor;"
-	        // Random texture
-	        //+ "uniform sampler2D rand;"  
-	        //+ "uniform vec2 u_screen;"
-	        + "uniform vec2 u_pixel;"
-
-	        + "varying vec2 tex_pos;"
-	        //
-	        // gauss bell center	
-	        + "const float gdisplace = 0.2;"
-	        //
-	        // "vec2 camerarange = vec2(1.0, 8.0);"
-	        + "const float nearZ = 1.0;"//camerarange.x;"
-	        + "const float farZ = 4.0;" //camerarange.y;"
-	        //
-	        + "float getDepth(float posZ){"
-	        + "	 return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));"
-	        + "}"
-	        //
-	        + "float compareDepths(in float depth1, in float posZ, inout float far) {"
-	        + "  float depth2 = getDepth(posZ);"
-	        //   depth difference (0-100)
-	        + "	 float diff = (depth1 - depth2) * 100.0;"
-	        //   set 'far == 1.0' when 'diff' > 'gdisplace'
-	        + "	 far = step(diff, gdisplace);"
-	        //   gauss bell width 2, reduce left bell width to avoid self-shadowing
-	        + "  float garea = max((1.0 - far) * 2.0, 0.01);"
-	        + "	 return pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));"
-	        + "}"
-	        //
-	        + "float addAO(float depth, float x1, float y1, float x2, float y2) {"
-	        + "    float ao = 0.0;"
-
-	        + "    float f_11;"
-	        + "    float z_11 = texture2D(u_tex, vec2(x1, y1)).x;"
-	        + "    float d_11 = compareDepths(depth, z_11, f_11);"
-
-	        + "    float f_12;"
-	        + "    float z_12 = texture2D(u_tex, vec2(x1, y2)).x;"
-	        + "    float d_12 = compareDepths(depth, z_12, f_12);"
-
-	        + "    float f_21;"
-	        + "    float z_21 = texture2D(u_tex, vec2(x2, y1)).x;"
-	        + "    float d_21 = compareDepths(depth, z_21, f_21);"
-
-	        + "    float f_22;"
-	        + "    float z_22 = texture2D(u_tex, vec2(x2, y2)).x;"
-	        + "    float d_22 = compareDepths(depth, z_22, f_22);"
-
-	        + "    ao += (1.0 - step(1.0, x1)) * (1.0 - step(1.0, y1))"
-	        + "          * (d_11 + f_11 * (1.0 - d_11) * d_22);"
-
-	        + "    ao += (1.0 - step(1.0, x1)) * step(0.0, y2)"
-	        + "          * (d_12 + f_12 * (1.0 - d_12) * d_21);"
-
-	        + "    ao += step(0.0, x2) * (1.0 - step(1.0, y1))"
-	        + "          * (d_21 + f_21 * (1.0 - d_21) * d_12);"
-
-	        + "    ao += step(0.0, x2) * step(0.0, y2)"
-	        + "          * (d_22 + f_22 * (1.0 - d_22) * d_11);"
-
-	        + "    return ao;"
-	        + "}"
-
-	        + "void main(void) {"
-	        //   randomization texture:
-	        //+ "	 vec2 fres = vec2(20.0, 20.0);"
-	        //+ "	vec3 random = texture2D(rand, gl_TexCoord[0].st * fres.xy);"
-	        //+ "	random = random * 2.0 - vec3(1.0);"
-
-	        //   initialize stuff:
-	        + "  vec4 color = texture2D(u_texColor, tex_pos);"
-
-	        //+ "  vec2 tex_pos = gl_FragCoord.xy / u_screen;"
-	        + "	 float depth = getDepth(texture2D(u_tex, tex_pos).x);"
-	        +
-	        "	 float ao = 0.0;"
-	        + "  float x = tex_pos.x;"
-	        + "  float y = tex_pos.y;"
-	        //   'lookup range in screen pixel'
-	        //+ "  float pw = 1.0 / u_screen.x * 0.5;"
-	        //+ "  float ph = 1.0 / u_screen.y * 0.5;"
-
-	        + "  float pw = u_pixel.x;"
-	        + "  float ph = u_pixel.y;"
-
-	        + "	 for (int i = 0; i < 4; i++) {"
-	        + "    float pwByDepth = pw / depth;"
-	        + "    float phByDepth = ph / depth;"
-
-	        //      calculate color bleeding and ao:
-
-	        + "    ao += addAO(depth, x + pwByDepth, y + phByDepth,x - pwByDepth, y - phByDepth);"
-
-	        + "    pwByDepth *= 1.2;"
-	        + "    phByDepth *= 1.2;"
-
-	        + "    ao += addAO(depth, x + pwByDepth, y, x, y - phByDepth);"
-
-	        //      sample jittering:
-	        //+ "		pw += random.x * 0.0007;"
-	        //+ "		ph += random.y * 0.0007;"
-	        //      increase sampling area:
-	        //+ "		pw *= 1.7;"
-	        //+ "		ph *= 1.7;"
-	        + "		pw *= 1.7;"
-	        + "		ph *= 1.7;"
-
-	        + "	 }"
-	        //	        //   final values, some adjusting
-	        //+ "if ((ao / 32.0) > 1.0){"
-	        //+ "	gl_FragColor = vec4(1.0,1.0,ao / 32.0 - 1.0,1.0);"
-	        //+ ""
-	        //+ "} else {"
-	        + "	 vec3 finalAO = vec3(0.25 * pow((ao / 32.0),1.2));"
-	        + "	 gl_FragColor = vec4(1.0 - finalAO, 1.0);"
-	        //+ "	 gl_FragColor = color - vec4(finalAO, 0.0);"
-	        //+ " }"
-	        //+ "	 gl_FragColor = vec4(finalAO, 1.0) * texture2D(u_texColor, tex_pos.xy);"
-	        //+ "	gl_FragColor = vec4(gl_TexCoord[0].xy,0.0,1.0);"
-	        //+ "	gl_FragColor = vec4(tex_pos.xy,0.0,1.0);"
-	        //+ "	 gl_FragColor = vec4(gl_FragCoord.xy / u_screen, 0.0, 1.0);"
-
-	        + "}";
-
-	//	private final static String fShader = ""
-	//	        + "precision mediump float;"
-	//	        + "uniform sampler2D u_tex;"
-	//	        + "uniform sampler2D u_texColor;"  // Depth texture 
-	//	        + "uniform vec2 u_screen;"
-	//	        + "varying vec2 tex_pos;"
-	//	        + "void main() {"
-	//	        //+ "  vec2 tex_pos = gl_FragCoord.xy / u_screen;"
-	//	        + " vec4 c = texture2D(u_tex, tex_pos.xy);"
-	//	        + "   gl_FragColor = c * texture2D(u_texColor, tex_pos.xy);"
-	//	        + "}";
-
-	//+ "#version 120\n"
-
 }

From d90a0e94756bdf93d266525e3a634f8f18a20719 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Fri, 21 Mar 2014 00:49:48 +0100
Subject: [PATCH 3/5] fx: combined ssao/fxaa shader

- rename and update shaders
---
 .../assets/shaders/post_combined.glsl         | 187 ++++++++++++++++++
 vtm/resources/assets/shaders/post_fxaa.glsl   | 117 +++++++++++
 vtm/resources/assets/shaders/post_fxaa.h      | 116 -----------
 vtm/resources/assets/shaders/post_ssao.glsl   | 143 ++++++++++++++
 .../layers/tile/s3db/S3DBTileLoader.java      |   2 +-
 .../org/oscim/renderer/OffscreenRenderer.java |  98 +++------
 6 files changed, 477 insertions(+), 186 deletions(-)
 create mode 100644 vtm/resources/assets/shaders/post_combined.glsl
 create mode 100644 vtm/resources/assets/shaders/post_fxaa.glsl
 delete mode 100644 vtm/resources/assets/shaders/post_fxaa.h
 create mode 100644 vtm/resources/assets/shaders/post_ssao.glsl

diff --git a/vtm/resources/assets/shaders/post_combined.glsl b/vtm/resources/assets/shaders/post_combined.glsl
new file mode 100644
index 00000000..395ae666
--- /dev/null
+++ b/vtm/resources/assets/shaders/post_combined.glsl
@@ -0,0 +1,187 @@
+#ifdef GLES
+precision highp float;
+#endif
+uniform vec2 u_pixel;
+attribute vec4 a_pos;
+varying vec2 tex_pos;
+varying vec2 tex_nw;
+varying vec2 tex_ne;
+varying vec2 tex_sw;
+varying vec2 tex_se;
+void
+main()
+{
+  gl_Position = a_pos;
+  tex_pos = (a_pos.xy + 1.0) * 0.5;
+  vec2 pixel = u_pixel * 2.5;
+  tex_nw = tex_pos + vec2(-1.0, -1.0) * pixel;
+  tex_ne = tex_pos + vec2(1.0, -1.0) * pixel;
+  tex_sw = tex_pos + vec2(-1.0, 1.0) * pixel;
+  tex_se = tex_pos + vec2(1.0, 1.0) * pixel;
+}
+
+$$
+
+#ifdef GLES
+precision highp float;
+#endif
+uniform sampler2D u_texColor;
+uniform sampler2D u_tex;
+uniform vec2 u_pixel;
+varying vec2 tex_pos;
+varying vec2 tex_nw;
+varying vec2 tex_ne;
+varying vec2 tex_sw;
+varying vec2 tex_se;
+
+const vec2 m_SpanMax = vec2(2.5, 2.5);
+const float m_ReduceMul = 0.15;
+const vec3 luma = vec3(0.299, 0.587, 0.114);
+
+#define FXAA_REDUCE_MIN   (1.0/128.0)
+
+// gauss bell center
+const float gdisplace = 0.2;
+const float nearZ = 1.0;
+const float farZ = 8.0;
+const int iterations = 2;
+
+float getDepth(float posZ) {
+  return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));
+}
+float compareDepths(in float depth1, in float depth2, inout float far) {
+  //   depth difference (0-100)
+  float diff = (depth1 - depth2) * 100.0;
+  //   set 'far == 1.0' when 'diff' > 'gdisplace'
+  far = step(diff, gdisplace);
+  // gauss bell width 2,
+  // if far reduce left bell width to avoid self-shadowing
+  float garea = max((1.0 - far) * 2.0, 0.1);
+
+  //return (step(diff, 0.0) * -0.1) + pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));
+  return  pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));
+}
+
+void
+addAO(int run, inout float depth, in float x1, in float y1, in float x2, in float y2, inout float ao){
+  float z_11 = getDepth(texture2D(u_tex, vec2(x1, y1)).x);
+  float z_12 = getDepth(texture2D(u_tex, vec2(x1, y2)).x);
+  float z_21 = getDepth(texture2D(u_tex, vec2(x2, y1)).x);
+  float z_22 = getDepth(texture2D(u_tex, vec2(x2, y2)).x);
+
+  if (run == 0)
+    depth = 0.5 * depth + (z_11 + z_12 + z_21 + z_22) * (0.25 * 0.5);
+
+  float f_11;
+  float d_11 = compareDepths(depth, z_11, f_11);
+
+  float f_12;
+  float d_12 = compareDepths(depth, z_12, f_12);
+
+  float f_21;
+  float d_21 = compareDepths(depth, z_21, f_21);
+
+  float f_22;
+  float d_22 = compareDepths(depth, z_22, f_22);
+
+  ao += 1.0 //(1.0 - step(1.0, x1)) * (1.0 - step(1.0, y1))
+      * (d_11 + f_11 * (1.0 - d_11) * d_22);
+
+  ao += 1.0 //(1.0 - step(1.0, x1)) * step(0.0, y2)
+      * (d_12 + f_12 * (1.0 - d_12) * d_21);
+
+  ao += 1.0 //step(0.0, x2) * (1.0 - step(1.0, y1))
+      * (d_21 + f_21 * (1.0 - d_21) * d_12);
+
+  ao += 1.0 //step(0.0, x2) * step(0.0, y2)
+      * (d_22 + f_22 * (1.0 - d_22) * d_11);
+}
+
+
+void
+main(){
+  vec2 pixel = u_pixel * 3.15;
+
+  vec4 rgbNW = texture2D(u_texColor, tex_nw);
+  vec4 rgbNE = texture2D(u_texColor, tex_ne);
+  vec4 rgbSW = texture2D(u_texColor, tex_sw);
+  vec4 rgbSE = texture2D(u_texColor, tex_se);
+
+  vec4 rgbM = texture2D(u_texColor, tex_pos);
+
+  if (rgbNW.a + rgbNE.a + rgbSW.a + rgbSE.a < 0.1) {
+    gl_FragColor = rgbM;
+    return;
+  }
+  //return vec4(rgbM - (rgbNW + rgbNE)*0.25,1.0);
+
+  float lumaNW = dot(rgbNW.rgb, luma);
+  float lumaNE = dot(rgbNE.rgb, luma);
+  float lumaSW = dot(rgbSW.rgb, luma);
+  float lumaSE = dot(rgbSE.rgb, luma);
+  float lumaM = dot(rgbM.rgb, luma);
+
+  float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+  float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+  //vec4 rgb = texture2D (tex, tex_pos);
+  //return vec4(0.5 + lumaM - lumaMin, lumaM, 0.5 + lumaM - lumaMax, 1.0) * rgb.a;
+
+  vec2 dir;
+  dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+  dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+  float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), FXAA_REDUCE_MIN);
+
+  float rcpDirMin = 1.0 / (dirReduce + min(abs(dir.x), abs(dir.y)));
+
+  dir = min(m_SpanMax, max(-m_SpanMax, dir * rcpDirMin)) * pixel;
+
+  vec4 rgbA = 0.5 * (texture2D(u_texColor, tex_pos + dir * vec2(1.0 / 3.0 - 0.5))
+      + texture2D(u_texColor, tex_pos + dir * vec2(2.0 / 3.0 - 0.5)));
+
+  vec4 rgbB = rgbA * 0.5 + 0.25 * (texture2D(u_texColor, tex_pos + dir * vec2(0.0 / 3.0 - 0.5))
+      + texture2D(u_texColor, tex_pos + dir * vec2(3.0 / 3.0 - 0.5)));
+
+  float lumaB = dot(rgbB.rgb, luma.rgb);
+
+  float d = step(lumaB, lumaMin) + step(lumaMax, lumaB);
+
+  vec4 color = (1.0 - d) * rgbB + d * rgbA;
+
+  //vec4 color = texture2D(u_texColor, tex_pos);
+
+  float depth = texture2D(u_tex, tex_pos).x;
+  float foggy = pow(depth,3.0);
+
+  depth = getDepth(depth);
+
+  float x = tex_pos.x;
+  float y = tex_pos.y;
+  float pw = u_pixel.x;
+  float ph = u_pixel.y;
+  float ao = 0.0;
+  for (int i = 0; i < iterations; i++) {
+    float pwByDepth = pw / depth;
+    float phByDepth = ph / depth;
+    addAO(i, depth, x + pwByDepth, y + phByDepth, x - pwByDepth, y - phByDepth, ao);
+    pwByDepth *= 1.2;
+    phByDepth *= 1.2;
+    addAO(i, depth, x + pwByDepth, y, x, y - phByDepth, ao);
+    // sample jittering:
+    //	pw += random.x * 0.0007;
+    //	ph += random.y * 0.0007;
+    // increase sampling area:
+    pw *= 1.7;
+    ph *= 1.7;
+
+  }
+
+  ao = ao / float(iterations * 8);
+  ao *= 0.4 * foggy;
+  ao = clamp(ao, 0.0, 1.0);
+
+  //gl_FragColor = vec4(0.5 - vao, max(0.5, ao));
+  gl_FragColor =  vec4(color.rgb - ao, max(color.a, ao));
+}
+
diff --git a/vtm/resources/assets/shaders/post_fxaa.glsl b/vtm/resources/assets/shaders/post_fxaa.glsl
new file mode 100644
index 00000000..823bb5ea
--- /dev/null
+++ b/vtm/resources/assets/shaders/post_fxaa.glsl
@@ -0,0 +1,117 @@
+#ifdef GLES
+precision highp float;
+#endif
+uniform vec2 u_pixel;
+attribute vec4 a_pos;
+varying vec2 tex_pos;
+varying vec2 tex_nw;
+varying vec2 tex_ne;
+varying vec2 tex_sw;
+varying vec2 tex_se;
+void
+main()
+{
+  gl_Position = a_pos;
+  tex_pos = (a_pos.xy + 1.0) * 0.5;
+  vec2 pixel = u_pixel * 2.5;
+  tex_nw = tex_pos + vec2(-1.0, -1.0) * pixel;
+  tex_ne = tex_pos + vec2(1.0, -1.0) * pixel;
+  tex_sw = tex_pos + vec2(-1.0, 1.0) * pixel;
+  tex_se = tex_pos + vec2(1.0, 1.0) * pixel;
+}
+
+$$
+
+#ifdef GLES
+precision highp float;
+#endif
+uniform sampler2D u_texColor;
+uniform vec2 u_pixel;
+varying vec2 tex_pos;
+varying vec2 tex_nw;
+varying vec2 tex_ne;
+varying vec2 tex_sw;
+varying vec2 tex_se;
+
+const vec2 m_SpanMax = vec2(2.5, 2.5);
+const float m_ReduceMul = 0.15;
+const vec3 luma = vec3(0.299, 0.587, 0.114);
+
+#define FXAA_REDUCE_MIN   (1.0/128.0)
+
+//float FxaaLuma(float3 rgb) {
+//  return rgb.g * (0.587/0.299) + rgb.b;
+//}
+
+void
+main(){
+  vec2 pixel = u_pixel * 3.15;
+
+  vec4 rgbNW = texture2D(u_texColor, tex_nw);
+  vec4 rgbNE = texture2D(u_texColor, tex_ne);
+  vec4 rgbSW = texture2D(u_texColor, tex_sw);
+  vec4 rgbSE = texture2D(u_texColor, tex_se);
+
+  vec4 rgbM = texture2D(u_texColor, tex_pos);
+
+  if (rgbNW.a + rgbNE.a + rgbSW.a + rgbSE.a < 0.1) {
+    gl_FragColor = rgbM;
+    return;
+  }
+  //return vec4(rgbM - (rgbNW + rgbNE)*0.25,1.0);
+
+  float lumaNW = dot(rgbNW.rgb, luma);
+  float lumaNE = dot(rgbNE.rgb, luma);
+  float lumaSW = dot(rgbSW.rgb, luma);
+  float lumaSE = dot(rgbSE.rgb, luma);
+  float lumaM = dot(rgbM.rgb, luma);
+
+  float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+  float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+  //vec4 rgb = texture2D (tex, tex_pos);
+  //return vec4(0.5 + lumaM - lumaMin, lumaM, 0.5 + lumaM - lumaMax, 1.0) * rgb.a;
+
+  vec2 dir;
+  dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+  dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+//  if (max(dir.x, dir.y) > 0.1){
+//    gl_FragColor = vec4(dir*0.5, 0.0, 0.5);
+//  } else{
+//    gl_FragColor = vec4(rgbM.rgb * 0.2, 0.8);
+//  }
+//  return;
+
+  float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), FXAA_REDUCE_MIN);
+
+  float rcpDirMin = 1.0 / (dirReduce + min(abs(dir.x), abs(dir.y)));
+
+  dir = min(m_SpanMax, max(-m_SpanMax, dir * rcpDirMin)) * pixel;
+
+  vec4 rgbA = 0.5 * (texture2D(u_texColor, tex_pos + dir * vec2(1.0 / 3.0 - 0.5))
+      + texture2D(u_texColor, tex_pos + dir * vec2(2.0 / 3.0 - 0.5)));
+
+  vec4 rgbB = rgbA * 0.5 + 0.25 * (texture2D(u_texColor, tex_pos + dir * vec2(0.0 / 3.0 - 0.5))
+      + texture2D(u_texColor, tex_pos + dir * vec2(3.0 / 3.0 - 0.5)));
+
+  float lumaB = dot(rgbB.rgb, luma.rgb);
+
+  float d = step(lumaB, lumaMin) + step(lumaMax, lumaB);
+
+  gl_FragColor = (1.0 - d) * rgbB + d * rgbA;
+
+  //gl_FragColor = vec4(rgbM.rgb * 0.5, 1.0) + vec4(((1.0 - d) * rgbB.rgb + d * rgbA.rgb) - rgbM.rgb, 1.0) * 2.0;
+
+//  if ((lumaB < lumaMin) || (lumaB > lumaMax))
+//    { return rgbA; } else { return rgbB; }
+}
+
+//vec2 rcpFrame = vec2(1.0) / g_Resolution;
+//gl_FragColor = vec4(FxaaPixelShader(tex_pos, m_Texture, rcpFrame), 1.0);
+//gl_FragColor = FxaaPixelShader(tex_pos, u_texColor, u_pixel * 3.15);
+//gl_FragColor = FxaaPixelShader (tex_pos, u_texColor, u_pixel * 2.35);
+//vec4 c = texture2D (u_texColor, tex_pos);
+//gl_FragColor = vec4 (c.rgb * 0.5, 1.0) + vec4(FxaaPixelShader (tex_pos, u_texColor, u_pixel * 3.15).rgb - c.rgb, 1.0) * 2.0;
+//gl_FragColor = 0.2*c + (FxaaPixelShader (tex_pos, u_texColor, u_pixel * 1.2)) * 0.8;
+//}
diff --git a/vtm/resources/assets/shaders/post_fxaa.h b/vtm/resources/assets/shaders/post_fxaa.h
deleted file mode 100644
index a519b51b..00000000
--- a/vtm/resources/assets/shaders/post_fxaa.h
+++ /dev/null
@@ -1,116 +0,0 @@
-precision mediump float;
-uniform vec2 u_pixel;
-attribute vec4 a_pos;
-varying vec2 tex_pos;
-
-void
-main()
-{
-  gl_Position = a_pos;
-  tex_pos = (a_pos.xy + 1.0) * 0.5;
-  //tex_pos.zw = tex_pos.xz - u_pixel * vec2 (0.5);
-}
-§
-precision mediump float;
-//uniform sampler2D m_Texture;
-//uniform vec2 g_Resolution;
-//uniform vec2 g_Resolution;
-uniform sampler2D u_texColor;
-uniform vec2 u_pixel;
-varying vec2 tex_pos;
-
-//uniform float m_VxOffset;
-//uniform float m_SpanMax;
-//uniform float m_ReduceMul;
-
-const vec2 m_SpanMax = vec2(2.5, 2.5);
-const float m_ReduceMul = 0.15;
-
-//varying vec2 texCoord;
-//varying vec4 pos;
-
-//#define FxaaTex(t, p) texture2D(t, p)
-//#define OffsetVec(a, b) vec2(a, b)
-//#define FxaaTexOff(t, p, o, r) texture2D(t, p + o * r)
-// Output of FxaaVertexShader interpolated across screen.
-// Input texture.
-// Constant {1.0/frameWidth, 1.0/frameHeight}.
-
-#define FXAA_REDUCE_MIN   (1.0/128.0)
-
-//float FxaaLuma(float3 rgb) {
-//  return rgb.g * (0.587/0.299) + rgb.b;
-//}
-
-vec4
-FxaaPixelShader(vec2 pos, sampler2D tex, vec2 pixel){
-
-  //#define FXAA_REDUCE_MUL   (1.0/8.0)
-  //#define FXAA_SPAN_MAX     8.0
-
-  vec3 rgbNW = texture2D(tex, pos + vec2(-1.0, -1.0) * pixel).xyz;
-//	vec3 rgbNE = FxaaTexOff(tex, pos.zw, OffsetVec(1,0), pixel.xy).xyz;
-//	vec3 rgbSW = FxaaTexOff(tex, pos.zw, OffsetVec(0,1), pixel.xy).xyz;
-//	vec3 rgbSE = FxaaTexOff(tex, pos.zw, OffsetVec(1,1), pixel.xy).xyz;
-
-  vec3 rgbNE = texture2D(tex, pos + vec2(1.0, -1.0) * pixel).xyz;
-  vec3 rgbSW = texture2D(tex, pos + vec2(-1.0, 1.0) * pixel).xyz;
-  vec3 rgbSE = texture2D(tex, pos + vec2(1.0, 1.0) * pixel).xyz;
-
-  vec3 rgbM = texture2D(tex, pos).xyz;
-
-  //return vec4(rgbM - (rgbNW + rgbNE)*0.25,1.0);
-
-  vec3 luma = vec3(0.299, 0.587, 0.114);
-  float lumaNW = dot(rgbNW, luma);
-  float lumaNE = dot(rgbNE, luma);
-  float lumaSW = dot(rgbSW, luma);
-  float lumaSE = dot(rgbSE, luma);
-  float lumaM = dot(rgbM, luma);
-
-  float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
-  float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
-
-  //vec4 rgb = texture2D (tex, pos);
-  //return vec4(0.5 + lumaM - lumaMin, lumaM, 0.5 + lumaM - lumaMax, 1.0) * rgb.a;
-
-  vec2 dir;
-  dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
-  dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
-
-  //return vec4(dir*0.5, 0.5, 1.0);
-
-  float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), FXAA_REDUCE_MIN);
-
-  float rcpDirMin = 1.0 / (dirReduce + min(abs(dir.x), abs(dir.y)));
-
-  dir = min(m_SpanMax, max(-m_SpanMax, dir * rcpDirMin)) * pixel;
-
-  vec4 rgbA = 0.5 * (texture2D(tex, pos + dir * vec2(1.0 / 3.0 - 0.5))
-                   + texture2D(tex, pos + dir * vec2(2.0 / 3.0 - 0.5)));
-
-  vec4 rgbB = rgbA * 0.5 + 0.25 * (texture2D(tex, pos + dir * vec2(0.0 / 3.0 - 0.5))
-                                 + texture2D(tex, pos + dir * vec2(3.0 / 3.0 - 0.5)));
-
-  float lumaB = dot(rgbB.xyz, luma.xyz);
-
-  float d = step(lumaB, lumaMin) + step(lumaMax, lumaB);
-
-  return (1.0 - d) * rgbB + d * rgbA;
-
-  //  if ((lumaB < lumaMin) || (lumaB > lumaMax))
-  //    { return rgbA; } else { return rgbB; }
-}
-
-void
-main(){
-  //vec2 rcpFrame = vec2(1.0) / g_Resolution;
-  //gl_FragColor = vec4(FxaaPixelShader(pos, m_Texture, rcpFrame), 1.0);
-  gl_FragColor = FxaaPixelShader(tex_pos, u_texColor, u_pixel * 3.15);
-  //gl_FragColor = FxaaPixelShader (tex_pos, u_texColor, u_pixel * 2.35);
-
-  //vec4 c = texture2D (u_texColor, tex_pos);
-  //gl_FragColor = vec4 (c.rgb * 0.5, 1.0) + vec4(FxaaPixelShader (tex_pos, u_texColor, u_pixel * 3.15).rgb - c.rgb, 1.0) * 2.0;
-
-  //gl_FragColor = 0.2*c + (FxaaPixelShader (tex_pos, u_texColor, u_pixel * 1.2)) * 0.8;
-}
diff --git a/vtm/resources/assets/shaders/post_ssao.glsl b/vtm/resources/assets/shaders/post_ssao.glsl
new file mode 100644
index 00000000..37d3bea0
--- /dev/null
+++ b/vtm/resources/assets/shaders/post_ssao.glsl
@@ -0,0 +1,143 @@
+#ifdef GLES
+precision highp float;
+#endif
+uniform vec2 u_pixel;
+attribute vec4 a_pos;
+varying vec2 tex_pos;
+void
+main(){
+  gl_Position = a_pos;
+  tex_pos = (a_pos.xy + 1.0) * 0.5;
+}
+
+$$
+
+#ifdef GLES
+precision highp float;
+#endif
+uniform sampler2D u_tex;
+uniform sampler2D u_texColor;
+uniform vec2 u_pixel;
+
+varying vec2 tex_pos;
+// gauss bell center
+const float gdisplace = 0.2;
+const float nearZ = 1.0;
+const float farZ = 4.0;
+const int iterations = 4;
+
+float getDepth(float posZ) {
+  return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ));
+}
+float compareDepths(in float depth1, in float depth2, inout float far) {
+  //   depth difference (0-100)
+  float diff = (depth1 - depth2) * 100.0;
+  //   set 'far == 1.0' when 'diff' > 'gdisplace'
+  far = step(diff, gdisplace);
+  // gauss bell width 2,
+  // if far reduce left bell width to avoid self-shadowing
+  float garea = max((1.0 - far) * 2.0, 0.1);
+
+  //return (step(diff, 0.0) * -0.1) + pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));
+  return  pow(2.7182, -2.0 * pow(diff - gdisplace,2.0) / pow(garea, 2.0));
+}
+
+void
+addAO(in float depth, in float x1, in float y1, in float x2, in float y2, inout float ao){
+  float z_11 = getDepth(texture2D(u_tex, vec2(x1, y1)).x);
+  float z_12 = getDepth(texture2D(u_tex, vec2(x1, y2)).x);
+  float z_21 = getDepth(texture2D(u_tex, vec2(x2, y1)).x);
+  float z_22 = getDepth(texture2D(u_tex, vec2(x2, y2)).x);
+  //depth = 0.99 * depth + (z_11 + z_12 + z_21 + z_22) * (0.25 * 0.01);
+
+
+  float f_11;
+  float d_11 = compareDepths(depth, z_11, f_11);
+
+  float f_12;
+  float d_12 = compareDepths(depth, z_12, f_12);
+
+  float f_21;
+  float d_21 = compareDepths(depth, z_21, f_21);
+
+  float f_22;
+  float d_22 = compareDepths(depth, z_22, f_22);
+
+  ao += 1.0 //(1.0 - step(1.0, x1)) * (1.0 - step(1.0, y1))
+      * (d_11 + f_11 * (1.0 - d_11) * d_22);
+
+  ao += 1.0 //(1.0 - step(1.0, x1)) * step(0.0, y2)
+      * (d_12 + f_12 * (1.0 - d_12) * d_21);
+
+  ao += 1.0 //step(0.0, x2) * (1.0 - step(1.0, y1))
+      * (d_21 + f_21 * (1.0 - d_21) * d_12);
+
+  ao += 1.0 //step(0.0, x2) * step(0.0, y2)
+      * (d_22 + f_22 * (1.0 - d_22) * d_11);
+}
+
+void
+main(void){
+  //   randomization texture:
+  //	 vec2 fres = vec2(20.0, 20.0);
+  //	vec3 random = texture2D(rand, gl_TexCoord[0].st * fres.xy);
+  //	random = random * 2.0 - vec3(1.0);
+  vec4 color = texture2D(u_texColor, tex_pos);
+  float depth = texture2D(u_tex, tex_pos).x;
+
+  float fog = pow(depth,3.0);
+  //return;
+  depth = getDepth(depth);
+
+  float x = tex_pos.x;
+  float y = tex_pos.y;
+  float pw = u_pixel.x;
+  float ph = u_pixel.y;
+  float ao = 0.0;
+
+  for (int i = 0; i < iterations; i++) {
+    float pwByDepth = pw / depth;
+    float phByDepth = ph / depth;
+    addAO(depth, x + pwByDepth, y + phByDepth, x - pwByDepth, y - phByDepth, ao);
+    pwByDepth *= 1.2;
+    phByDepth *= 1.2;
+    addAO(depth, x + pwByDepth, y, x, y - phByDepth, ao);
+    // sample jittering:
+    //	pw += random.x * 0.0007;
+    //	ph += random.y * 0.0007;
+    // increase sampling area:
+    pw *= 1.7;
+    ph *= 1.7;
+
+  }
+
+  //vec3 vao = vec3(fog * pow(ao / float(iterations * 8), 1.2));
+  ao = ao / float(iterations * 8);
+  ao *= 0.2;
+  ao = clamp(ao, 0.0, 1.0);
+
+  vec3 vao = vec3(ao);
+
+  //gl_FragColor = vec4(0.5 - vao, max(0.5, ao));
+  gl_FragColor =  vec4(color.rgb - ao, max(color.a, ao));
+
+
+  //gl_FragColor =  color - (fog * vec4(vao, 0.0));
+
+
+  //gl_FragColor =  vec4(vec3(0.8) - vao, 1.0);
+
+  //color *= 0.5;
+
+  //gl_FragColor =  vec4(color.rgb - fog * vao, max(color.a, ao));
+
+
+  //gl_FragColor =  vec4(1.0) - (vec4(vao, 0.0));
+  //gl_FragColor =  vec4((color.rgb + vao)*0.5, color.a);
+
+  // }
+  //	 gl_FragColor = vec4(vao, 1.0) * texture2D(u_texColor, tex_pos.xy);
+  //	gl_FragColor = vec4(gl_TexCoord[0].xy,0.0,1.0);
+  //	gl_FragColor = vec4(tex_pos.xy,0.0,1.0);
+  //	 gl_FragColor = vec4(gl_FragCoord.xy / u_screen, 0.0, 1.0);
+}
diff --git a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
index 9cc9f211..92c1abc8 100644
--- a/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
+++ b/vtm/src/org/oscim/layers/tile/s3db/S3DBTileLoader.java
@@ -73,7 +73,7 @@ class S3DBTileLoader extends TileLoader {
 		layers.setExtrusionLayers(mRoofs);
 		tile.data = layers;
 
-		//process(mTilePlane);
+		process(mTilePlane);
 
 		try {
 			/* query database, which calls process() callback */
diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
index 8b14b461..cdb0ebe3 100644
--- a/vtm/src/org/oscim/renderer/OffscreenRenderer.java
+++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
@@ -21,8 +21,6 @@ public class OffscreenRenderer extends LayerRenderer {
 	public OffscreenRenderer(int w, int h) {
 		texW = w;
 		texH = h;
-		//texW = nearestPowerOf2(texW);
-		//texH = nearestPowerOf2(texH);
 	}
 
 	int nearestPowerOf2(int x) {
@@ -37,23 +35,17 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	boolean initialized;
 
-	private boolean useDepthTexture = false;
+	private boolean useDepthTexture = true;
 
 	protected boolean setup1(GLViewport viewport) {
 		IntBuffer buf = MapRenderer.getIntBuffer(1);
 
 		texW = (int) viewport.getWidth();
 		texH = (int) viewport.getHeight();
-		//texW = nearestPowerOf2(texW);
-		//texH = nearestPowerOf2(texH);
 
 		GL.glGenFramebuffers(1, buf);
 		fb = buf.get(0);
 
-		//		buf.clear();
-		//		GL.glGenRenderbuffers(1, buf);
-		//		depthRb = buf.get(0);
-
 		buf.clear();
 		GL.glGenTextures(1, buf);
 		renderTex = buf.get(0);
@@ -64,13 +56,13 @@ public class OffscreenRenderer extends LayerRenderer {
 		GL.glBindTexture(GL20.GL_TEXTURE_2D, renderTex);
 		GLUtils.checkGlError("0");
 
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
-		GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
+		GLUtils.setTextureParameter(GL20.GL_NEAREST,
+		                            GL20.GL_NEAREST,
+		                            GL20.GL_CLAMP_TO_EDGE,
+		                            GL20.GL_CLAMP_TO_EDGE);
 
-		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA,
-		                texW, texH, 0, GL20.GL_RGBA,
+		GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0,
+		                GL20.GL_RGBA, texW, texH, 0, GL20.GL_RGBA,
 		                GL20.GL_UNSIGNED_BYTE, null);
 
 		GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
@@ -84,11 +76,11 @@ public class OffscreenRenderer extends LayerRenderer {
 			buf.clear();
 			GL.glGenTextures(1, buf);
 			renderDepth = buf.get(0);
-
-			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, GL20.GL_CLAMP_TO_EDGE);
-			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, GL20.GL_CLAMP_TO_EDGE);
-			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_NEAREST);
-			GL.glTexParameteri(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_NEAREST);
+			GL.glBindTexture(GL20.GL_TEXTURE_2D, renderDepth);
+			GLUtils.setTextureParameter(GL20.GL_NEAREST,
+			                            GL20.GL_NEAREST,
+			                            GL20.GL_CLAMP_TO_EDGE,
+			                            GL20.GL_CLAMP_TO_EDGE);
 			GLUtils.checkGlError("1");
 
 			GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT,
@@ -97,10 +89,8 @@ public class OffscreenRenderer extends LayerRenderer {
 
 			GLUtils.checkGlError("11 " + texW + "  / " + texH);
 
-			GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
-			                          GL20.GL_DEPTH_ATTACHMENT,
-			                          GL20.GL_TEXTURE_2D,
-			                          renderDepth, 0);
+			GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER, GL20.GL_DEPTH_ATTACHMENT,
+			                          GL20.GL_TEXTURE_2D, renderDepth, 0);
 		} else {
 			buf.clear();
 			GL.glGenRenderbuffers(1, buf);
@@ -119,44 +109,24 @@ public class OffscreenRenderer extends LayerRenderer {
 		}
 
 		GLUtils.checkGlError("111");
-		// create render buffer and bind 16-bit depth buffer
-		//GL.glBindRenderbuffer(GL20.GL_RENDERBUFFER, depthRb);
-
-		//GL.glRenderbufferStorage(GL20.GL_RENDERBUFFER,
-		//                         GL20.GL_DEPTH_COMPONENT16,
-		//                         texW,
-		//                         texH);
-
-		GLUtils.checkGlError("2");
-
-		GLUtils.checkGlError("3");
-
-		//GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
-		//                          GL20.GL_COLOR_ATTACHMENT0,
-		//                          GL20.GL_TEXTURE_2D,
-		//                          renderTex, 0);
-		//
-		//GL.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER,
-		//                             GL20.GL_DEPTH_ATTACHMENT,
-		//                             GL20.GL_RENDERBUFFER,
-		//                             depthRb);
 
 		int status = GL.glCheckFramebufferStatus(GL20.GL_FRAMEBUFFER);
+		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
+		GL.glBindTexture(GL20.GL_TEXTURE_2D, 0);
+
 		if (status != GL20.GL_FRAMEBUFFER_COMPLETE) {
 			log.debug("invalid framebuffer!!! " + status);
 			return false;
 		}
 
-		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
-
 		//shader = GLShader.createProgram(vShader, fShader);
 		//shader = GLShader.createProgram(vShader, fSSAO);
 		//shader = GLShader.createProgram(vShader, fShaderFXAA);
-		shader = GLShader.loadShader("post_fxaa");
+		//shader = GLShader.loadShader("post_fxaa");
+		shader = GLShader.loadShader("post_combined");
 
-		//hTex = GL.glGetUniformLocation(shader, "u_tex");
+		hTex = GL.glGetUniformLocation(shader, "u_tex");
 		hTexColor = GL.glGetUniformLocation(shader, "u_texColor");
-		//hScreen = GL.glGetUniformLocation(shader, "u_screen");
 		hPixel = GL.glGetUniformLocation(shader, "u_pixel");
 		hPos = GL.glGetAttribLocation(shader, "a_pos");
 
@@ -165,10 +135,8 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	int shader;
 	int hPos;
-	//int hTex;
+	int hTex;
 	int hTexColor;
-
-	//int hScreen;
 	int hPixel;
 
 	public void enable(boolean on) {
@@ -197,7 +165,6 @@ public class OffscreenRenderer extends LayerRenderer {
 			initialized = true;
 		}
 		mRenderer.update(viewport);
-		//log.debug(">>> ist ready " + mRenderer.isReady());
 		setReady(mRenderer.isReady());
 	}
 
@@ -214,28 +181,21 @@ public class OffscreenRenderer extends LayerRenderer {
 		GL.glClear(GL20.GL_DEPTH_BUFFER_BIT | GL20.GL_COLOR_BUFFER_BIT);
 		//GL.glClear(GL20.GL_DEPTH_BUFFER_BIT);
 
-		GLUtils.checkGlError("-----");
 		((S3DBRenderer) mRenderer).render2(viewport);
-		GLUtils.checkGlError("----");
 
 		GL.glViewport(0, 0, (int) viewport.getWidth(), (int) viewport.getHeight());
 
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
 
-		GLUtils.checkGlError("--");
-
 		GLState.useProgram(shader);
-		GLUtils.checkGlError("-0");
 
 		// bind the framebuffer texture
-		//GL.glActiveTexture(GL20.GL_TEXTURE1);
-		//GLUtils.checkGlError("-1");
-
-		//GLState.bindTex2D(renderDepth);
-		//GL.glUniform1i(hTex, 1);
-		//GLUtils.checkGlError("-2");
-
-		GL.glActiveTexture(GL20.GL_TEXTURE0);
+		if (useDepthTexture) {
+			GL.glActiveTexture(GL20.GL_TEXTURE1);
+			GLState.bindTex2D(renderDepth);
+			GL.glUniform1i(hTex, 1);
+			GL.glActiveTexture(GL20.GL_TEXTURE0);
+		}
 		GLState.bindTex2D(renderTex);
 		GL.glUniform1i(hTexColor, 0);
 
@@ -245,12 +205,12 @@ public class OffscreenRenderer extends LayerRenderer {
 		GL.glUniform2f(hPixel, (float) (1.0 / texW * 0.5), (float) (1.0 / texH * 0.5));
 
 		GLState.enableVertexArrays(hPos, -1);
-		GLUtils.checkGlError("-3");
 
 		GLState.test(false, false);
 		GLState.blend(true);
 		GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
-		GLUtils.checkGlError("-4");
+
+		GLUtils.checkGlError("....");
 
 		//GL.glDepthRangef(1, -1);
 		//GL.glClearDepthf(1);

From a7897427a372f06e1f4ef31c8677c6ff1b391cdf Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Fri, 21 Mar 2014 00:38:07 +0100
Subject: [PATCH 4/5] wrap Offscreen renderer in S3DB/BuildingLayer

---
 .../oscim/android/test/S3DBMapActivity.java   | 15 ++--
 .../org/oscim/layers/tile/s3db/S3DBLayer.java | 19 ++---
 .../layers/tile/vector/BuildingLayer.java     | 28 ++++++--
 .../org/oscim/renderer/OffscreenRenderer.java | 72 ++++++-------------
 4 files changed, 63 insertions(+), 71 deletions(-)

diff --git a/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java b/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
index 8d234ac0..5ee41e64 100644
--- a/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/S3DBMapActivity.java
@@ -1,10 +1,8 @@
 package org.oscim.android.test;
 
 import org.oscim.android.cache.TileCache;
-import org.oscim.layers.GenericLayer;
 import org.oscim.layers.tile.TileLayer;
 import org.oscim.layers.tile.s3db.S3DBLayer;
-import org.oscim.renderer.OffscreenRenderer;
 import org.oscim.theme.VtmThemes;
 import org.oscim.tiling.TileSource;
 import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
@@ -20,6 +18,7 @@ public class S3DBMapActivity extends BaseMapActivity {
 		super.onCreate(savedInstanceState);
 
 		mMap.setTheme(VtmThemes.DEFAULT);
+
 		//mMap.setTheme(VtmThemes.TRONRENDER);
 		//mMap.setTheme(VtmThemes.OSMARENDER);
 
@@ -31,13 +30,15 @@ public class S3DBMapActivity extends BaseMapActivity {
 			ts.setCache(mS3dbCache);
 		}
 		TileLayer tl = new S3DBLayer(mMap, ts);
-		OffscreenRenderer or = new OffscreenRenderer(mMap.getWidth(),
-		                                             mMap.getHeight());
-		or.setRenderer(tl.getRenderer());
+		//OffscreenRenderer or = new OffscreenRenderer(mMap.getWidth(),
+		//                                             mMap.getHeight());
+		//or.setRenderer(tl.getRenderer());
 		mMap.layers().add(tl);
 
-		mMap.layers().add(new GenericLayer(mMap, or));
-		mMap.layers().add(new LabelLayer(mMap, mBaseLayer));
+		//mMap.layers().add(new GenericLayer(mMap, or));
+
+		//mMap.layers().add(new LabelLayer(mMap, mBaseLayer));
+		mMap.setMapPosition(53.08, 8.83, Math.pow(2, 17));
 	}
 
 	@Override
diff --git a/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java b/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
index 4f7db87a..df21c952 100644
--- a/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
+++ b/vtm/src/org/oscim/layers/tile/s3db/S3DBLayer.java
@@ -7,6 +7,7 @@ import org.oscim.layers.tile.TileRenderer;
 import org.oscim.map.Map;
 import org.oscim.renderer.ExtrusionRenderer;
 import org.oscim.renderer.GLViewport;
+import org.oscim.renderer.OffscreenRenderer;
 import org.oscim.tiling.TileSource;
 import org.oscim.utils.ColorUtil;
 import org.oscim.utils.ColorsCSS;
@@ -41,25 +42,27 @@ public class S3DBLayer extends TileLayer {
 
 	public static class S3DBRenderer extends TileRenderer {
 		ExtrusionRenderer mExtRenderer;
+		OffscreenRenderer or;
 
 		public S3DBRenderer() {
 			mExtRenderer = new ExtrusionRenderer(this, 16, true, false);
+
+			or = new OffscreenRenderer();
+			or.setRenderer(mExtRenderer);
 		}
 
 		@Override
 		protected synchronized void update(GLViewport v) {
 			super.update(v);
-			mExtRenderer.update(v);
-			setReady(mExtRenderer.isReady());
+			//mExtRenderer.update(v);
+			or.update(v);
+			setReady(or.isReady());
 		}
 
 		@Override
 		protected synchronized void render(GLViewport v) {
-			mExtRenderer.render(v);
-		}
-
-		public synchronized void render2(GLViewport v) {
-			mExtRenderer.render2(v);
+			or.render(v);
+			//mExtRenderer.render(v);
 		}
 	}
 
@@ -101,7 +104,7 @@ public class S3DBLayer extends TileLayer {
 			return Color.LTGRAY;
 
 		if ("transparent" == color)
-			return Color.get(128, 128, 128, 128);
+			return Color.get(0, 1, 1, 1);
 
 		Integer css = ColorsCSS.get(color);
 
diff --git a/vtm/src/org/oscim/layers/tile/vector/BuildingLayer.java b/vtm/src/org/oscim/layers/tile/vector/BuildingLayer.java
index 4abdfdb1..834b5f27 100644
--- a/vtm/src/org/oscim/layers/tile/vector/BuildingLayer.java
+++ b/vtm/src/org/oscim/layers/tile/vector/BuildingLayer.java
@@ -25,6 +25,7 @@ import org.oscim.layers.tile.vector.VectorTileLayer.TileLoaderThemeHook;
 import org.oscim.map.Map;
 import org.oscim.renderer.ExtrusionRenderer;
 import org.oscim.renderer.GLViewport;
+import org.oscim.renderer.OffscreenRenderer;
 import org.oscim.renderer.elements.ElementLayers;
 import org.oscim.renderer.elements.ExtrusionLayer;
 import org.oscim.theme.styles.ExtrusionStyle;
@@ -35,14 +36,22 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
 	//static final Logger log = LoggerFactory.getLogger(BuildingOverlay.class);
 
 	private final static int MIN_ZOOM = 17;
+	private final static boolean POST_AA = false;
+
 	private final int mMinZoom;
+	private ExtrusionRenderer mExtRenderer;
 
 	public BuildingLayer(Map map, VectorTileLayer tileLayer) {
-		super(map);
-		tileLayer.addHook(this);
+		this(map, tileLayer, MIN_ZOOM);
 
-		mMinZoom = MIN_ZOOM;
-		mRenderer = new ExtrusionRenderer(tileLayer.tileRenderer(), MIN_ZOOM);
+		//		super(map);
+		//		tileLayer.addHook(this);
+		//
+		//		mMinZoom = MIN_ZOOM;
+		//
+		//		OffscreenRenderer or = new OffscreenRenderer();
+		//		or.setRenderer(new ExtrusionRenderer(tileLayer.tileRenderer(), MIN_ZOOM));
+		//		mRenderer = or;
 	}
 
 	public BuildingLayer(Map map, VectorTileLayer tileLayer, int minZoom) {
@@ -50,8 +59,7 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
 		tileLayer.addHook(this);
 
 		mMinZoom = minZoom;
-		mRenderer = new ExtrusionRenderer(tileLayer.tileRenderer(), mMinZoom) {
-
+		mExtRenderer = new ExtrusionRenderer(tileLayer.tileRenderer(), mMinZoom) {
 			private long mStartTime;
 
 			@Override
@@ -90,6 +98,14 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
 				super.update(v);
 			}
 		};
+
+		if (POST_AA) {
+			OffscreenRenderer or = new OffscreenRenderer();
+			or.setRenderer(mExtRenderer);
+			mRenderer = or;
+		} else {
+			mRenderer = mExtRenderer;
+		}
 	}
 
 	private final float mFadeTime = 500;
diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
index cdb0ebe3..839f5ee3 100644
--- a/vtm/src/org/oscim/renderer/OffscreenRenderer.java
+++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
@@ -3,7 +3,6 @@ package org.oscim.renderer;
 import java.nio.IntBuffer;
 
 import org.oscim.backend.GL20;
-import org.oscim.layers.tile.s3db.S3DBLayer.S3DBRenderer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -11,31 +10,15 @@ public class OffscreenRenderer extends LayerRenderer {
 	final static Logger log = LoggerFactory.getLogger(OffscreenRenderer.class);
 
 	int fb;
-	//int depthRb;
 	int renderTex;
 	int renderDepth;
 
-	int texW;
-	int texH;
-
-	public OffscreenRenderer(int w, int h) {
-		texW = w;
-		texH = h;
-	}
-
-	int nearestPowerOf2(int x) {
-		--x;
-		x |= x >> 1;
-		x |= x >> 2;
-		x |= x >> 4;
-		x |= x >> 8;
-		x |= x >> 16;
-		return ++x;
-	}
+	int texW = -1;
+	int texH = -1;
 
 	boolean initialized;
 
-	private boolean useDepthTexture = true;
+	private boolean useDepthTexture = false;
 
 	protected boolean setup1(GLViewport viewport) {
 		IntBuffer buf = MapRenderer.getIntBuffer(1);
@@ -50,11 +33,12 @@ public class OffscreenRenderer extends LayerRenderer {
 		GL.glGenTextures(1, buf);
 		renderTex = buf.get(0);
 
+		GLUtils.checkGlError("0");
+
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
 
 		// generate color texture
 		GL.glBindTexture(GL20.GL_TEXTURE_2D, renderTex);
-		GLUtils.checkGlError("0");
 
 		GLUtils.setTextureParameter(GL20.GL_NEAREST,
 		                            GL20.GL_NEAREST,
@@ -69,8 +53,7 @@ public class OffscreenRenderer extends LayerRenderer {
 		                          GL20.GL_COLOR_ATTACHMENT0,
 		                          GL20.GL_TEXTURE_2D,
 		                          renderTex, 0);
-
-		GLUtils.checkGlError("00");
+		GLUtils.checkGlError("1");
 
 		if (useDepthTexture) {
 			buf.clear();
@@ -81,16 +64,17 @@ public class OffscreenRenderer extends LayerRenderer {
 			                            GL20.GL_NEAREST,
 			                            GL20.GL_CLAMP_TO_EDGE,
 			                            GL20.GL_CLAMP_TO_EDGE);
-			GLUtils.checkGlError("1");
 
-			GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_DEPTH_COMPONENT,
-			                texW, texH, 0, GL20.GL_DEPTH_COMPONENT,
+			GL.glTexImage2D(GL20.GL_TEXTURE_2D, 0,
+			                GL20.GL_DEPTH_COMPONENT,
+			                texW, texH, 0,
+			                GL20.GL_DEPTH_COMPONENT,
 			                GL20.GL_UNSIGNED_SHORT, null);
 
-			GLUtils.checkGlError("11 " + texW + "  / " + texH);
-
-			GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER, GL20.GL_DEPTH_ATTACHMENT,
-			                          GL20.GL_TEXTURE_2D, renderDepth, 0);
+			GL.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
+			                          GL20.GL_DEPTH_ATTACHMENT,
+			                          GL20.GL_TEXTURE_2D,
+			                          renderDepth, 0);
 		} else {
 			buf.clear();
 			GL.glGenRenderbuffers(1, buf);
@@ -108,14 +92,14 @@ public class OffscreenRenderer extends LayerRenderer {
 			                             depthRenderbuffer);
 		}
 
-		GLUtils.checkGlError("111");
+		GLUtils.checkGlError("2");
 
 		int status = GL.glCheckFramebufferStatus(GL20.GL_FRAMEBUFFER);
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
 		GL.glBindTexture(GL20.GL_TEXTURE_2D, 0);
 
 		if (status != GL20.GL_FRAMEBUFFER_COMPLETE) {
-			log.debug("invalid framebuffer!!! " + status);
+			log.debug("invalid framebuffer! " + status);
 			return false;
 		}
 
@@ -159,7 +143,7 @@ public class OffscreenRenderer extends LayerRenderer {
 	}
 
 	@Override
-	protected void update(GLViewport viewport) {
+	public void update(GLViewport viewport) {
 		if (!initialized) {
 			setup1(viewport);
 			initialized = true;
@@ -169,21 +153,15 @@ public class OffscreenRenderer extends LayerRenderer {
 	}
 
 	@Override
-	protected void render(GLViewport viewport) {
+	public void render(GLViewport viewport) {
 		//begin();
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
 		GL.glViewport(0, 0, texW, texH);
 		GL.glDepthMask(true);
-		//GL.glViewport(0, 0, this.texW, this.texH);
 		GL.glClearColor(0, 0, 0, 0);
-		//GL.glDepthRangef(0, 1);
-		//GL.glClearDepthf(1);
 		GL.glClear(GL20.GL_DEPTH_BUFFER_BIT | GL20.GL_COLOR_BUFFER_BIT);
-		//GL.glClear(GL20.GL_DEPTH_BUFFER_BIT);
 
-		((S3DBRenderer) mRenderer).render2(viewport);
-
-		GL.glViewport(0, 0, (int) viewport.getWidth(), (int) viewport.getHeight());
+		mRenderer.render(viewport);
 
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
 
@@ -201,21 +179,15 @@ public class OffscreenRenderer extends LayerRenderer {
 
 		MapRenderer.bindQuadVertexVBO(hPos, true);
 
-		//GL.glUniform2f(hScreen, texW, texH);
-		GL.glUniform2f(hPixel, (float) (1.0 / texW * 0.5), (float) (1.0 / texH * 0.5));
+		GL.glUniform2f(hPixel,
+		               (float) (1.0 / texW * 0.5),
+		               (float) (1.0 / texH * 0.5));
 
 		GLState.enableVertexArrays(hPos, -1);
 
 		GLState.test(false, false);
 		GLState.blend(true);
 		GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
-
 		GLUtils.checkGlError("....");
-
-		//GL.glDepthRangef(1, -1);
-		//GL.glClearDepthf(1);
-
-		//GL.glActiveTexture(GL20.GL_TEXTURE1);
-
 	}
 }

From a6df240b8b716444d43ab2f68101a91fd2da0f60 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Sat, 22 Mar 2014 04:31:20 +0100
Subject: [PATCH 5/5] use GLShader for OffscreenRenderer

---
 vtm/src/org/oscim/renderer/MapRenderer.java   |  1 +
 .../org/oscim/renderer/OffscreenRenderer.java | 64 ++++++++++---------
 2 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/vtm/src/org/oscim/renderer/MapRenderer.java b/vtm/src/org/oscim/renderer/MapRenderer.java
index cc9c17a0..f72e6734 100644
--- a/vtm/src/org/oscim/renderer/MapRenderer.java
+++ b/vtm/src/org/oscim/renderer/MapRenderer.java
@@ -320,6 +320,7 @@ public class MapRenderer {
 		GLState.init(GL);
 		GLUtils.init(GL);
 		GLShader.init(GL);
+		OffscreenRenderer.init(GL);
 
 		// Set up some vertex buffer objects
 		BufferObject.init(GL, 200);
diff --git a/vtm/src/org/oscim/renderer/OffscreenRenderer.java b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
index 839f5ee3..8d3fa863 100644
--- a/vtm/src/org/oscim/renderer/OffscreenRenderer.java
+++ b/vtm/src/org/oscim/renderer/OffscreenRenderer.java
@@ -20,7 +20,20 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	private boolean useDepthTexture = false;
 
-	protected boolean setup1(GLViewport viewport) {
+	static class Shader extends GLShader {
+		int aPos, uTexDepth, uTexColor, uPixel;
+
+		Shader(String shaderFile) {
+			if (!create(shaderFile))
+				return;
+			aPos = getAttrib("a_pos");
+			uTexColor = getUniform("u_texColor");
+			uTexDepth = getUniform("u_tex");
+			uPixel = getUniform("u_pixel");
+		}
+	}
+
+	protected boolean setupFBO(GLViewport viewport) {
 		IntBuffer buf = MapRenderer.getIntBuffer(1);
 
 		texW = (int) viewport.getWidth();
@@ -102,26 +115,17 @@ public class OffscreenRenderer extends LayerRenderer {
 			log.debug("invalid framebuffer! " + status);
 			return false;
 		}
-
-		//shader = GLShader.createProgram(vShader, fShader);
-		//shader = GLShader.createProgram(vShader, fSSAO);
-		//shader = GLShader.createProgram(vShader, fShaderFXAA);
-		//shader = GLShader.loadShader("post_fxaa");
-		shader = GLShader.loadShader("post_combined");
-
-		hTex = GL.glGetUniformLocation(shader, "u_tex");
-		hTexColor = GL.glGetUniformLocation(shader, "u_texColor");
-		hPixel = GL.glGetUniformLocation(shader, "u_pixel");
-		hPos = GL.glGetAttribLocation(shader, "a_pos");
-
 		return true;
 	}
 
-	int shader;
-	int hPos;
-	int hTex;
-	int hTexColor;
-	int hPixel;
+	static void init(GL20 gl20) {
+		GL = gl20;
+		shaders[0] = new Shader("post_fxaa");
+		shaders[1] = new Shader("post_ssao");
+		shaders[2] = new Shader("post_combined");
+	}
+
+	static Shader[] shaders = new Shader[3];
 
 	public void enable(boolean on) {
 		if (on)
@@ -144,17 +148,15 @@ public class OffscreenRenderer extends LayerRenderer {
 
 	@Override
 	public void update(GLViewport viewport) {
-		if (!initialized) {
-			setup1(viewport);
-			initialized = true;
-		}
+		if (texW != viewport.getWidth() || texH != viewport.getHeight())
+			setupFBO(viewport);
+
 		mRenderer.update(viewport);
 		setReady(mRenderer.isReady());
 	}
 
 	@Override
 	public void render(GLViewport viewport) {
-		//begin();
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb);
 		GL.glViewport(0, 0, texW, texH);
 		GL.glDepthMask(true);
@@ -165,25 +167,27 @@ public class OffscreenRenderer extends LayerRenderer {
 
 		GL.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
 
-		GLState.useProgram(shader);
+		Shader s = shaders[0];
+		s.useProgram();
 
-		// bind the framebuffer texture
+		/* bind depth texture */
 		if (useDepthTexture) {
 			GL.glActiveTexture(GL20.GL_TEXTURE1);
 			GLState.bindTex2D(renderDepth);
-			GL.glUniform1i(hTex, 1);
+			GL.glUniform1i(s.uTexDepth, 1);
 			GL.glActiveTexture(GL20.GL_TEXTURE0);
 		}
+		/* bind color texture */
 		GLState.bindTex2D(renderTex);
-		GL.glUniform1i(hTexColor, 0);
+		GL.glUniform1i(s.uTexColor, 0);
 
-		MapRenderer.bindQuadVertexVBO(hPos, true);
+		MapRenderer.bindQuadVertexVBO(s.aPos, true);
 
-		GL.glUniform2f(hPixel,
+		GL.glUniform2f(s.uPixel,
 		               (float) (1.0 / texW * 0.5),
 		               (float) (1.0 / texH * 0.5));
 
-		GLState.enableVertexArrays(hPos, -1);
+		GLState.enableVertexArrays(s.aPos, -1);
 
 		GLState.test(false, false);
 		GLState.blend(true);