diff --git a/src/org/oscim/renderer/BaseMap.java b/src/org/oscim/renderer/BaseMap.java index 49fb1f5b..11691e54 100644 --- a/src/org/oscim/renderer/BaseMap.java +++ b/src/org/oscim/renderer/BaseMap.java @@ -54,7 +54,6 @@ public class BaseMap { mDrawCnt = 0; GLES20.glDepthFunc(GLES20.GL_LESS); - glStencilMask(0xFF); LineRenderer.beginLines(); for (int i = 0; i < tileCnt; i++) { @@ -118,6 +117,8 @@ public class BaseMap { // set depth offset (used for clipping to tile boundaries) GLES20.glPolygonOffset(1, mDrawCnt++); + if (mDrawCnt > 20) + mDrawCnt = 0; GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.vbo.id); @@ -144,12 +145,7 @@ public class BaseMap { } } - glStencilMask(0xFF); - GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); - //glStencilMask(0x0); - //PolygonRenderer.drawOver(mvp); - //GLES20.glFlush(); } private static int drawProxyChild(MapTile tile, MapPosition pos) { @@ -170,6 +166,8 @@ public class BaseMap { private static void drawProxyTile(MapTile tile, MapPosition pos, boolean parent) { int diff = pos.zoomLevel - tile.zoomLevel; + QuadTree r = tile.rel; + MapTile proxy; if (pos.scale > 1.5f || diff < 0) { // prefer drawing children @@ -179,30 +177,32 @@ public class BaseMap { if (parent) { // draw parent proxy if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { - MapTile t = tile.rel.parent.tile; - if (t.state == STATE_READY) { - drawTile(t, pos); + proxy = r.parent.tile; + if (proxy.state == STATE_READY) { + //Log.d(TAG, "1. draw parent " + proxy); + drawTile(proxy, pos); } } } else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) { // check if parent was already drawn if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { - MapTile t = tile.rel.parent.tile; - if (t.state == STATE_READY) + proxy = r.parent.tile; + if (proxy.state == STATE_READY) return; } - MapTile t = tile.rel.parent.parent.tile; - if (t.state == STATE_READY) - drawTile(t, pos); + proxy = r.parent.parent.tile; + if (proxy.state == STATE_READY) + drawTile(proxy, pos); } } else { // prefer drawing parent if (parent) { if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { - MapTile t = tile.rel.parent.tile; - if (t != null && t.state == STATE_READY) { - drawTile(t, pos); + proxy = r.parent.tile; + if (proxy != null && proxy.state == STATE_READY) { + //Log.d(TAG, "2. draw parent " + proxy); + drawTile(proxy, pos); return; } @@ -212,17 +212,17 @@ public class BaseMap { } else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) { // check if parent was already drawn if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { - MapTile t = tile.rel.parent.tile; - if (t.state == STATE_READY) + proxy = r.parent.tile; + if (proxy.state == STATE_READY) return; } // this will do nothing, just to check if (drawProxyChild(tile, pos) > 0) return; - MapTile t = tile.rel.parent.parent.tile; - if (t.state == STATE_READY) - drawTile(t, pos); + proxy = r.parent.parent.tile; + if (proxy.state == STATE_READY) + drawTile(proxy, pos); } } } diff --git a/src/org/oscim/renderer/PolygonRenderer.java b/src/org/oscim/renderer/PolygonRenderer.java index a181863a..12413d70 100644 --- a/src/org/oscim/renderer/PolygonRenderer.java +++ b/src/org/oscim/renderer/PolygonRenderer.java @@ -45,9 +45,8 @@ import org.oscim.utils.GlUtils; import android.opengl.GLES20; public final class PolygonRenderer { - //private static final String TAG = PolygonRenderer.class.getName(); + private static final String TAG = PolygonRenderer.class.getName(); - // private static final int NUM_VERTEX_SHORTS = 2; private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0; private static final int STENCIL_BITS = 8; private final static int CLIP_BIT = 0x80; @@ -84,15 +83,15 @@ public final class PolygonRenderer { return true; } - private static void fillPolygons(int zoom, float scale) { + private static void fillPolygons(int start, int end, int zoom, float scale) { /* draw to framebuffer */ glColorMask(true, true, true, true); /* do not modify stencil buffer */ - glStencilMask(0); + glStencilMask(0x00); - for (int c = mStart; c < mCount; c++) { + for (int c = start; c < end; c++) { Area a = mFillPolys[c].area; if (a.fade >= zoom) { @@ -132,7 +131,7 @@ public final class PolygonRenderer { } // set stencil buffer mask used to draw this layer - // also check that clip bit is 0 to avoid overdraw + // also check that clip bit is set to avoid overdraw // of other tiles glStencilFunc(GL_EQUAL, 0xff, CLIP_BIT | 1 << c); @@ -141,10 +140,8 @@ public final class PolygonRenderer { } } - // layers to fill + // current layer to fill (0 - STENCIL_BITS-1) private static int mCount; - // stencil buffer index to start fill - private static int mStart; /** * draw polygon layers (unil layer.next is not polygon layer) @@ -166,29 +163,24 @@ public final class PolygonRenderer { public static Layer draw(MapPosition pos, Layer layer, float[] matrix, boolean first, boolean clip) { - int zoom = pos.zoomLevel; - float scale = pos.scale; - - GLState.useProgram(polygonProgram); - - GLState.enableVertexArrays(hPolygonVertexPosition, -1); - - glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, - false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); - - glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); - - // reset start when only one layer left in stencil buffer - if (first || mCount > 5) { - mStart = mCount = 0; - } else { - mStart = mCount; - } - GLState.test(false, true); - Layer l = layer; + GLState.useProgram(polygonProgram); + GLState.enableVertexArrays(hPolygonVertexPosition, -1); + glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, + false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); + glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); + int zoom = pos.zoomLevel; + int cur = mCount; + + // reset start when only one layer left in stencil buffer + if (first || cur > 5) + cur = 0; + + int start = cur; + + Layer l = layer; for (; l != null && l.type == Layer.POLYGON; l = l.next) { PolygonLayer pl = (PolygonLayer) l; @@ -196,137 +188,131 @@ public final class PolygonRenderer { if (pl.area.fade > 0 && pl.area.fade > zoom) continue; - if (mCount == mStart) { - drawStencilRegion(clip, first); + if (cur == start) { + drawStencilRegion(first); first = false; // op for stencil method polygon drawing glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GL_INVERT); - //GLState.blend(false); } - mFillPolys[mCount] = pl; + mFillPolys[cur] = pl; // set stencil mask to draw to - glStencilMask(1 << mCount++); + glStencilMask(1 << cur++); glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.verticesCnt); // draw up to 7 layers into stencil buffer - if (mCount == STENCIL_BITS - 1) { - fillPolygons(zoom, scale); - mStart = mCount = 0; + if (cur == STENCIL_BITS - 1) { + fillPolygons(start, cur, zoom, pos.scale); + start = cur = 0; } } - if (mCount > 0) - fillPolygons(zoom, scale); + if (cur > 0) + fillPolygons(start, cur, zoom, pos.scale); if (clip) { if (first) { - drawStencilRegion(clip, first); + drawStencilRegion(first); // disable writes to stencil buffer glStencilMask(0x00); // enable writes to color buffer glColorMask(true, true, true, true); + } else { + // set test for clip to tile region + glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); } - // clip to tile region - glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); } + mCount = cur; + return l; } /** - * @param clip ... - * @param first ... + * Draw a tile filling rectangle to set stencil- and depth buffer + * appropriately + * @param first in the first run the clip region is set based on + * depth buffer and depth buffer is updated */ - static void drawStencilRegion(boolean clip, boolean first) { - //if (!first && clip) { - // // only clear 'layer-bits' - // glStencilMask(0x7F); - // GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); - // glColorMask(false, false, false, false); - // glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); - // return; - //} - // disable drawing to framebuffer (will be re-enabled in fill) + static void drawStencilRegion(boolean first) { + + // disable drawing to color buffer glColorMask(false, false, false, false); - if (!first) { - // write to all bits - glStencilMask(0xFF); + // write to all stencil bits + glStencilMask(0xFF); + + if (first) { + // clear previous clip-region from stencil buffer + GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); + + // Draw clip-region into depth and stencil buffer + // this is used for tile line and polygon layers. + // Depth offset is increased for each tile. Together + // with depth test (GL_LESS) this ensures to only + // draw where no other tile has drawn yet. + GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL); + + // test depth and write to depth buffer + GLState.test(true, true); + glDepthMask(true); + + // always pass stencil test and set clip bit + glStencilFunc(GL_ALWAYS, CLIP_BIT, 0x00); + } else { + // use clip bit from stencil buffer + // to clear stencil 'layer-bits' (0x7f) + glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); } // set clip bit (0x80) for draw region glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_REPLACE); - if (clip) { - if (first) { - // draw clip-region into depth and stencil buffer: - // this is used for tile line and polygon layers - GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL); - - // test depth and write to depth buffer - GLState.test(true, true); - glDepthMask(true); - } - } - if (!clip || first) { - // always pass stencil test: - glStencilFunc(GL_ALWAYS, CLIP_BIT, CLIP_BIT); - } else { - // use clip region from stencil buffer - // to clear stencil 'layer-bits' (0x7f) - glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); - } - // draw a quad for the tile region glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (clip) { - if (first) { - // dont modify depth buffer - glDepthMask(false); - - GLState.test(false, true); - - GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL); - } - } - if (first) { + // dont modify depth buffer + glDepthMask(false); + // test only stencil + GLState.test(false, true); + + GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL); + glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT); } } - static void drawOver(float[] matrix) { - - GLState.useProgram(polygonProgram); - - GLState.enableVertexArrays(hPolygonVertexPosition, -1); - - glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, - false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); - - glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); - - /* clear stencilbuffer (tile region) by drawing - * a quad with func 'always' and op 'zero' */ - - // disable drawing to framebuffer (will be re-enabled in fill) - glColorMask(false, false, false, false); - - // always pass stencil test: - glStencilFunc(GL_ALWAYS, 0x00, 0x00); - // write to all bits - glStencilMask(0xFF); - // zero out area to draw to - glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_ZERO); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glColorMask(true, true, true, true); - } + // static void drawOver(float[] matrix) { + // + // GLState.useProgram(polygonProgram); + // + // GLState.enableVertexArrays(hPolygonVertexPosition, -1); + // + // glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, + // false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); + // + // glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); + // + // /* clear stencilbuffer (tile region) by drawing + // * a quad with func 'always' and op 'zero' */ + // + // // disable drawing to framebuffer (will be re-enabled in fill) + // glColorMask(false, false, false, false); + // + // // always pass stencil test: + // glStencilFunc(GL_ALWAYS, 0x00, 0x00); + // // write to all bits + // glStencilMask(0xFF); + // // zero out area to draw to + // glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_ZERO); + // + // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + // 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 };