diff --git a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java index 8cae3ea8..39a1e691 100644 --- a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java +++ b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java @@ -25,9 +25,8 @@ import org.slf4j.LoggerFactory; public abstract class ExtrusionRenderer extends LayerRenderer { static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class); - static final boolean debugDraw = false; - private final boolean drawAlpha; + private final boolean mTranslucent; private final int mMode; private Shader mShader; @@ -37,7 +36,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer { public ExtrusionRenderer(boolean mesh, boolean alpha) { mMode = mesh ? 1 : 0; - drawAlpha = alpha; + mTranslucent = alpha; } public static class Shader extends GLShader { @@ -67,11 +66,6 @@ public abstract class ExtrusionRenderer extends LayerRenderer { } private void renderCombined(int vertexPointer, ExtrusionLayers els) { - if (els.vboIndices == null) - return; - - els.vboIndices.bind(); - els.vboVertices.bind(); for (ExtrusionLayer el = els.layers; el != null; el = el.next()) { @@ -93,169 +87,149 @@ public abstract class ExtrusionRenderer extends LayerRenderer { @Override public void render(GLViewport v) { - // TODO one could render in one pass to texture and then draw the texture - // with alpha... might be faster and would allow postprocessing outlines. - - ExtrusionLayers[] els = mExtrusionLayerSet; - Shader s = mShader; - - if (debugDraw) { - s.useProgram(); - GLState.enableVertexArrays(s.aPos, s.aLight); - GL.glUniform1i(s.uMode, 0); - GLUtils.glUniform4fv(s.uColor, 4, DEBUG_COLOR); - GL.glUniform1f(s.uAlpha, 1); - - GLState.test(false, false); - GLState.blend(true); - for (int i = 0; i < mExtrusionLayerCnt; i++) { - ExtrusionLayer el = els[i].getLayers(); - - setMatrix(v, els[i], 0); - v.mvp.setAsUniform(s.uMVP); - - renderCombined(s.aPos, els[i]); - - /* just a temporary reference! */ - els[i] = null; - } - return; - } GL.glDepthMask(true); GL.glClear(GL20.GL_DEPTH_BUFFER_BIT); GLState.test(true, false); + Shader s = mShader; s.useProgram(); GLState.enableVertexArrays(s.aPos, -1); - GLState.blend(false); - GL.glEnable(GL20.GL_CULL_FACE); + /* only use face-culling when it's unlikely + * that one'moves through the building' */ + if (v.pos.zoomLevel < 18) + GL.glEnable(GL20.GL_CULL_FACE); + GL.glDepthFunc(GL20.GL_LESS); - GL.glUniform1f(s.uAlpha, mAlpha); - if (drawAlpha) { + ExtrusionLayers[] els = mExtrusionLayerSet; + + if (mTranslucent) { + /* only draw to depth buffer */ + GLState.blend(false); GL.glColorMask(false, false, false, false); GL.glUniform1i(s.uMode, -1); - //GLUtils.glUniform4fv(uExtColor, 4, mColor); - /* draw to depth buffer */ for (int i = 0; i < mExtrusionLayerCnt; i++) { - ExtrusionLayer el = els[i].getLayers(); - if (el == null) - continue; + if (els[i].vboIndices == null) + return; - int d = 0; // FIXME MapTile.depthOffset(t) * 10; + els[i].vboIndices.bind(); + els[i].vboVertices.bind(); - setMatrix(v, els[i], d); + setMatrix(v, els[i], true); v.mvp.setAsUniform(s.uMVP); renderCombined(s.aPos, els[i]); } + /* only draw to color buffer */ GL.glColorMask(true, true, true, true); GL.glDepthMask(false); - GLState.blend(true); + + GL.glDepthFunc(GL20.GL_EQUAL); } GLState.blend(true); - GLState.enableVertexArrays(s.aPos, s.aLight); + GLState.enableVertexArrays(s.aPos, s.aLight); float[] currentColor = null; for (int i = 0; i < mExtrusionLayerCnt; i++) { - ExtrusionLayer el = els[i].getLayers(); - - if (el == null) - continue; - if (els[i].vboIndices == null) continue; els[i].vboIndices.bind(); els[i].vboVertices.bind(); - int d = 0; - if (drawAlpha) { - GL.glDepthFunc(GL20.GL_EQUAL); - - // FIXME d = MapTile.depthOffset(t) * 10; + if (!mTranslucent) { + setMatrix(v, els[i], false); + v.mvp.setAsUniform(s.uMVP); } - setMatrix(v, els[i], d); - v.mvp.setAsUniform(s.uMVP); - + ExtrusionLayer el = els[i].getLayers(); for (; el != null; el = el.next()) { if (el.colors != currentColor) { currentColor = el.colors; - GLUtils.glUniform4fv(s.uColor, mMode == 0 ? 4 : 1, + GLUtils.glUniform4fv(s.uColor, + mMode == 0 ? 4 : 1, el.colors); } - /* indices offset */ - int indexOffset = el.indexOffset; - /* vertex byte offset */ - int vertexOffset = el.getOffset(); - - GL.glVertexAttribPointer(s.aPos, 3, - GL20.GL_SHORT, false, 8, vertexOffset); + GL.glVertexAttribPointer(s.aPos, 3, GL20.GL_SHORT, + false, 8, el.getOffset()); GL.glVertexAttribPointer(s.aLight, 2, - GL20.GL_UNSIGNED_BYTE, false, 8, vertexOffset + 6); + GL20.GL_UNSIGNED_BYTE, + false, 8, el.getOffset() + 6); /* draw extruded outlines */ if (el.numIndices[0] > 0) { + if (mTranslucent) { + GL.glDepthFunc(GL20.GL_EQUAL); + setMatrix(v, els[i], true); + v.mvp.setAsUniform(s.uMVP); + } + /* draw roof */ GL.glUniform1i(s.uMode, 0); - GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[2], + GL.glDrawElements(GL20.GL_TRIANGLES, + el.numIndices[2], GL20.GL_UNSIGNED_SHORT, - (el.numIndices[0] + el.numIndices[1]) * 2); + (el.numIndices[0] + + el.numIndices[1]) * 2); /* draw sides 1 */ GL.glUniform1i(s.uMode, 1); - GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[0], + GL.glDrawElements(GL20.GL_TRIANGLES, + el.numIndices[0], GL20.GL_UNSIGNED_SHORT, 0); /* draw sides 2 */ GL.glUniform1i(s.uMode, 2); - GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[1], - GL20.GL_UNSIGNED_SHORT, el.numIndices[0] * 2); + GL.glDrawElements(GL20.GL_TRIANGLES, + el.numIndices[1], + GL20.GL_UNSIGNED_SHORT, + el.numIndices[0] * 2); - if (drawAlpha) { + if (mTranslucent) { /* drawing gl_lines with the same coordinates does not * result in same depth values as polygons, so add * offset and draw gl_lequal: */ GL.glDepthFunc(GL20.GL_LEQUAL); + v.mvp.addDepthOffset(100); + v.mvp.setAsUniform(s.uMVP); } - v.mvp.addDepthOffset(100); - v.mvp.setAsUniform(s.uMVP); - GL.glUniform1i(s.uMode, 3); - - int offset = 2 * (indexOffset + int offset = 2 * (el.indexOffset + el.numIndices[0] + el.numIndices[1] + el.numIndices[2]); - GL.glDrawElements(GL20.GL_LINES, el.numIndices[3], - GL20.GL_UNSIGNED_SHORT, offset); + GL.glDrawElements(GL20.GL_LINES, + el.numIndices[3], + GL20.GL_UNSIGNED_SHORT, + offset); + } /* draw triangle meshes */ if (el.numIndices[4] > 0) { - int offset = 2 * (indexOffset + int offset = 2 * (el.indexOffset + el.numIndices[0] + el.numIndices[1] + el.numIndices[2] + el.numIndices[3]); - GL.glUniform1i(s.uMode, 4); - GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4], - GL20.GL_UNSIGNED_SHORT, offset); + GL.glDrawElements(GL20.GL_TRIANGLES, + el.numIndices[4], + GL20.GL_UNSIGNED_SHORT, + offset); } } @@ -263,56 +237,31 @@ public abstract class ExtrusionRenderer extends LayerRenderer { els[i] = null; } - GL.glDepthMask(false); - GL.glDisable(GL20.GL_CULL_FACE); + if (!mTranslucent) + GL.glDepthMask(false); + + if (v.pos.zoomLevel < 18) + GL.glDisable(GL20.GL_CULL_FACE); + GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); } - private static void setMatrix(GLViewport v, ExtrusionLayers l, int delta) { + private static void setMatrix(GLViewport v, ExtrusionLayers l, boolean offset) { + int z = l.zoomLevel; double curScale = Tile.SIZE * v.pos.scale; float scale = (float) (v.pos.scale / (1 << z)); float x = (float) ((l.x - v.pos.x) * curScale); float y = (float) ((l.y - v.pos.y) * curScale); + v.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE); - - // scale height ??? v.mvp.setValue(10, scale / 10); - v.mvp.multiplyLhs(v.viewproj); - v.mvp.addDepthOffset(delta); + if (offset) { + int delta = (int) (l.x * (1 << z)) % 4 + (int) (l.y * (1 << z)) % 4 * 4; + v.mvp.addDepthOffset(delta); + } } - - private static float A = 0.88f; - private static float R = 0xe9; - private static float G = 0xe8; - private static float B = 0xe6; - private static float O = 20; - private static float S = 4; - private static float L = 0; - - private static float[] DEBUG_COLOR = { - // roof color - A * ((R + L) / 255), - A * ((G + L) / 255), - A * ((B + L) / 255), - 0.8f, - // sligthly differ adjacent side - // faces to improve contrast - A * ((R - S) / 255 + 0.01f), - A * ((G - S) / 255 + 0.01f), - A * ((B - S) / 255), - A, - A * ((R - S) / 255), - A * ((G - S) / 255), - A * ((B - S) / 255), - A, - // roof outline - (R - O) / 255, - (G - O) / 255, - (B - O) / 255, - 0.9f, - }; }