From 0fb0aa59c2cee5de31bbd3d9386aedde481c7359 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Thu, 20 Mar 2014 13:28:41 +0100
Subject: [PATCH] use GLShader for PolygonLayer

---
 .../{simple_shader.glsl => base_shader.glsl}  |   6 +-
 .../assets/shaders/polygon_layer_tex.glsl     |  28 ++
 .../oscim/renderer/elements/PolygonLayer.java | 243 ++++++------------
 3 files changed, 115 insertions(+), 162 deletions(-)
 rename vtm/resources/assets/shaders/{simple_shader.glsl => base_shader.glsl} (83%)
 create mode 100644 vtm/resources/assets/shaders/polygon_layer_tex.glsl

diff --git a/vtm/resources/assets/shaders/simple_shader.glsl b/vtm/resources/assets/shaders/base_shader.glsl
similarity index 83%
rename from vtm/resources/assets/shaders/simple_shader.glsl
rename to vtm/resources/assets/shaders/base_shader.glsl
index 174ce389..9bf76a97 100644
--- a/vtm/resources/assets/shaders/simple_shader.glsl
+++ b/vtm/resources/assets/shaders/base_shader.glsl
@@ -1,11 +1,15 @@
+#ifdef GLES
 precision mediump float;
+#endif
 uniform mat4 u_mvp;
 attribute vec4 a_pos;
 void main() {
 	gl_Position = u_mvp * a_pos;
 }
-ยง
+$$
+#ifdef GLES
 precision mediump float;
