diff --git a/src/org/oscim/renderer/LineTexRenderer.java b/src/org/oscim/renderer/LineTexRenderer.java index 74524bdd..01028c31 100644 --- a/src/org/oscim/renderer/LineTexRenderer.java +++ b/src/org/oscim/renderer/LineTexRenderer.java @@ -23,6 +23,7 @@ import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layers; import org.oscim.renderer.layer.LineLayer; import org.oscim.renderer.layer.LineTexLayer; +import org.oscim.theme.renderinstruction.Line; import org.oscim.utils.GlUtils; import android.opengl.GLES20; @@ -45,15 +46,16 @@ public class LineTexRenderer { private static int hTexColor; private static int hBgColor; private static int hScale; + private static int hPatternScale; private static int hWidth; private static int mIndicesBufferID; private static int mVertexFlipID; - // draw up to 100 quads in one round + // batch up up to 100 quads in one draw call private static int maxQuads = 100; private static int maxIndices = maxQuads * 6; - private static int mTexID; + private static int[] mTexID; public static void init() { shader = GlUtils.createProgram(vertexShader, fragmentShader); @@ -66,6 +68,7 @@ public class LineTexRenderer { hTexColor = GLES20.glGetUniformLocation(shader, "u_color"); hBgColor = GLES20.glGetUniformLocation(shader, "u_bgcolor"); hScale = GLES20.glGetUniformLocation(shader, "u_scale"); + hPatternScale = GLES20.glGetUniformLocation(shader, "u_pscale"); hWidth = GLES20.glGetUniformLocation(shader, "u_width"); hVertexPosition0 = GLES20.glGetAttribLocation(shader, "a_pos0"); @@ -115,14 +118,13 @@ public class LineTexRenderer { GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); + mTexID = new int[10]; + byte[] stipple = new byte[2]; - stipple[0] = 8; - stipple[1] = 8; - //stipple[2] = 16; - //stipple[3] = 48; - - mTexID = GlUtils.loadStippleTexture(stipple); + stipple[0] = 32; + stipple[1] = 32; + mTexID[0] = GlUtils.loadStippleTexture(stipple); } private final static int STRIDE = 12; @@ -144,12 +146,7 @@ public class LineTexRenderer { GLES20.glUniformMatrix4fv(hMatrix, 1, false, matrix, 0); - GLES20.glUniform4f(hTexColor, 1.0f, 1.0f, 1.0f, 1.0f); - //aa9988 - GLES20.glUniform4f(hBgColor, 0x99 / 255f, 0x96 / 255f, 0x93 / 255f, 0.95f); - - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); @@ -160,21 +157,37 @@ public class LineTexRenderer { GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id); - int offset = layers.texLineOffset; - float s = pos.scale / div; + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID[0]); + Layer l = curLayer; while (l != null && l.type == Layer.TEXLINE) { LineTexLayer ll = (LineTexLayer) l; - //Line line = ll.line; + Line line = ll.line; + + if (line.stippleColor == null) + GLES20.glUniform4f(hTexColor, 1.0f, 1.0f, 1.0f, 1.0f); + else + GLES20.glUniform4fv(hTexColor, 1, line.stippleColor, 0); + + GLES20.glUniform4fv(hBgColor, 1, line.color, 0); + + //GLES20.glUniform4f(hBgColor, 0x99 / 255f, 0x96 / 255f, 0x93 / 255f, 0.95f); // scale pattern to twice its size, then reset scale to 1. // (coord scale * pattern size) / scale - GLES20.glUniform1f(hScale, (8 * 16) / Math.max((int)(s+0.25f), 1)); + GLES20.glUniform1f(hPatternScale, (8 * (64 / line.stipple)) / Math.max((int) s, 1)); + //float f = Math.max((int)(s), 1); + //Log.d(TAG, s + " : " + f); + //GLES20.glUniform1f(hPatternScale, (8 * line.stipple) / 1); + GLES20.glUniform1f(hScale, pos.scale); GLES20.glUniform1f(hWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE); + // add offset vertex + int vOffset = -STRIDE; + // first pass int allIndices = (ll.evenQuads * 6); for (int i = 0; i < allIndices; i += maxIndices) { @@ -183,7 +196,7 @@ public class LineTexRenderer { numIndices = maxIndices; // i / 6 * (24 shorts per block * 2 short bytes) - int add = offset + i * 8; + int add = (l.offset + i * 8) + vOffset;; GLES20.glVertexAttribPointer(hVertexPosition0, 4, GLES20.GL_SHORT, false, STRIDE, @@ -212,7 +225,7 @@ public class LineTexRenderer { if (numIndices > maxIndices) numIndices = maxIndices; // i / 6 * (24 shorts per block * 2 short bytes) - int add = offset + i * 8; + int add = (l.offset + i * 8) + vOffset; GLES20.glVertexAttribPointer(hVertexPosition0, 4, GLES20.GL_SHORT, false, STRIDE, @@ -255,7 +268,7 @@ public class LineTexRenderer { + "precision mediump float;" + "uniform mat4 u_mvp;" + "uniform vec4 u_color;" - + "uniform float u_scale;" + + "uniform float u_pscale;" + "uniform float u_width;" + "attribute vec4 a_pos0;" + "attribute vec4 a_pos1;" @@ -264,20 +277,41 @@ public class LineTexRenderer { + "attribute float a_flip;" + "varying vec2 v_st;" + "void main() {" - // coord scale 8 * pattern length 16 - //+ " float div = (8.0 * 16.0) / max(ceil(log(u_scale)),1.0);" - + " float div = u_scale;" + + " vec4 pos;" + " if (a_flip == 0.0){" + " vec2 dir = u_width * a_pos0.zw;" - + " gl_Position = u_mvp * vec4(a_pos0.xy + dir, 0.0, 1.0);" - + " v_st = vec2(a_len0.x/div, 1.0);" - + " }else {" + + " pos = vec4(a_pos0.xy + dir, 0.0, 1.0);" + + " v_st = vec2(a_len0.x / u_pscale, 1.0);" + + " } else {" + " vec2 dir = u_width * a_pos1.zw ;" - + " gl_Position = u_mvp * vec4(a_pos1.xy - dir, 0.0, 1.0);" - + " v_st = vec2(a_len1.x/div, -1.0);" - + " }" + + " pos = vec4(a_pos1.xy - dir, 0.0, 1.0);" + + " v_st = vec2(a_len1.x / u_pscale, -1.0);" + + " }" + + " gl_Position = u_mvp * pos;" + "}"; + /* + final static String fragmentShader = "" + + "#extension GL_OES_standard_derivatives : enable\n" + + " precision mediump float;" + + " uniform sampler2D tex;" + + " uniform float u_scale;" + + " uniform vec4 u_color;" + + " uniform vec4 u_bgcolor;" + + " varying vec2 v_st;" + + " void main() {" + + " float len = texture2D(tex, v_st).a;" + + " float tex_w = abs(v_st.t);" + + " vec2 st_width = fwidth(v_st);" + + " float fuzz = max(st_width.s, st_width.t);" + //+ " float fuzz = fwidth(v_st.t);" + //+ " float line_w = 1.0 - smoothstep(1.0 - fuzz, 1.0, tex_w);" + //+ " float stipple_w = 1.0 - smoothstep(0.7 - fuzz, 0.7, tex_w);" + + " float stipple_p = 1.0 - smoothstep(1.0 - fuzz, 1.0, length(vec2(len*u_scale, v_st.t)));" + + " gl_FragColor = u_bgcolor * stipple_p;" + // + " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));" + + "}"; //*/ + //* final static String fragmentShader = "" + "#extension GL_OES_standard_derivatives : enable\n" + "precision mediump float;" @@ -294,6 +328,6 @@ public class LineTexRenderer { + " float stipple_w = (1.0 - smoothstep(0.7 - fuzz, 0.7, tex_w));" + " float stipple_p = smoothstep(0.495, 0.505, len);" + " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));" - + "}"; + + "}"; //*/ } diff --git a/src/org/oscim/renderer/layer/Layers.java b/src/org/oscim/renderer/layer/Layers.java index 4d2c1010..05499077 100644 --- a/src/org/oscim/renderer/layer/Layers.java +++ b/src/org/oscim/renderer/layer/Layers.java @@ -150,9 +150,17 @@ public class Layers { lineOffset = size * SHORT_BYTES; size += addLayerItems(sbuf, baseLayers, Layer.LINE, 0); - texLineOffset = size * SHORT_BYTES; - size += addLayerItems(sbuf, baseLayers, Layer.TEXLINE, 0); + for (Layer l = baseLayers; l != null; l= l.next){ + if (l.type == Layer.TEXLINE){ + // HACK, see LineTexLayer + //sbuf.position(sbuf.position() + 6); + addPoolItems(l, sbuf); + //l.offset -= 12; + } + } + + //size += addLayerItems(sbuf, baseLayers, Layer.TEXLINE, 0); for (Layer l = textureLayers; l != null; l = l.next) { TextureLayer tl = (TextureLayer) l; @@ -172,18 +180,10 @@ public class Layers { VertexPoolItem last = null, items = null; int size = 0; - // HACK, see LineTexLayer - boolean addOffset = (type == Layer.TEXLINE); - for (; l != null; l = l.next) { if (l.type != type) continue; - if (addOffset){ - sbuf.position(sbuf.position() + 6); - addOffset = false; - } - for (VertexPoolItem it = l.pool; it != null; it = it.next) { if (it.next == null){ size += it.used; @@ -199,6 +199,7 @@ public class Layers { continue; l.offset = pos; + pos += l.verticesCnt; last.next = items; diff --git a/src/org/oscim/renderer/layer/LineTexLayer.java b/src/org/oscim/renderer/layer/LineTexLayer.java index 75cb50b9..4f2a2712 100644 --- a/src/org/oscim/renderer/layer/LineTexLayer.java +++ b/src/org/oscim/renderer/layer/LineTexLayer.java @@ -21,6 +21,8 @@ import org.oscim.theme.renderinstruction.Line; /** * Layer for textured or stippled lines + * + * this would be all so much simpler with geometry shaders... */ public final class LineTexLayer extends Layer { // Interleave two segment quads in one block to be able to use @@ -57,6 +59,11 @@ public final class LineTexLayer extends Layer { // 2, 1, 3, // 4, 5, 6, // 6, 5, 7, + // + // BIG NOTE: renderer assumes to be able to offset vertex array position + // so that in the first pass 'pos1' offset will be < 0 if no data precedes + // - in our case there is always the polygon fill array at start + // - see addLine hack otherwise. private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER; // scale factor mapping extrusion vector to short values @@ -84,15 +91,11 @@ public final class LineTexLayer extends Layer { if (pool == null) { curItem = pool = VertexPool.get(); - // need to make sure there is one unused - // vertex in front for interleaving. - // HACK add this offset when compiling - // otherwise one cant use the full + // HACK add one vertex offset when compiling + // buffer otherwise one cant use the full // VertexItem - //curItem.used = 6; - - verticesCnt = 1; + //verticesCnt = 1; } VertexPoolItem si = curItem; @@ -207,14 +210,14 @@ public final class LineTexLayer extends Layer { pos += length; } + evenSegment = even; + // advance offset to last written position if (!even) opos += 12; si.used = opos; curItem = si; - - evenSegment = even; } @Override diff --git a/src/org/oscim/renderer/overlays/TestOverlay.java b/src/org/oscim/renderer/overlays/TestOverlay.java index 6eccd8de..a49c7cf8 100644 --- a/src/org/oscim/renderer/overlays/TestOverlay.java +++ b/src/org/oscim/renderer/overlays/TestOverlay.java @@ -18,8 +18,11 @@ import org.oscim.core.MapPosition; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.LineTexLayer; import org.oscim.renderer.layer.TextItem; +import org.oscim.theme.renderinstruction.Line; import org.oscim.view.MapView; +import android.graphics.Color; + public class TestOverlay extends BasicOverlay { TextItem labels; @@ -47,7 +50,8 @@ public class TestOverlay extends BasicOverlay { LineTexLayer lt = (LineTexLayer) layers.getLayer(2, Layer.TEXLINE); - lt.width = 4; + lt.line = new Line(Color.BLUE, 1.0f, 8); + lt.width = 8; lt.addLine(points, null); float[] points2 = { @@ -57,7 +61,9 @@ public class TestOverlay extends BasicOverlay { -200, 200, -200, -200 }; - + lt = (LineTexLayer) layers.getLayer(3, Layer.TEXLINE); + lt.line = new Line(Color.BLUE, 1.0f, 16); + lt.width = 8; lt.addLine(points2, null); // diff --git a/src/org/oscim/theme/renderinstruction/Line.java b/src/org/oscim/theme/renderinstruction/Line.java index 255fa80f..e01ea060 100644 --- a/src/org/oscim/theme/renderinstruction/Line.java +++ b/src/org/oscim/theme/renderinstruction/Line.java @@ -47,24 +47,40 @@ public final class Line extends RenderInstruction { */ public static Line create(Line line, String elementName, Attributes attributes, int level, boolean isOutline) { - String src = null; - int stroke = Color.BLACK; - float strokeWidth = 0; - int stipple = 0; - Cap strokeLinecap = Cap.ROUND; + + // Style name + String style = null; + // Bitmap + //String src = null; + + float width = 0; + Cap cap = Cap.ROUND; + + // Extras int fade = -1; boolean fixed = false; - String style = null; float blur = 0; float min = 0; + // Stipple + int stipple = 0; + float stippleWidth = 0; + + float[] color = null; + float[] stippleColor = null; + if (line != null) { + color = line.color; fixed = line.fixed; fade = line.fade; - strokeLinecap = line.cap; + cap = line.cap; blur = line.blur; min = line.min; + stipple = line.stipple; + stippleColor = line.stippleColor; + stippleWidth = line.stippleWidth; } + for (int i = 0; i < attributes.getLength(); ++i) { String name = attributes.getLocalName(i); String value = attributes.getValue(i); @@ -72,21 +88,27 @@ public final class Line extends RenderInstruction { if ("name".equals(name)) style = value; else if ("src".equals(name)) { - src = value; + //src = value; } else if ("stroke".equals(name)) { - stroke = Color.parseColor(value); + int stroke = Color.parseColor(value); + color = GlUtils.colorToFloatP(stroke); } else if ("width".equals(name)) { - strokeWidth = Float.parseFloat(value); + width = Float.parseFloat(value); + } else if ("cap".equals(name)) { + cap = Cap.valueOf(value.toUpperCase(Locale.ENGLISH)); + } else if ("fixed".equals(name)) { + fixed = Boolean.parseBoolean(value); } else if ("stipple".equals(name)) { stipple = Integer.parseInt(value); - } else if ("cap".equals(name)) { - strokeLinecap = Cap.valueOf(value.toUpperCase(Locale.ENGLISH)); + } else if ("stipple-stroke".equals(name)) { + int stroke = Color.parseColor(value); + stippleColor = GlUtils.colorToFloatP(stroke); + } else if ("stipple-width".equals(name)) { + stippleWidth = Float.parseFloat(value); } else if ("fade".equals(name)) { fade = Integer.parseInt(value); } else if ("min".equals(name)) { min = Float.parseFloat(value); - } else if ("fixed".equals(name)) { - fixed = Boolean.parseBoolean(value); } else if ("blur".equals(name)) { blur = Float.parseFloat(value); } else if ("from".equals(name)) { @@ -95,38 +117,27 @@ public final class Line extends RenderInstruction { } } - if (stipple != 0) - strokeLinecap = Cap.BUTT; + // hint that sth is missing + if (color == null) + color = GlUtils.colorToFloatP(Color.RED); + if (stipple != 0 && stippleColor == null) + stippleColor = GlUtils.colorToFloatP(Color.GREEN); + + // inherit properties from 'line' if (line != null) { + // use stroke width relative to 'line' + width = line.width + width; + if (width <= 0) + width = 1; - strokeWidth = line.width + strokeWidth; - if (strokeWidth <= 0) - strokeWidth = 1; - - return new Line(line, style, src, stroke, strokeWidth, stipple, - strokeLinecap, level, fixed, fade, blur, isOutline, min); + } else if (!isOutline) { + validate(width); } - if (!isOutline) - validate(strokeWidth); - - return new Line(style, src, stroke, strokeWidth, stipple, strokeLinecap, - level, fixed, fade, blur, isOutline, min); - } - - public Line(int stroke, float width, Cap cap) { - this.level = 0; - this.blur = 0; - this.cap = cap; - this.outline = false; - this.style = ""; - this.width = width; - this.fixed = true; - this.fade = -1; - this.stipple = 2; - this.min = 0; - color = GlUtils.colorToFloatP(stroke); + return new Line(level, style, color, width, cap, fixed, + stipple, stippleColor, stippleWidth, + fade, blur, isOutline, min); } private static void validate(float strokeWidth) { @@ -147,59 +158,28 @@ public final class Line extends RenderInstruction { private final int level; - public final float width; - - // public final boolean round; - - public final float color[]; - - public final boolean outline; - - public final boolean fixed; - - public final int fade; - public final String style; - + public final float width; + public final float[] color; public final Cap cap; - + public final boolean outline; + public final boolean fixed; + public final int fade; public final float blur; - - public final int stipple; - public final float min; - /** - * @param style - * ... - * @param src - * ... - * @param stroke - * ... - * @param strokeWidth - * ... - * @param stipple - * ... - * @param strokeLinecap - * ... - * @param level - * ... - * @param fixed - * ... - * @param fade - * ... - * @param blur - * ... - * @param isOutline - * ... - * @param min ... - */ - private Line(String style, String src, int stroke, float strokeWidth, - int stipple, Cap strokeLinecap, int level, boolean fixed, - int fade, float blur, boolean isOutline, float min) { - super(); + public final int stipple; + public final float[] stippleColor; + public final float stippleWidth; + private Line(int level, String style, float[] stroke, float width, + Cap cap, boolean fixed, + int stipple, float[] stippleColor, float stippleWidth, + int fade, float blur, boolean isOutline, float min) { + + this.level = level; this.style = style; + this.outline = isOutline; // paint = new Paint(Paint.ANTI_ALIAS_FLAG); // @@ -213,51 +193,55 @@ public final class Line extends RenderInstruction { // if (strokeDasharray != null) { // paint.setPathEffect(new DashPathEffect(strokeDasharray, 0)); // } - // paint.setStrokeCap(strokeLinecap); - // round = (strokeLinecap == Cap.ROUND); - - this.cap = strokeLinecap; - - color = GlUtils.colorToFloatP(stroke); - - this.width = strokeWidth; - this.level = level; - this.outline = isOutline; + this.cap = cap; + this.color = stroke; + this.width = width; this.fixed = fixed; + + this.stipple = stipple; + this.stippleColor = stippleColor; + this.stippleWidth = stippleWidth; + this.blur = blur; this.fade = fade; - this.stipple = stipple; this.min = min; } + public Line(int stroke, float width, Cap cap) { + this.level = 0; + this.blur = 0; + this.cap = cap; + this.outline = false; + this.style = ""; + this.width = width; + this.fixed = true; + this.fade = -1; + this.stipple = 0; + this.stippleColor = null; + this.stippleWidth = 0; + this.min = 0; + this.color = GlUtils.colorToFloatP(stroke); + } - private Line(Line line, String style, String src, int stroke, float strokeWidth, - int stipple, Cap strokeLinecap, int level, boolean fixed, - int fade, float blur, boolean isOutline, float min) { - super(); - - this.style = style; - - // round = (strokeLinecap == Cap.ROUND); - - color = line.color; - - this.width = strokeWidth; - this.level = level; - this.outline = isOutline; - this.fixed = fixed; - this.fade = fade; - this.cap = strokeLinecap; - this.blur = blur; + public Line(int stroke, float width, int stipple) { + this.level = 0; + this.blur = 0; + this.cap = Cap.BUTT; + this.outline = false; + this.style = ""; + this.width = width; + this.fixed = true; + this.fade = -1; this.stipple = stipple; - this.min = min; + this.stippleColor = null; + this.stippleWidth = 0; + this.min = 0; + color = GlUtils.colorToFloatP(stroke); } @Override public void renderWay(IRenderCallback renderCallback, Tag[] tags) { - // renderCallback.renderWay(mPaint, mLevel, mColor, mStrokeWidth, - // mRound, mOutline); renderCallback.renderWay(this, level); } @@ -266,7 +250,5 @@ public final class Line extends RenderInstruction { // paint.setStrokeWidth(strokeWidth * scaleFactor); // } - public int getLevel() { - return this.level; - } + } diff --git a/src/org/oscim/theme/styles/default.xml b/src/org/oscim/theme/styles/default.xml index 0bf7e040..c0f0f45f 100644 --- a/src/org/oscim/theme/styles/default.xml +++ b/src/org/oscim/theme/styles/default.xml @@ -56,7 +56,12 @@ - + + + + + @@ -377,10 +382,22 @@ - + + + + + + + + + + + + + @@ -604,10 +621,22 @@ - + - + + + + + + + + + + + + + @@ -704,10 +733,18 @@ - + - + + + + + + + + + @@ -882,7 +919,8 @@ - +