diff --git a/vtm/resources/assets/shaders/circle.glsl b/vtm/resources/assets/shaders/circle.glsl new file mode 100644 index 00000000..4fd2442b --- /dev/null +++ b/vtm/resources/assets/shaders/circle.glsl @@ -0,0 +1,30 @@ +#ifdef GLES +precision highp float; +#endif +uniform mat4 u_mvp; +uniform float u_radius; +uniform vec2 u_screen; +attribute vec2 a_pos; +varying vec2 v_tex; + +void +main(){ + gl_Position = u_mvp * vec4(a_pos, 0.0, 1.0); + v_tex = a_pos; +} + +$$ + +#ifdef GLES +precision highp float; +#endif +varying vec2 v_tex; +uniform float u_radius; +uniform vec4 u_color; +uniform vec2 u_screen; + +void +main(){ + float len = 1.0 - length(v_tex - u_screen); + gl_FragColor = u_color * smoothstep(0.0, u_radius, len); +} diff --git a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java index ec5874a1..2a467778 100644 --- a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java +++ b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java @@ -24,6 +24,7 @@ import org.oscim.renderer.GLMatrix; import org.oscim.renderer.GLViewport; import org.oscim.renderer.MapRenderer; import org.oscim.renderer.bucket.BitmapBucket; +import org.oscim.renderer.bucket.CircleBucket; import org.oscim.renderer.bucket.HairLineBucket; import org.oscim.renderer.bucket.LineBucket; import org.oscim.renderer.bucket.LineTexBucket; @@ -39,6 +40,7 @@ import static org.oscim.layers.tile.MapTile.PROXY_PARENT; import static org.oscim.layers.tile.MapTile.State.READY; import static org.oscim.renderer.MapRenderer.COORD_SCALE; import static org.oscim.renderer.bucket.RenderBucket.BITMAP; +import static org.oscim.renderer.bucket.RenderBucket.CIRCLE; import static org.oscim.renderer.bucket.RenderBucket.HAIRLINE; import static org.oscim.renderer.bucket.RenderBucket.LINE; import static org.oscim.renderer.bucket.RenderBucket.MESH; @@ -219,6 +221,9 @@ public class VectorTileRenderer extends TileRenderer { case BITMAP: b = BitmapBucket.Renderer.draw(b, v, 1, mLayerAlpha); break; + case CIRCLE: + b = CircleBucket.Renderer.draw(b, v); + break; default: /* just in case */ log.error("unknown layer {}", b.type); diff --git a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java index 382d97cc..27185089 100644 --- a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java +++ b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java @@ -25,6 +25,7 @@ import org.oscim.core.TagSet; import org.oscim.core.Tile; import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.TileLoader; +import org.oscim.renderer.bucket.CircleBucket; import org.oscim.renderer.bucket.LineBucket; import org.oscim.renderer.bucket.LineTexBucket; import org.oscim.renderer.bucket.MeshBucket; @@ -330,6 +331,10 @@ public class VectorTileLoader extends TileLoader implements RenderStyle.Callback @Override public void renderCircle(CircleStyle circle, int level) { + int nLevel = mCurBucket + level; + CircleBucket cb = mBuckets.getCircleBucket(nLevel); + cb.circle = circle; + cb.addCircle(mElement); } @Override diff --git a/vtm/src/org/oscim/renderer/BucketRenderer.java b/vtm/src/org/oscim/renderer/BucketRenderer.java index 786f0b36..cde49d78 100644 --- a/vtm/src/org/oscim/renderer/BucketRenderer.java +++ b/vtm/src/org/oscim/renderer/BucketRenderer.java @@ -20,6 +20,7 @@ package org.oscim.renderer; import org.oscim.core.MapPosition; import org.oscim.core.Tile; import org.oscim.renderer.bucket.BitmapBucket; +import org.oscim.renderer.bucket.CircleBucket; import org.oscim.renderer.bucket.HairLineBucket; import org.oscim.renderer.bucket.LineBucket; import org.oscim.renderer.bucket.LineTexBucket; @@ -33,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.oscim.renderer.bucket.RenderBucket.BITMAP; +import static org.oscim.renderer.bucket.RenderBucket.CIRCLE; import static org.oscim.renderer.bucket.RenderBucket.HAIRLINE; import static org.oscim.renderer.bucket.RenderBucket.LINE; import static org.oscim.renderer.bucket.RenderBucket.MESH; @@ -140,6 +142,9 @@ public class BucketRenderer extends LayerRenderer { } b = TextureBucket.Renderer.draw(b, v, div); break; + case CIRCLE: + b = CircleBucket.Renderer.draw(b, v); + break; default: log.error("invalid bucket {}", b.type); b = b.next; diff --git a/vtm/src/org/oscim/renderer/bucket/CircleBucket.java b/vtm/src/org/oscim/renderer/bucket/CircleBucket.java new file mode 100644 index 00000000..5afcfc30 --- /dev/null +++ b/vtm/src/org/oscim/renderer/bucket/CircleBucket.java @@ -0,0 +1,94 @@ +package org.oscim.renderer.bucket; + +import org.oscim.backend.GL; +import org.oscim.core.GeometryBuffer; +import org.oscim.renderer.GLShader; +import org.oscim.renderer.GLState; +import org.oscim.renderer.GLUtils; +import org.oscim.renderer.GLViewport; +import org.oscim.theme.styles.CircleStyle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.oscim.backend.GLAdapter.gl; +import static org.oscim.renderer.MapRenderer.COORD_SCALE; + +public class CircleBucket extends RenderBucket { + static final Logger log = LoggerFactory.getLogger(CircleBucket.class); + + public CircleStyle circle; + + public CircleBucket(int level) { + super(RenderBucket.CIRCLE, true, false); + this.level = level; + } + + public void addCircle(GeometryBuffer geom) { + if (!geom.isPoint()) { + log.error("Circle style applied to non-point geometry"); + return; + } + + float x = geom.getPointX(0); + float y = geom.getPointY(0); + + vertexItems.add((short) (x * COORD_SCALE), (short) (y * COORD_SCALE)); + indiceItems.add((short) numVertices++); + numIndices++; + } + + public static class Renderer { + static CircleBucket.Renderer.Shader shader; + + static boolean init() { + shader = new CircleBucket.Renderer.Shader("circle"); + return true; + } + + public static class Shader extends GLShader { + int uMVP, uColor, uRadius, uScreen, aPos; + + Shader(String shaderFile) { + if (!create(shaderFile)) + return; + + uMVP = getUniform("u_mvp"); + uColor = getUniform("u_color"); + uRadius = getUniform("u_radius"); + uScreen = getUniform("u_screen"); + aPos = getAttrib("a_pos"); + } + + public void set(GLViewport v) { + useProgram(); + GLState.enableVertexArrays(aPos, -1); + + v.mvp.setAsUniform(uMVP); + gl.uniform2f(uScreen, v.getWidth() / 2, v.getHeight() / 2); + gl.lineWidth(2); + } + } + + public static RenderBucket draw(RenderBucket b, GLViewport v) { + GLState.blend(true); + + CircleBucket.Renderer.Shader s = shader; + + s.set(v); + + for (; b != null && b.type == CIRCLE; b = b.next) { + CircleBucket cb = (CircleBucket) b; + + GLUtils.setColor(s.uColor, cb.circle.fill, 1); + gl.uniform1f(s.uRadius, cb.circle.radius); + + gl.vertexAttribPointer(s.aPos, 2, GL.SHORT, + false, 0, cb.vertexOffset); + + gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4); + } + + return b; + } + } +} diff --git a/vtm/src/org/oscim/renderer/bucket/RenderBucket.java b/vtm/src/org/oscim/renderer/bucket/RenderBucket.java index b423590b..5f048728 100644 --- a/vtm/src/org/oscim/renderer/bucket/RenderBucket.java +++ b/vtm/src/org/oscim/renderer/bucket/RenderBucket.java @@ -31,7 +31,7 @@ public abstract class RenderBucket extends Inlist { public static final int HAIRLINE = 5; public static final int SYMBOL = 6; public static final int BITMAP = 7; - public static final int SDF = 8; + public static final int CIRCLE = 8; public final int type; diff --git a/vtm/src/org/oscim/renderer/bucket/RenderBuckets.java b/vtm/src/org/oscim/renderer/bucket/RenderBuckets.java index b9b557f3..d7943d18 100644 --- a/vtm/src/org/oscim/renderer/bucket/RenderBuckets.java +++ b/vtm/src/org/oscim/renderer/bucket/RenderBuckets.java @@ -22,12 +22,14 @@ import org.oscim.layers.tile.MapTile.TileData; import org.oscim.renderer.BufferObject; import org.oscim.renderer.MapRenderer; import org.oscim.theme.styles.AreaStyle; +import org.oscim.theme.styles.CircleStyle; import org.oscim.theme.styles.LineStyle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ShortBuffer; +import static org.oscim.renderer.bucket.RenderBucket.CIRCLE; import static org.oscim.renderer.bucket.RenderBucket.HAIRLINE; import static org.oscim.renderer.bucket.RenderBucket.LINE; import static org.oscim.renderer.bucket.RenderBucket.MESH; @@ -52,6 +54,7 @@ public class RenderBuckets extends TileData { 2, // HAIRLINE_VERTEX 6, // SYMBOL 6, // BITMAP + 2, // CIRCLE }; private final static int SHORT_BYTES = 2; @@ -118,6 +121,14 @@ public class RenderBuckets extends TileData { return ll; } + public CircleBucket addCircleBucket(int level, CircleStyle style) { + CircleBucket l = (CircleBucket) getBucket(level, CIRCLE); + if (l == null) + return null; + l.circle = style; + return l; + } + /** * Get or add the LineBucket for a level. Levels are ordered from * bottom (0) to top @@ -158,6 +169,14 @@ public class RenderBuckets extends TileData { return (HairLineBucket) getBucket(level, HAIRLINE); } + /** + * Get or add the CircleBucket for a level. Levels are ordered from + * bottom (0) to top + */ + public CircleBucket getCircleBucket(int level) { + return (CircleBucket) getBucket(level, CIRCLE); + } + /** * Set new bucket items and clear previous. */ @@ -225,6 +244,8 @@ public class RenderBuckets extends TileData { bucket = new MeshBucket(level); else if (type == HAIRLINE) bucket = new HairLineBucket(level); + else if (type == CIRCLE) + bucket = new CircleBucket(level); if (bucket == null) throw new IllegalArgumentException(); @@ -360,6 +381,14 @@ public class RenderBuckets extends TileData { } } + for (RenderBucket l = buckets; l != null; l = l.next) { + if (l.type == CIRCLE) { + l.compile(vboData, iboData); + l.vertexOffset = pos; + pos += l.numVertices; + } + } + offset[LINE] = vboData.position() * SHORT_BYTES; pos = 0; for (RenderBucket l = buckets; l != null; l = l.next) { @@ -425,5 +454,6 @@ public class RenderBuckets extends TileData { BitmapBucket.Renderer.init(); MeshBucket.Renderer.init(); HairLineBucket.Renderer.init(); + CircleBucket.Renderer.init(); } } diff --git a/vtm/src/org/oscim/theme/styles/CircleStyle.java b/vtm/src/org/oscim/theme/styles/CircleStyle.java index d5be548b..a251ba3e 100644 --- a/vtm/src/org/oscim/theme/styles/CircleStyle.java +++ b/vtm/src/org/oscim/theme/styles/CircleStyle.java @@ -28,7 +28,6 @@ public final class CircleStyle extends RenderStyle { public final int fill; public final int outline; public final float radius; - public float renderRadius; public final boolean scaleRadius; public final float strokeWidth;