+#endif
 uniform vec4 u_color;
 void main() {
 	gl_FragColor = u_color;
diff --git a/vtm/resources/assets/shaders/polygon_layer_tex.glsl b/vtm/resources/assets/shaders/polygon_layer_tex.glsl
new file mode 100644
index 00000000..0dd6c92a
--- /dev/null
+++ b/vtm/resources/assets/shaders/polygon_layer_tex.glsl
@@ -0,0 +1,28 @@
+#ifdef GLES
+precision mediump float;
+#endif
+uniform mat4 u_mvp;
+uniform vec2 u_scale;
+attribute vec4 a_pos;
+varying vec2 v_st;
+varying vec2 v_st2;
+void
+main(){
+  v_st = clamp(a_pos.xy, 0.0, 1.0) * (2.0 / u_scale.y);
+  v_st2 = clamp(a_pos.xy, 0.0, 1.0) * (4.0 / u_scale.y);
+  gl_Position = u_mvp * a_pos;
+}
+$$
+
+#ifdef GLES
+precision mediump float;
+#endif
+uniform vec4 u_color;
+uniform sampler2D tex;
+uniform vec2 u_scale;
+varying vec2 v_st;
+varying vec2 v_st2;
+void
+main(){
+  gl_FragColor = mix(texture2D(tex, v_st), texture2D(tex, v_st2), u_scale.x);
+}
diff --git a/vtm/src/org/oscim/renderer/elements/PolygonLayer.java b/vtm/src/org/oscim/renderer/elements/PolygonLayer.java
index 1b9fdc16..7fa68e42 100644
--- a/vtm/src/org/oscim/renderer/elements/PolygonLayer.java
+++ b/vtm/src/org/oscim/renderer/elements/PolygonLayer.java
@@ -16,14 +16,10 @@
  */
 package org.oscim.renderer.elements;
 
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
 import org.oscim.backend.GL20;
 import org.oscim.core.GeometryBuffer;
 import org.oscim.core.Tile;
-import org.oscim.renderer.GLMatrix;
+import org.oscim.renderer.GLShader;
 import org.oscim.renderer.GLState;
 import org.oscim.renderer.GLUtils;
 import org.oscim.renderer.GLViewport;
@@ -117,9 +113,25 @@ public final class PolygonLayer extends RenderElement {
 		si.used = outPos;
 	}
 
+	static class Shader extends GLShader {
+		int uMVP, uColor, uScale, aPos;
+
+		Shader(String shaderFile) {
+			if (!create(shaderFile))
+				return;
+
+			uMVP = getUniform("u_mvp");
+			aPos = getAttrib("a_pos");
+
+			if (shaderFile == "polygon_layer_tex")
+				uScale = getUniform("u_scale");
+			else
+				uColor = getUniform("u_color");
+		}
+	}
+
 	public static final class Renderer {
 
-		private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
 		private static final int STENCIL_BITS = 8;
 		private final static int CLIP_BIT = 0x80;
 
@@ -127,40 +139,12 @@ public final class PolygonLayer extends RenderElement {
 
 		private static AreaStyle[] mAreaFills;
 
-		private static int numShaders = 2;
-		private static int polyShader = 0;
-		private static int texShader = 1;
-
-		private static int[] polygonProgram = new int[numShaders];
-
-		private static int[] hPolygonVertexPosition = new int[numShaders];
-		private static int[] hPolygonMatrix = new int[numShaders];
-		private static int[] hPolygonColor = new int[numShaders];
-		private static int[] hPolygonScale = new int[numShaders];
+		private static Shader polyShader;
+		private static Shader texShader;
 
 		static boolean init() {
-
-			for (int i = 0; i < numShaders; i++) {
-
-				// Set up the program for rendering polygons
-				if (i == 0) {
-					polygonProgram[i] = ShaderProgram.loadShader("simple_shader");
-					//polygonProgram[i] = GLUtils.createProgram(polygonVertexShader,
-					//                                         polygonFragmentShader);
-				} else if (i == 1) {
-					polygonProgram[i] = ShaderProgram.loadShader("poly_texture");
-				}
-
-				if (polygonProgram[i] == 0) {
-					log.error("Could not create polygon program.");
-					return false;
-				}
-				hPolygonMatrix[i] = GL.glGetUniformLocation(polygonProgram[i], "u_mvp");
-				hPolygonColor[i] = GL.glGetUniformLocation(polygonProgram[i], "u_color");
-				hPolygonScale[i] = GL.glGetUniformLocation(polygonProgram[i], "u_scale");
-
-				hPolygonVertexPosition[i] = GL.glGetAttribLocation(polygonProgram[i], "a_pos");
-			}
+			polyShader = new Shader("base_shader");
+			texShader = new Shader("polygon_layer_tex");
 
 			mAreaFills = new AreaStyle[STENCIL_BITS];
 
@@ -175,17 +159,18 @@ public final class PolygonLayer extends RenderElement {
 
 			/* do not modify stencil buffer */
 			GL.glStencilMask(0x00);
-			int shader = polyShader;
+			//int shader = polyShader;
+
+			Shader s = setShader(polyShader, v, false);
 
 			for (int c = start; c < end; c++) {
 				AreaStyle a = mAreaFills[c].current();
 
 				if (enableTexture && a.texture != null) {
-					shader = texShader;
-					setShader(texShader, v);
+					s = setShader(texShader, v, false);
 					float num = FastMath.clamp((Tile.SIZE / a.texture.width) >> 1, 1, Tile.SIZE);
 					float transition = Interpolation.exp5.apply(FastMath.clamp(scale - 1, 0, 1));
-					GL.glUniform2f(hPolygonScale[1], transition, div / num);
+					GL.glUniform2f(s.uScale, transition, div / num);
 
 					//if (a.texture.alpha);
 					GLState.blend(true);
@@ -202,17 +187,17 @@ public final class PolygonLayer extends RenderElement {
 					}
 					GLState.blend(true);
 
-					GLUtils.setColor(hPolygonColor[shader], a.color, f);
+					GLUtils.setColor(s.uColor, a.color, f);
 
 				} else if (a.blendScale > 0 && a.blendScale <= zoom) {
 					/* blend colors (not alpha) */
 					GLState.blend(false);
 
 					if (a.blendScale == zoom)
-						GLUtils.setColorBlend(hPolygonColor[shader],
-						                      a.color, a.blendColor, scale - 1.0f);
+						GLUtils.setColorBlend(s.uColor, a.color,
+						                      a.blendColor, scale - 1.0f);
 					else
-						GLUtils.setColor(hPolygonColor[shader], a.blendColor, 1);
+						GLUtils.setColor(s.uColor, a.blendColor, 1);
 
 				} else {
 					if (a.color < 0xff000000)
@@ -220,38 +205,37 @@ public final class PolygonLayer extends RenderElement {
 					else
 						GLState.blend(false);
 
-					GLUtils.setColor(hPolygonColor[shader], a.color, 1);
+					GLUtils.setColor(s.uColor, a.color, 1);
 				}
 
-				// set stencil buffer mask used to draw this layer
-				// also check that clip bit is set to avoid overdraw
-				// of other tiles
+				/* set stencil buffer mask used to draw this layer
+				 * also check that clip bit is set to avoid overdraw
+				 * of other tiles */
 				GL.glStencilFunc(GL20.GL_EQUAL, 0xff, CLIP_BIT | 1 << c);
 
 				/* draw tile fill coordinates */
 				GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
 
-				if (shader != polyShader) {
-					// disable texture shader
-					setShader(polyShader, v);
-					shader = polyShader;
-				}
+				/* disable texture shader */
+				if (s != polyShader)
+					s = setShader(polyShader, v, false);
 			}
 		}
 
 		// current layer to fill (0 - STENCIL_BITS-1)
 		private static int mCount;
 
-		private static void setShader(int shader, GLViewport v) {
-			GLState.useProgram(polygonProgram[shader]);
+		private static Shader setShader(Shader shader, GLViewport v, boolean first) {
+			if (shader.useProgram() || first) {
 
-			GLState.enableVertexArrays(hPolygonVertexPosition[shader], -1);
+				GLState.enableVertexArrays(shader.aPos, -1);
 
-			GL.glVertexAttribPointer(hPolygonVertexPosition[shader], 2,
-			                         GL20.GL_SHORT, false, 0,
-			                         POLYGON_VERTICES_DATA_POS_OFFSET);
+				GL.glVertexAttribPointer(shader.aPos, 2,
+				                         GL20.GL_SHORT, false, 0, 0);
 
-			v.mvp.setAsUniform(hPolygonMatrix[shader]);
+				v.mvp.setAsUniform(shader.uMVP);
+			}
+			return shader;
 		}
 
 		/**
@@ -281,7 +265,7 @@ public final class PolygonLayer extends RenderElement {
 
 			GLState.test(false, true);
 
-			setShader(polyShader, v);
+			setShader(polyShader, v, first);
 
 			int zoom = v.pos.zoomLevel;
 			float scale = (float) v.pos.getZoomScale();
@@ -346,7 +330,7 @@ public final class PolygonLayer extends RenderElement {
 		}
 
 		public static void clip(GLViewport v) {
-			setShader(polyShader, v);
+			setShader(polyShader, v, true);
 
 			drawStencilRegion(true, 1);
 			/* disable writes to stencil buffer */
@@ -413,10 +397,11 @@ public final class PolygonLayer extends RenderElement {
 		 * and 'alpha' to fake a fade effect.
 		 */
 		public static void drawOver(GLViewport v, int color, float alpha) {
-			setShader(polyShader, v);
+			// TODO true could be avoided when same shader and vbo
+			setShader(polyShader, v, true);
 
 			if (color != 0) {
-				GLUtils.setColor(hPolygonColor[0], color, alpha);
+				GLUtils.setColor(polyShader.uColor, color, alpha);
 				GLState.blend(true);
 			} else {
 				/* disable drawing to framebuffer (will be re-enabled in fill) */
@@ -441,103 +426,39 @@ public final class PolygonLayer extends RenderElement {
 				GL.glColorMask(true, true, true, true);
 		}
 
-		private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
-		private static float[] debugFillColor2 = { .8f, .8f, .8f, .8f };
-		private static FloatBuffer mDebugFill;
+		//private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
+		//private static float[] debugFillColor2 = { .8f, .8f, .8f, .8f };
+		//private static FloatBuffer mDebugFill;
 
-		static void debugDraw(GLMatrix m, float[] coords, int color) {
-			GLState.test(false, false);
-			if (mDebugFill == null) {
-				mDebugFill = ByteBuffer
-				    .allocateDirect(32)
-				    .order(ByteOrder.nativeOrder())
-				    .asFloatBuffer();
-				mDebugFill.put(coords);
-			}
-
-			GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
-
-			mDebugFill.position(0);
-			GLState.useProgram(polygonProgram[0]);
-			GL.glEnableVertexAttribArray(hPolygonVertexPosition[0]);
-
-			GL.glVertexAttribPointer(hPolygonVertexPosition[0], 2, GL20.GL_FLOAT,
-			                         false, 0, mDebugFill);
-
-			m.setAsUniform(hPolygonMatrix[0]);
-
-			if (color == 0)
-				GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor);
-			else
-				GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor2);
-
-			GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
-
-			GLUtils.checkGlError("draw debug");
-		}
-
-		//		private final static String polygonVertexShader = ""
-		//		        + "precision mediump float;"
-		//		        + "uniform mat4 u_mvp;"
-		//		        + "attribute vec4 a_pos;"
-		//		        + "void main() {"
-		//		        + "  gl_Position = u_mvp * a_pos;"
-		//		        + "}";
+		//static void debugDraw(GLMatrix m, float[] coords, int color) {
+		//	GLState.test(false, false);
+		//	if (mDebugFill == null) {
+		//		mDebugFill = ByteBuffer
+		//		    .allocateDirect(32)
+		//		    .order(ByteOrder.nativeOrder())
+		//		    .asFloatBuffer();
+		//		mDebugFill.put(coords);
+		//	}
 		//
-		//		private final static String polygonFragmentShader = ""
-		//		        + "precision mediump float;"
-		//		        + "uniform vec4 u_color;"
-		//		        + "void main() {"
-		//		        + "  gl_FragColor = u_color;"
-		//		        + "}";
-
-		//		private final static String polygonVertexShaderZ = ""
-		//		        + "precision highp float;"
-		//		        + "uniform mat4 u_mvp;"
-		//		        + "attribute vec4 a_pos;"
-		//		        + "varying float z;"
-		//		        + "void main() {"
-		//		        + "  gl_Position = u_mvp * a_pos;"
-		//		        + "  z = gl_Position.z;"
-		//		        + "}";
-		//		private final static String polygonFragmentShaderZ = ""
-		//		        + "precision highp float;"
-		//		        + "uniform vec4 u_color;"
-		//		        + "varying float z;"
-		//		        + "void main() {"
-		//		        + "if (z < -1.0)"
-		//		        + "  gl_FragColor = vec4(0.0, z + 2.0, 0.0, 1.0)*0.8;"
-		//		        + "else if (z < 0.0)"
-		//		        + "  gl_FragColor = vec4(z + 1.0, 0.0, 0.0, 1.0)*0.8;"
-		//		        + "else if (z < 1.0)"
-		//		        + "  gl_FragColor = vec4(0.0, 0.0, z, 1.0)*0.8;"
-		//		        + "else"
-		//		        + "  gl_FragColor = vec4(0.0, z - 1.0, 0.0, 1.0)*0.8;"
-		//		        + "}";
-
-		//		private final static String textureVertexShader = ""
-		//		        + "precision mediump float;"
-		//		        + "uniform mat4 u_mvp;"
-		//		        + "uniform vec2 u_scale;"
-		//		        + "attribute vec4 a_pos;"
-		//		        + "varying vec2 v_st;"
-		//		        + "varying vec2 v_st2;"
-		//		        + "void main() {"
-		//		        + "  v_st = clamp(a_pos.xy, 0.0, 1.0) * (2.0 / u_scale.y);"
-		//		        + "  v_st2 = clamp(a_pos.xy, 0.0, 1.0) * (4.0 / u_scale.y);"
-		//		        + "  gl_Position = u_mvp * a_pos;"
-		//		        + "}";
+		//	GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
 		//
-		//		private final static String textureFragmentShader = ""
-		//		        + "precision mediump float;"
-		//		        + "uniform vec4 u_color;"
-		//		        + "uniform sampler2D tex;"
-		//		        + "uniform vec2 u_scale;"
-		//		        + "varying vec2 v_st;"
-		//		        + "varying vec2 v_st2;"
-		//		        + "void main() {"
-		//		        + "  gl_FragColor = mix(texture2D(tex, v_st), texture2D(tex, v_st2), u_scale.x);"
-		//		        + "}";
+		//	mDebugFill.position(0);
+		//	GLState.useProgram(polygonProgram[0]);
+		//	GL.glEnableVertexAttribArray(hPolygonVertexPosition[0]);
+		//
+		//	GL.glVertexAttribPointer(hPolygonVertexPosition[0], 2, GL20.GL_FLOAT,
+		//	                         false, 0, mDebugFill);
+		//
+		//	m.setAsUniform(hPolygonMatrix[0]);
+		//
+		//	if (color == 0)
+		//		GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor);
+		//	else
+		//		GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor2);
+		//
+		//	GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
+		//
+		//	GLUtils.checkGlError("draw debug");
+		//}
 	}
-
 }