Circle map style rendering (#202) #122

This commit is contained in:
Andrey Novikov 2016-10-11 16:04:20 +03:00 committed by Emux
parent 71d7b71035
commit 2821d8ddb8
8 changed files with 170 additions and 2 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -31,7 +31,7 @@ public abstract class RenderBucket extends Inlist<RenderBucket> {
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;

View File

@ -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();
}
}

View File

@ -28,7 +28,6 @@ public final class CircleStyle extends RenderStyle<CircleStyle> {
public final int fill;
public final int outline;
public final float radius;
public float renderRadius;
public final boolean scaleRadius;
public final float strokeWidth;