From 7cc32f1572478e148f54fdc917569c2ff38cf1b4 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Sat, 5 Jan 2013 07:59:55 +0100 Subject: [PATCH] use GLState for depth and stencil test --- src/org/oscim/renderer/BaseLayer.java | 8 +- src/org/oscim/renderer/GLState.java | 65 +++++----- src/org/oscim/renderer/PolygonRenderer.java | 121 ++++++++---------- src/org/oscim/renderer/TextureRenderer.java | 2 +- .../renderer/overlays/BuildingOverlay.java | 4 +- .../renderer/overlays/ExtrusionOverlay.java | 4 +- .../oscim/renderer/overlays/ModelOverlay.java | 2 +- .../renderer/overlays/RenderOverlay.java | 2 + 8 files changed, 99 insertions(+), 109 deletions(-) diff --git a/src/org/oscim/renderer/BaseLayer.java b/src/org/oscim/renderer/BaseLayer.java index f9d77a95..3c36df4f 100644 --- a/src/org/oscim/renderer/BaseLayer.java +++ b/src/org/oscim/renderer/BaseLayer.java @@ -16,7 +16,6 @@ package org.oscim.renderer; import static android.opengl.GLES20.GL_ARRAY_BUFFER; import static android.opengl.GLES20.GL_BLEND; -import static android.opengl.GLES20.GL_DEPTH_TEST; import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL; import static org.oscim.generator.JobTile.STATE_READY; @@ -51,9 +50,7 @@ public class BaseLayer { Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, pos.viewMatrix, 0); /* draw base layer */ - GLES20.glEnable(GL_DEPTH_TEST); GLES20.glEnable(GL_POLYGON_OFFSET_FILL); - // mDrawCount = 0; for (int i = 0; i < tileCnt; i++) { MapTile t = tiles[i]; @@ -72,7 +69,7 @@ public class BaseLayer { } GLES20.glDisable(GL_POLYGON_OFFSET_FILL); - GLES20.glDisable(GL_DEPTH_TEST); + mDrawSerial++; } @@ -116,7 +113,8 @@ public class BaseLayer { PolygonRenderer.draw(pos, null, mvp, true, true); clipped = true; } - + // clip lines to quad in depth buffer + GLState.test(true, false); GLES20.glEnable(GL_BLEND); l = LineRenderer.draw(pos, l, mvp, div, simpleShader, tile.layers.lineOffset); diff --git a/src/org/oscim/renderer/GLState.java b/src/org/oscim/renderer/GLState.java index 4817b34f..6d5ffb8b 100644 --- a/src/org/oscim/renderer/GLState.java +++ b/src/org/oscim/renderer/GLState.java @@ -34,39 +34,42 @@ public class GLState { blend = false; depth = false; stencil = false; + + GLES20.glDisable(GLES20.GL_STENCIL_TEST); + GLES20.glDisable(GLES20.GL_DEPTH_TEST); } - // public static void blend(boolean enable) { - // if (blend == enable) - // return; - // - // if (blend) - // GLES20.glEnable(GLES20.GL_BLEND); - // else - // GLES20.glDisable(GLES20.GL_BLEND); - // } - // - // public static void test(boolean depthTest, boolean stencilTest) { - // if (depth != depthTest) { - // - // if (depthTest) - // GLES20.glEnable(GLES20.GL_DEPTH_TEST); - // else - // GLES20.glDisable(GLES20.GL_DEPTH_TEST); - // - // depth = depthTest; - // } - // - // if (stencil != stencilTest) { - // - // if (stencilTest) - // GLES20.glEnable(GLES20.GL_STENCIL_TEST); - // else - // GLES20.glDisable(GLES20.GL_STENCIL_TEST); - // - // stencil = stencilTest; - // } - // } + public static void blend(boolean enable) { + if (blend == enable) + return; + + if (blend) + GLES20.glEnable(GLES20.GL_BLEND); + else + GLES20.glDisable(GLES20.GL_BLEND); + } + + public static void test(boolean depthTest, boolean stencilTest) { + if (depth != depthTest) { + + if (depthTest) + GLES20.glEnable(GLES20.GL_DEPTH_TEST); + else + GLES20.glDisable(GLES20.GL_DEPTH_TEST); + + depth = depthTest; + } + + if (stencil != stencilTest) { + + if (stencilTest) + GLES20.glEnable(GLES20.GL_STENCIL_TEST); + else + GLES20.glDisable(GLES20.GL_STENCIL_TEST); + + stencil = stencilTest; + } + } public static void enableVertexArrays(int va1, int va2) { if (va1 > 1 || va2 > 1) diff --git a/src/org/oscim/renderer/PolygonRenderer.java b/src/org/oscim/renderer/PolygonRenderer.java index fe81d7e2..b9ecccc1 100644 --- a/src/org/oscim/renderer/PolygonRenderer.java +++ b/src/org/oscim/renderer/PolygonRenderer.java @@ -16,12 +16,10 @@ package org.oscim.renderer; import static android.opengl.GLES20.GL_ALWAYS; import static android.opengl.GLES20.GL_BLEND; -import static android.opengl.GLES20.GL_DEPTH_TEST; import static android.opengl.GLES20.GL_EQUAL; import static android.opengl.GLES20.GL_INVERT; import static android.opengl.GLES20.GL_LESS; import static android.opengl.GLES20.GL_SHORT; -import static android.opengl.GLES20.GL_STENCIL_TEST; import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.GL_TRIANGLE_STRIP; import static android.opengl.GLES20.GL_ZERO; @@ -167,8 +165,25 @@ public final class PolygonRenderer { // stencil buffer index to start fill private static int mStart; + /** + * draw polygon layers (unil layer.next is not polygon layer) + * using stencil buffer method + * @param pos + * used to fade layers accorind to 'fade' + * in layer.area. + * @param layer + * layer to draw (referencing vertices in current vbo) + * @param matrix + * mvp matrix + * @param first + * pass true to clear stencil buffer region + * @param drawClipped + * clip to first quad in current vbo + * @return + * next layer + */ public static Layer draw(MapPosition pos, Layer layer, - float[] matrix, boolean first, boolean drawClip) { + float[] matrix, boolean first, boolean drawClipped) { int zoom = pos.zoomLevel; float scale = pos.scale; @@ -182,9 +197,11 @@ public final class PolygonRenderer { glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); - // use stencilbuffer method for polygon drawing - glEnable(GL_STENCIL_TEST); - //GLState.stencilTest(true); + // reset start when only two layer left in stencil buffer + // if (mCount > 5) { + // mCount = 0; + // mStart = 0; + // } if (first) { mCount = 0; @@ -202,7 +219,8 @@ public final class PolygonRenderer { continue; if (mCount == mStart) { - // clear stencilbuffer (tile region) + // clear stencilbuffer (tile region) by drawing + // a quad with func 'always' and op 'zero' // disable drawing to framebuffer glColorMask(false, false, false, false); @@ -210,55 +228,38 @@ public final class PolygonRenderer { // never pass the test: always apply fail op glStencilFunc(GL_ALWAYS, 0, 0xFF); glStencilMask(0xFF); - glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - if (drawClip) { + if (drawClipped) { + GLState.test(true, true); // draw clip-region into depth buffer: // this is used for lines and polygons // write to depth buffer glDepthMask(true); - // to prevent overdraw gl_less restricts - // the clip to the area where no other - // tile has drawn + // to prevent overdraw gl_less restricts the + // clip to the area where no other tile has drawn glDepthFunc(GL_LESS); } glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (drawClip) { + if (drawClipped) { first = false; - drawClip = false; - // dont modify depth buffer + drawClipped = false; + // do not modify depth buffer anymore glDepthMask(false); // only draw to this tile glDepthFunc(GL_EQUAL); } - // stencil op for stencil method polygon drawing + // op for stencil method polygon drawing glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); - - // no need for depth test while drawing stencil - if (drawClip) - glDisable(GL_DEPTH_TEST); - } - // else if (mCount == mStart) { - // // disable drawing to framebuffer - // glColorMask(false, false, false, false); - // - // // never pass the test: always apply fail op - // glStencilFunc(GL_ALWAYS, 0, 0xFF); - // - // // stencil op for stencil method polygon drawing - // glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); - // - // // no need for depth test while drawing stencil - // if (clip) - // glDisable(GL_DEPTH_TEST); - // } + + // no need for depth test while drawing stencil + GLState.test(false, true); mFillPolys[mCount] = pl; @@ -270,8 +271,8 @@ public final class PolygonRenderer { // draw up to 8 layers into stencil buffer if (mCount == STENCIL_BITS) { /* only draw where nothing was drawn yet */ - if (drawClip) - glEnable(GL_DEPTH_TEST); + if (drawClipped) + GLState.test(true, true); fillPolygons(zoom, scale); mCount = 0; @@ -281,35 +282,38 @@ public final class PolygonRenderer { if (mCount > 0) { /* only draw where nothing was drawn yet */ - if (drawClip) - glEnable(GL_DEPTH_TEST); + if (drawClipped) + GLState.test(true, true); fillPolygons(zoom, scale); } - // maybe reset start when only few layers left in stencil buffer - // if (mCount > 5){ - // mCount = 0; - // mStart = 0; - // } - glDisable(GL_STENCIL_TEST); + if (drawClipped && first) { + GLState.test(true, false); + GLES20.glColorMask(false, false, false, false); + GLES20.glDepthMask(true); + GLES20.glDepthFunc(GLES20.GL_LESS); - if (drawClip && first) - drawDepthClip(); + GLES20.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + GLES20.glDepthMask(false); + GLES20.glColorMask(true, true, true, true); + GLES20.glDepthFunc(GLES20.GL_EQUAL); + } return l; } private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f }; private static float[] debugFillColor2 = { 0.0f, 0.3f, 0.0f, 0.3f }; - - private static ByteBuffer mDebugFill; + private static FloatBuffer mDebugFill; static void debugDraw(float[] matrix, float[] coords, int color) { + GLState.test(false, false); + if (mDebugFill == null) + mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()) + .asFloatBuffer(); - mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()); - FloatBuffer buf = mDebugFill.asFloatBuffer(); - buf.put(coords); + mDebugFill.put(coords); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); @@ -330,18 +334,5 @@ public final class PolygonRenderer { glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GlUtils.checkGlError("draw debug"); - // GLES20.glDisableVertexAttribArray(hPolygonVertexPosition); - } - - static void drawDepthClip() { - glColorMask(false, false, false, false); - GLES20.glDepthMask(true); - GLES20.glDepthFunc(GLES20.GL_LESS); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - GLES20.glDepthMask(false); - glColorMask(true, true, true, true); - GLES20.glDepthFunc(GLES20.GL_EQUAL); } } diff --git a/src/org/oscim/renderer/TextureRenderer.java b/src/org/oscim/renderer/TextureRenderer.java index c4ca4844..5cabcf72 100644 --- a/src/org/oscim/renderer/TextureRenderer.java +++ b/src/org/oscim/renderer/TextureRenderer.java @@ -90,7 +90,7 @@ public final class TextureRenderer { } public static Layer draw(Layer layer, float scale, float[] projection, float matrix[]) { - + GLState.test(false, false); // GlUtils.checkGlError("draw texture >"); GLES20.glUseProgram(mTextureProgram); diff --git a/src/org/oscim/renderer/overlays/BuildingOverlay.java b/src/org/oscim/renderer/overlays/BuildingOverlay.java index 4dd4aa5b..d6f2c0b9 100644 --- a/src/org/oscim/renderer/overlays/BuildingOverlay.java +++ b/src/org/oscim/renderer/overlays/BuildingOverlay.java @@ -373,10 +373,8 @@ public class BuildingOverlay extends RenderOverlay { GLES20.glUniform1i(hBuildingMode, 0); GLES20.glColorMask(false, false, false, false); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); - GLES20.glEnable(GLES20.GL_DEPTH_TEST); - + GLState.test(true, false); GLES20.glEnable(GLES20.GL_CULL_FACE); - //GLES20.glCullFace(GLES20.GL_CW); GLES20.glDepthMask(true); GLES20.glDepthFunc(GLES20.GL_LESS); diff --git a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java index 69127d7e..67c513dc 100644 --- a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java +++ b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java @@ -200,13 +200,12 @@ public class ExtrusionOverlay extends RenderOverlay { } GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); + GLState.test(true, false); GLES20.glUseProgram(extrusionProgram); GLState.enableVertexArrays(hExtrusionVertexPosition, -1); - GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glCullFace(GLES20.GL_FRONT); GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL); - GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthMask(true); GLES20.glColorMask(false, false, false, false); @@ -291,7 +290,6 @@ public class ExtrusionOverlay extends RenderOverlay { } GLES20.glDisable(GLES20.GL_CULL_FACE); - GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/org/oscim/renderer/overlays/ModelOverlay.java b/src/org/oscim/renderer/overlays/ModelOverlay.java index 84f2b950..6cb3d933 100644 --- a/src/org/oscim/renderer/overlays/ModelOverlay.java +++ b/src/org/oscim/renderer/overlays/ModelOverlay.java @@ -188,7 +188,7 @@ public class ModelOverlay extends RenderOverlay { // draw to depth buffer GLES20.glColorMask(false, false, false, false); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); - GLES20.glEnable(GLES20.GL_DEPTH_TEST); + GLState.test(true, false); GLES20.glDepthMask(true); GLES20.glDepthFunc(GLES20.GL_LESS); diff --git a/src/org/oscim/renderer/overlays/RenderOverlay.java b/src/org/oscim/renderer/overlays/RenderOverlay.java index 048d8f86..61ac8bbd 100644 --- a/src/org/oscim/renderer/overlays/RenderOverlay.java +++ b/src/org/oscim/renderer/overlays/RenderOverlay.java @@ -18,6 +18,7 @@ import org.oscim.core.MapPosition; import org.oscim.core.Tile; import org.oscim.renderer.BufferObject; import org.oscim.renderer.GLRenderer; +import org.oscim.renderer.GLState; import org.oscim.renderer.LineRenderer; import org.oscim.renderer.PolygonRenderer; import org.oscim.renderer.TextureRenderer; @@ -104,6 +105,7 @@ public abstract class RenderOverlay { Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id); + GLState.test(false, false); for (Layer l = layers.layers; l != null;) { if (l.type == Layer.POLYGON) {