- use Stencil instead of Depth for clipping test
to avoid drawing everything with polygonOffset - add GLState.useProgram
This commit is contained in:
parent
5f03a33492
commit
be748138ac
@ -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_POLYGON_OFFSET_FILL;
|
||||
import static org.oscim.generator.JobTile.STATE_READY;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
@ -31,7 +30,7 @@ import android.opengl.Matrix;
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public class BaseMap {
|
||||
private final static String TAG = BaseMap.class.getName();
|
||||
//private final static String TAG = BaseMap.class.getName();
|
||||
|
||||
// used to not draw a tile twice per frame.
|
||||
private static int mDrawSerial = 0;
|
||||
@ -52,10 +51,10 @@ public class BaseMap {
|
||||
static void draw(MapTile[] tiles, int tileCnt, MapPosition pos) {
|
||||
//long start = SystemClock.uptimeMillis();
|
||||
Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, pos.viewMatrix, 0);
|
||||
|
||||
mDrawCnt = 0;
|
||||
|
||||
GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
GLES20.glDepthFunc(GLES20.GL_LESS);
|
||||
|
||||
LineRenderer.beginLines();
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
@ -63,9 +62,8 @@ public class BaseMap {
|
||||
drawTile(t, pos);
|
||||
}
|
||||
|
||||
// proxies are clipped to the region where nothing was drawn to depth
|
||||
// buffer.
|
||||
// TODO draw all parent before grandparent
|
||||
// proxies are clipped to the region where nothing was drawn to depth buffer.
|
||||
// draw child or parent proxies.
|
||||
// TODO draw proxies for placeholder...
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
@ -73,6 +71,7 @@ public class BaseMap {
|
||||
drawProxyTile(t, pos, true);
|
||||
}
|
||||
|
||||
// draw grandparents
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null))
|
||||
@ -81,8 +80,6 @@ public class BaseMap {
|
||||
|
||||
LineRenderer.endLines();
|
||||
|
||||
GLES20.glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
//GLES20.glFinish();
|
||||
//long end = SystemClock.uptimeMillis();
|
||||
//Log.d(TAG, "base took " + (end - start));
|
||||
mDrawSerial++;
|
||||
@ -103,9 +100,10 @@ public class BaseMap {
|
||||
if (t.holder != null)
|
||||
t = t.holder;
|
||||
|
||||
if (t.layers == null || t.vbo == null)
|
||||
if (t.layers == null || t.vbo == null) {
|
||||
//Log.d(TAG, "missing data " + (t.layers == null) + " " + (t.vbo == null));
|
||||
return;
|
||||
|
||||
}
|
||||
// set Model matrix for tile
|
||||
float div = FastMath.pow(tile.zoomLevel - pos.zoomLevel);
|
||||
float x = (float) (tile.pixelX - pos.x * div);
|
||||
@ -117,8 +115,7 @@ public class BaseMap {
|
||||
Matrix.multiplyMM(mvp, 0, mVPMatrix, 0, mvp, 0);
|
||||
|
||||
// set depth offset (used for clipping to tile boundaries)
|
||||
//GLES20.glPolygonOffset(-1, -GLRenderer.depthOffset(t));
|
||||
GLES20.glPolygonOffset(-1, (mDrawCnt++));
|
||||
GLES20.glPolygonOffset(1, mDrawCnt++);
|
||||
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.vbo.id);
|
||||
|
||||
@ -140,8 +137,6 @@ public class BaseMap {
|
||||
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,
|
||||
@ -149,6 +144,7 @@ public class BaseMap {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PolygonRenderer.drawOver(mvp);
|
||||
}
|
||||
|
||||
private static int drawProxyChild(MapTile tile, MapPosition pos) {
|
||||
@ -179,8 +175,9 @@ public class BaseMap {
|
||||
// draw parent proxy
|
||||
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
||||
MapTile t = tile.rel.parent.tile;
|
||||
if (t.state == STATE_READY)
|
||||
if (t.state == STATE_READY) {
|
||||
drawTile(t, pos);
|
||||
}
|
||||
}
|
||||
} else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
||||
// check if parent was already drawn
|
||||
@ -197,14 +194,14 @@ public class BaseMap {
|
||||
} else {
|
||||
// prefer drawing parent
|
||||
if (parent) {
|
||||
MapTile t = tile.rel.parent.tile;
|
||||
|
||||
if (t != null && t.state == STATE_READY) {
|
||||
drawTile(t, pos);
|
||||
return;
|
||||
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
||||
MapTile t = tile.rel.parent.tile;
|
||||
if (t != null && t.state == STATE_READY) {
|
||||
drawTile(t, pos);
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
drawProxyChild(tile, pos);
|
||||
|
||||
} else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
|
||||
|
@ -27,6 +27,7 @@ public class GLState {
|
||||
private static boolean blend = false;
|
||||
private static boolean depth = false;
|
||||
private static boolean stencil = false;
|
||||
private static int shader;
|
||||
|
||||
public static void init() {
|
||||
vertexArray[0] = false;
|
||||
@ -34,11 +35,19 @@ public class GLState {
|
||||
blend = false;
|
||||
depth = false;
|
||||
stencil = false;
|
||||
|
||||
shader = -1;
|
||||
GLES20.glDisable(GLES20.GL_STENCIL_TEST);
|
||||
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
public static void useProgram(int shaderProgram) {
|
||||
if (shaderProgram != shader) {
|
||||
GLES20.glUseProgram(shaderProgram);
|
||||
shader = shaderProgram;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
public static void blend(boolean enable) {
|
||||
if (blend == enable)
|
||||
return;
|
||||
|
@ -20,9 +20,7 @@ import static android.opengl.GLES20.glDrawArrays;
|
||||
import static android.opengl.GLES20.glGetAttribLocation;
|
||||
import static android.opengl.GLES20.glGetUniformLocation;
|
||||
import static android.opengl.GLES20.glUniform1f;
|
||||
import static android.opengl.GLES20.glUniform1i;
|
||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
||||
import static android.opengl.GLES20.glUseProgram;
|
||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
@ -119,7 +117,7 @@ public final class LineRenderer {
|
||||
if (layer == null)
|
||||
return null;
|
||||
|
||||
glUseProgram(lineProgram[mode]);
|
||||
GLState.useProgram(lineProgram[mode]);
|
||||
|
||||
int uLineScale = hLineScale[mode];
|
||||
int uLineMode = hLineMode[mode];
|
||||
@ -153,7 +151,7 @@ public final class LineRenderer {
|
||||
|
||||
glUniform1f(uLineScale, pixel);
|
||||
int lineMode = 0;
|
||||
glUniform1i(uLineMode, lineMode);
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
|
||||
float blurScale = pixel;
|
||||
boolean blur = false;
|
||||
@ -209,11 +207,11 @@ public final class LineRenderer {
|
||||
if (o.roundCap) {
|
||||
if (lineMode != 1) {
|
||||
lineMode = 1;
|
||||
glUniform1i(uLineMode, lineMode);
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
}
|
||||
} else if (lineMode != 0) {
|
||||
lineMode = 0;
|
||||
glUniform1i(uLineMode, lineMode);
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
}
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
|
||||
}
|
||||
@ -244,11 +242,11 @@ public final class LineRenderer {
|
||||
if (ll.roundCap) {
|
||||
if (lineMode != 1) {
|
||||
lineMode = 1;
|
||||
glUniform1i(uLineMode, lineMode);
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
}
|
||||
} else if (lineMode != 0) {
|
||||
lineMode = 0;
|
||||
glUniform1i(uLineMode, lineMode);
|
||||
glUniform1f(uLineMode, lineMode);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
|
||||
@ -263,8 +261,9 @@ public final class LineRenderer {
|
||||
+ "uniform mat4 u_mvp;"
|
||||
+ "uniform float u_width;"
|
||||
+ "attribute vec4 a_pos;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform float u_mode;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "varying vec2 v_mode;"
|
||||
+ "const float dscale = 8.0/2048.0;"
|
||||
+ "void main() {"
|
||||
// scale extrusion to u_width pixel
|
||||
@ -274,22 +273,27 @@ public final class LineRenderer {
|
||||
// last two bits of a_st hold the texture coordinates
|
||||
// ..maybe one could wrap texture so that `abs` is not required
|
||||
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
|
||||
+ " v_mode = vec2(1.0 - u_mode, u_mode);"
|
||||
+ "}";
|
||||
|
||||
private final static String lineSimpleFragmentShader = ""
|
||||
+ "precision mediump float;"
|
||||
+ "uniform sampler2D tex;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform float u_width;"
|
||||
+ "uniform float u_wscale;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "varying vec2 v_mode;"
|
||||
+ "void main() {"
|
||||
+ " float len;"
|
||||
+ " if (u_mode == 0)"
|
||||
+ " len = abs(v_st.s);"
|
||||
+ " else"
|
||||
+ " len = texture2D(tex, v_st).a;"
|
||||
//+ " float len;"
|
||||
// some say one should not use conditionals
|
||||
// (FIXME currently required as overlay line renderers dont load the texture)
|
||||
//+ " if (u_mode == 0)"
|
||||
//+ " len = abs(v_st.s);"
|
||||
//+ " else"
|
||||
//+ " len = texture2D(tex, v_st).a;"
|
||||
// one trick to avoid branching, need to check performance
|
||||
+ " float len = max(v_mode[0] * abs(v_st.s), v_mode[1] * texture2D(tex, v_st).a);"
|
||||
// interpolate alpha between: 0.0 < 1.0 - len < u_wscale
|
||||
// where wscale is 'filter width' / 'line width' and 0 <= len <= sqrt(2)
|
||||
+ " gl_FragColor = u_color * smoothstep(0.0, u_wscale, 1.0 - len);"
|
||||
@ -300,7 +304,7 @@ public final class LineRenderer {
|
||||
+ "#extension GL_OES_standard_derivatives : enable\n"
|
||||
+ "precision mediump float;"
|
||||
+ "uniform sampler2D tex;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform float u_mode;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "uniform float u_width;"
|
||||
+ "uniform float u_wscale;"
|
||||
@ -308,7 +312,7 @@ public final class LineRenderer {
|
||||
+ "void main() {"
|
||||
+ " float len;"
|
||||
+ " float fuzz;"
|
||||
+ " if (u_mode == 0){"
|
||||
+ " if (u_mode == 0.0){"
|
||||
+ " len = abs(v_st.s);"
|
||||
+ " fuzz = fwidth(v_st.s);"
|
||||
+ " } else {"
|
||||
@ -317,10 +321,12 @@ public final class LineRenderer {
|
||||
+ " vec2 st_width = fwidth(v_st);"
|
||||
+ " fuzz = max(st_width.s, st_width.t);"
|
||||
+ " }"
|
||||
// smoothstep is too sharp, guess one could increase extrusion with z..
|
||||
// but this looks ok too:
|
||||
+ " gl_FragColor = u_color * min(1.0, (1.0 - len) / (u_wscale + fuzz));"
|
||||
//+ " gl_FragColor = u_color * smoothstep(0.0, fuzz + u_wscale, 1.0 - len);"
|
||||
// smoothstep is too sharp, guess one could increase extrusion with z..
|
||||
// this looks ok:
|
||||
//+ " gl_FragColor = u_color * min(1.0, (1.0 - len) / (u_wscale + fuzz));"
|
||||
// can be faster according to nvidia docs 'Optimize OpenGL ES 2.0 Performace'
|
||||
+ " gl_FragColor = u_color * clamp((1.0 - len) / (u_wscale + fuzz), 0.0, 1.0);"
|
||||
+ "}";
|
||||
|
||||
// private final static String lineVertexShader = ""
|
||||
|
@ -18,13 +18,11 @@ import static android.opengl.GLES20.GL_ALWAYS;
|
||||
import static android.opengl.GLES20.GL_BLEND;
|
||||
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_TRIANGLE_FAN;
|
||||
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
|
||||
import static android.opengl.GLES20.GL_ZERO;
|
||||
import static android.opengl.GLES20.glColorMask;
|
||||
import static android.opengl.GLES20.glDepthFunc;
|
||||
import static android.opengl.GLES20.glDepthMask;
|
||||
import static android.opengl.GLES20.glDisable;
|
||||
import static android.opengl.GLES20.glDrawArrays;
|
||||
@ -36,7 +34,6 @@ import static android.opengl.GLES20.glStencilMask;
|
||||
import static android.opengl.GLES20.glStencilOp;
|
||||
import static android.opengl.GLES20.glUniform4fv;
|
||||
import static android.opengl.GLES20.glUniformMatrix4fv;
|
||||
import static android.opengl.GLES20.glUseProgram;
|
||||
import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@ -51,7 +48,7 @@ import org.oscim.utils.GlUtils;
|
||||
import android.opengl.GLES20;
|
||||
|
||||
public final class PolygonRenderer {
|
||||
// private static final String TAG = "PolygonRenderer";
|
||||
//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;
|
||||
@ -93,7 +90,7 @@ public final class PolygonRenderer {
|
||||
boolean blend = false;
|
||||
|
||||
/* draw to framebuffer */
|
||||
glColorMask(true, true, true, true);
|
||||
glColorMask(true, true, true, false);
|
||||
|
||||
/* do not modify stencil buffer */
|
||||
glStencilMask(0);
|
||||
@ -144,18 +141,10 @@ public final class PolygonRenderer {
|
||||
glUniform4fv(hPolygonColor, 1, l.area.color, 0);
|
||||
}
|
||||
|
||||
// if (alpha < 1) {
|
||||
// if (!blend) {
|
||||
// glEnable(GL_BLEND);
|
||||
// blend = true;
|
||||
// }
|
||||
// } else if (blend) {
|
||||
// glDisable(GL_BLEND);
|
||||
// blend = false;
|
||||
// }
|
||||
|
||||
/* set stencil buffer mask used to draw this layer */
|
||||
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
|
||||
// set stencil buffer mask used to draw this layer
|
||||
// also check that clip bit is 0 to avoid overdraw
|
||||
// of other tiles
|
||||
glStencilFunc(GL_EQUAL, 0x7f, 0x80 | 1 << c);
|
||||
|
||||
/* draw tile fill coordinates */
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
@ -195,7 +184,7 @@ public final class PolygonRenderer {
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
|
||||
glUseProgram(polygonProgram);
|
||||
GLState.useProgram(polygonProgram);
|
||||
|
||||
GLState.enableVertexArrays(hPolygonVertexPosition, -1);
|
||||
|
||||
@ -204,82 +193,33 @@ public final class PolygonRenderer {
|
||||
|
||||
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
|
||||
|
||||
// reset start when only two layer left in stencil buffer
|
||||
// if (mCount > 5) {
|
||||
// mCount = 0;
|
||||
// mStart = 0;
|
||||
// }
|
||||
|
||||
if (first) {
|
||||
// reset start when only one layer left in stencil buffer
|
||||
if (first || mCount > 5) {
|
||||
mCount = 0;
|
||||
mStart = 0;
|
||||
} else {
|
||||
mStart = mCount;
|
||||
}
|
||||
|
||||
//GLState.test(drawClipped, true);
|
||||
GLState.test(true, true);
|
||||
GLState.test(false, true);
|
||||
|
||||
Layer l = layer;
|
||||
|
||||
for (; l != null && l.type == Layer.POLYGON; l = l.next) {
|
||||
PolygonLayer pl = (PolygonLayer) l;
|
||||
// fade out polygon layers (set in RederTheme)
|
||||
|
||||
// fade out polygon layers (set in RenderTheme)
|
||||
if (pl.area.fade > 0 && pl.area.fade > zoom)
|
||||
continue;
|
||||
|
||||
if (mCount == mStart) {
|
||||
/* clear stencilbuffer (tile region) by drawing
|
||||
* a quad with func 'always' and op 'zero' */
|
||||
|
||||
// disable drawing to framebuffer
|
||||
glColorMask(false, false, false, false);
|
||||
|
||||
// if (!first) {
|
||||
// // first run draw map bg, otherwise
|
||||
// // disable drawing to framebuffer
|
||||
// glColorMask(false, false, false, false);
|
||||
// } else {
|
||||
// glUniform4fv(hPolygonColor, 1, GLRenderer.mClearColor, 0);
|
||||
// }
|
||||
|
||||
// never pass the test: always apply fail op
|
||||
glStencilFunc(GL_ALWAYS, 0, 0xFF);
|
||||
glStencilMask(0xFF);
|
||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
|
||||
/* draw clip-region into depth buffer:
|
||||
* this is used for lines and polygons */
|
||||
if (first && drawClipped) {
|
||||
// write to depth buffer
|
||||
glDepthMask(true);
|
||||
|
||||
// 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 (first) {
|
||||
// glColorMask(false, false, false, false);
|
||||
// }
|
||||
|
||||
if (first && drawClipped) {
|
||||
first = false;
|
||||
// do not modify depth buffer anymore
|
||||
glDepthMask(false);
|
||||
// only draw to this tile
|
||||
glDepthFunc(GL_EQUAL);
|
||||
}
|
||||
drawStencilRegion(drawClipped, first);
|
||||
first = false;
|
||||
|
||||
// op for stencil method polygon drawing
|
||||
glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GL_INVERT);
|
||||
}
|
||||
|
||||
// no need for depth test while drawing stencil
|
||||
//GLState.test(false, true);
|
||||
|
||||
mFillPolys[mCount] = pl;
|
||||
|
||||
// set stencil mask to draw to
|
||||
@ -287,43 +227,113 @@ public final class PolygonRenderer {
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.verticesCnt);
|
||||
|
||||
// draw up to 8 layers into stencil buffer
|
||||
if (mCount == STENCIL_BITS) {
|
||||
/* only draw where nothing was drawn yet */
|
||||
if (drawClipped)
|
||||
GLState.test(true, true);
|
||||
|
||||
// draw up to 7 layers into stencil buffer
|
||||
if (mCount == STENCIL_BITS - 1) {
|
||||
fillPolygons(zoom, scale);
|
||||
mCount = 0;
|
||||
mStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCount > 0) {
|
||||
/* only draw where nothing was drawn yet */
|
||||
if (drawClipped)
|
||||
GLState.test(true, true);
|
||||
|
||||
if (mCount > 0)
|
||||
fillPolygons(zoom, scale);
|
||||
|
||||
if (drawClipped) {
|
||||
if (first) {
|
||||
drawStencilRegion(drawClipped, first);
|
||||
|
||||
glStencilMask(0x00);
|
||||
glColorMask(true, true, true, false);
|
||||
}
|
||||
|
||||
// clip bit must be zero
|
||||
glStencilFunc(GL_EQUAL, 0x00, 0x80);
|
||||
}
|
||||
|
||||
if (drawClipped && first) {
|
||||
GLState.test(true, false);
|
||||
GLES20.glColorMask(false, false, false, false);
|
||||
//glUniform4fv(hPolygonColor, 1, GLRenderer.mClearColor, 0);
|
||||
|
||||
GLES20.glDepthMask(true);
|
||||
GLES20.glDepthFunc(GLES20.GL_LESS);
|
||||
|
||||
GLES20.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
GLES20.glDepthMask(false);
|
||||
GLES20.glColorMask(true, true, true, true);
|
||||
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
static void drawStencilRegion(boolean clip, boolean first) {
|
||||
/* 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);
|
||||
GLES20.glUniform4f(hPolygonColor, 0.7f, 0.7f, 0.7f, 1);
|
||||
|
||||
// write to all bits
|
||||
glStencilMask(0xFF);
|
||||
// zero out area to draw to
|
||||
glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GL_ZERO);
|
||||
|
||||
if (clip) {
|
||||
if (first) {
|
||||
// draw clip-region into depth and stencil buffer:
|
||||
// this is used for tile line and polygon layers
|
||||
|
||||
// always pass stencil test:
|
||||
glStencilFunc(GL_ALWAYS, 0x00, 0x00);
|
||||
|
||||
GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
// test depth. stencil passes always, just keep it enabled
|
||||
GLState.test(true, true);
|
||||
// write to depth buffer
|
||||
glDepthMask(true);
|
||||
}
|
||||
else {
|
||||
// use clip region from stencil buffer
|
||||
glStencilFunc(GL_EQUAL, 0x00, 0x80);
|
||||
}
|
||||
} else {
|
||||
// always pass stencil test:
|
||||
glStencilFunc(GL_ALWAYS, 0x00, 0x00);
|
||||
}
|
||||
|
||||
// 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);
|
||||
} else {
|
||||
glStencilFunc(GL_ALWAYS, 0x00, 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, 0xFF, 0xFF);
|
||||
// write to all bits
|
||||
glStencilMask(0xFF);
|
||||
// zero out area to draw to
|
||||
glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_REPLACE);
|
||||
|
||||
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 };
|
||||
private static FloatBuffer mDebugFill;
|
||||
@ -339,7 +349,7 @@ public final class PolygonRenderer {
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
mDebugFill.position(0);
|
||||
glUseProgram(polygonProgram);
|
||||
GLState.useProgram(polygonProgram);
|
||||
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
|
||||
|
||||
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_FLOAT,
|
||||
|
@ -93,7 +93,7 @@ public final class TextureRenderer {
|
||||
GLState.test(false, false);
|
||||
GLES20.glEnable(GLES20.GL_BLEND);
|
||||
// GlUtils.checkGlError("draw texture >");
|
||||
GLES20.glUseProgram(mTextureProgram);
|
||||
GLState.useProgram(mTextureProgram);
|
||||
|
||||
GLState.enableVertexArrays(hTextureTexCoord, hTextureVertex);
|
||||
|
||||
|
@ -350,7 +350,7 @@ public class BuildingOverlay extends RenderOverlay {
|
||||
setMatrix(pos, mv);
|
||||
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
|
||||
|
||||
GLES20.glUseProgram(buildingProgram);
|
||||
GLState.useProgram(buildingProgram);
|
||||
|
||||
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
|
||||
GLES20.glUniform4f(hBuildingColor, 0.5f, 0.5f, 0.5f, 0.7f);
|
||||
|
@ -180,7 +180,7 @@ public class ExtrusionOverlay extends RenderOverlay {
|
||||
int uExtMode = hExtrusionMode[shaderMode];
|
||||
|
||||
if (debug) {
|
||||
GLES20.glUseProgram(extrusionProgram[shaderMode]);
|
||||
GLState.useProgram(extrusionProgram[shaderMode]);
|
||||
|
||||
GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition);
|
||||
GLES20.glUniform1i(uExtMode, 0);
|
||||
@ -224,9 +224,11 @@ public class ExtrusionOverlay extends RenderOverlay {
|
||||
|
||||
GLState.test(true, false);
|
||||
|
||||
GLES20.glUseProgram(extrusionProgram[shaderMode]);
|
||||
GLState.useProgram(extrusionProgram[shaderMode]);
|
||||
GLState.enableVertexArrays(uExtVertexPosition, -1);
|
||||
if (pos.scale < 2) {
|
||||
// chances are high that one moves through a building
|
||||
// with scale > 2 also draw back sides in this case.
|
||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
||||
GLES20.glCullFace(GLES20.GL_FRONT);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public class ModelOverlay extends RenderOverlay {
|
||||
setMatrix(pos, mv);
|
||||
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
|
||||
|
||||
GLES20.glUseProgram(polygonProgram);
|
||||
GLState.useProgram(polygonProgram);
|
||||
|
||||
GLState.enableVertexArrays(hPolygonVertexPosition, hPolygonLightPosition);
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
//
|
||||
// Vertex layout:
|
||||
// x/y pos[16][16], dir_x[8]|dir_y[8], start[4]|length[12]
|
||||
// - 'direction' precision 1/16 maximum line width is 2*32
|
||||
// - 'direction' precision 1/16, maximum line width is 2*16
|
||||
// - texture 'start' prescision 1
|
||||
// -> max tex width is 32
|
||||
// - segment 'length' prescision 1/4
|
||||
@ -99,16 +99,18 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
0, 0, 0, 0,
|
||||
};
|
||||
|
||||
private final short[] indices = {
|
||||
private short[] indices = {
|
||||
0, 1, 2,
|
||||
2, 1, 3,
|
||||
|
||||
4, 5, 6,
|
||||
6, 5, 7,
|
||||
|
||||
8, 9, 10,
|
||||
10, 9, 11,
|
||||
};
|
||||
|
||||
private byte[] flip = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
|
||||
private byte[] flip;
|
||||
|
||||
private static int testProgram;
|
||||
private static int htestVertexPosition0;
|
||||
@ -131,13 +133,14 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
+ "const float ffff = 65536.0;"
|
||||
+ "void main() {"
|
||||
+ " if (a_flip == 0.0){"
|
||||
+ " vec2 dir = vec2((a_pos0.z / ffff), fract(a_pos0.z/ff))*64.0;"
|
||||
// extract 8 bit direction vector
|
||||
+ " vec2 dir = a_pos0.zw/16.0;"
|
||||
+ " gl_Position = u_mvp * vec4(a_pos0.xy + dir, 0.0, 1.0);"
|
||||
+ " color = vec4(0.0,1.0,a_pos0.w,1.0);"
|
||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.0);"
|
||||
+ " }else {"
|
||||
+ " vec2 dir = vec2((a_pos1.z / ffff), fract(a_pos1.z/ff))*64.0;"
|
||||
+ " vec2 dir = a_pos1.zw/16.0;"
|
||||
+ " gl_Position = u_mvp * vec4(a_pos1.xy - dir, 0.0, 1.0);"
|
||||
+ " color = vec4(1.0,0.5,a_pos1.w,1.0);"
|
||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.0);"
|
||||
+ "}}";
|
||||
|
||||
final static String testFragmentShader = ""
|
||||
@ -151,6 +154,9 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
private int mVertexBufferID;
|
||||
private int mVertexFlipID;
|
||||
|
||||
private int mNumVertices;
|
||||
private int mNumIndices;
|
||||
|
||||
@Override
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
||||
boolean tilesChanged) {
|
||||
@ -178,6 +184,93 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
mVertexBufferID = mVboIds[1];
|
||||
mVertexFlipID = mVboIds[2];
|
||||
|
||||
float points[] = {
|
||||
800, 0,
|
||||
0, 0,
|
||||
//-400, 100,
|
||||
//-600, 200,
|
||||
//-800, 100,
|
||||
};
|
||||
|
||||
// float[] points = new float[12 * 2];
|
||||
// for (int i = 0; i < 24; i += 2) {
|
||||
// points[i + 0] = (float) Math.sin(-i / 11f * Math.PI) * 400;
|
||||
// points[i + 1] = (float) Math.cos(-i / 11f * Math.PI) * 400;
|
||||
// }
|
||||
|
||||
mNumVertices = (points.length - 2) * 2;
|
||||
|
||||
short[] vertices = new short[(mNumVertices + 2) * 4];
|
||||
|
||||
int opos = 4;
|
||||
|
||||
float x = points[0];
|
||||
float y = points[1];
|
||||
|
||||
float scale = 127;
|
||||
boolean even = true;
|
||||
|
||||
for (int i = 2; i < points.length;) {
|
||||
float nx = points[i++];
|
||||
float ny = points[i++];
|
||||
|
||||
// Calculate triangle corners for the given width
|
||||
float vx = nx - x;
|
||||
float vy = ny - y;
|
||||
|
||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
|
||||
// normal vector
|
||||
vx = (vx / a);
|
||||
vy = (vy / a);
|
||||
|
||||
float ux = -vy;
|
||||
float uy = vx;
|
||||
|
||||
short dx = (short) (ux * scale);
|
||||
short dy = (short) (uy * scale);
|
||||
|
||||
vertices[opos + 0] = (short) x;
|
||||
vertices[opos + 1] = (short) y;
|
||||
vertices[opos + 2] = dx;
|
||||
vertices[opos + 3] = dy;
|
||||
|
||||
vertices[opos + 8] = (short) nx;
|
||||
vertices[opos + 9] = (short) ny;
|
||||
vertices[opos + 10] = dx;
|
||||
vertices[opos + 11] = dy;
|
||||
|
||||
x = nx;
|
||||
y = ny;
|
||||
|
||||
if (even) {
|
||||
opos += 4;
|
||||
even = false;
|
||||
} else {
|
||||
even = true;
|
||||
opos += 12;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
flip = new byte[(points.length - 2)];
|
||||
for (int i = 0; i < flip.length; i++)
|
||||
flip[i] = (byte) (i % 2);
|
||||
|
||||
short j = 0;
|
||||
mNumIndices = ((points.length) >> 2) * 6;
|
||||
|
||||
indices = new short[mNumIndices];
|
||||
for (int i = 0; i < mNumIndices; i += 6, j += 4) {
|
||||
indices[i + 0] = (short) (j + 0);
|
||||
indices[i + 1] = (short) (j + 1);
|
||||
indices[i + 2] = (short) (j + 2);
|
||||
|
||||
indices[i + 3] = (short) (j + 2);
|
||||
indices[i + 4] = (short) (j + 1);
|
||||
indices[i + 5] = (short) (j + 3);
|
||||
}
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(128 * 4)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
|
||||
@ -185,20 +278,24 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
sbuf.put(indices);
|
||||
sbuf.flip();
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
|
||||
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 18 * 2, sbuf, GLES20.GL_STATIC_DRAW);
|
||||
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length * 2, sbuf,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
sbuf.clear();
|
||||
sbuf.put(box);
|
||||
//sbuf.put(box);
|
||||
sbuf.put(vertices);
|
||||
sbuf.flip();
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 56 * 2, sbuf, GLES20.GL_STATIC_DRAW);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.length * 2, sbuf,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
|
||||
buf.clear();
|
||||
buf.put(flip);
|
||||
buf.flip();
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 12, buf, GLES20.GL_STATIC_DRAW);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, flip.length, buf,
|
||||
GLES20.GL_STATIC_DRAW);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
@ -213,12 +310,13 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
setMatrix(pos, mv);
|
||||
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
|
||||
|
||||
GLES20.glUseProgram(testProgram);
|
||||
GLState.useProgram(testProgram);
|
||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||
GLState.test(false, false);
|
||||
GLState.enableVertexArrays(-1, -1);
|
||||
GLES20.glEnableVertexAttribArray(htestVertexPosition0);
|
||||
GLES20.glEnableVertexAttribArray(htestVertexPosition1);
|
||||
|
||||
GLES20.glEnableVertexAttribArray(htestVertexFlip);
|
||||
|
||||
GLES20.glUniformMatrix4fv(htestMatrix, 1, false, mv, 0);
|
||||
@ -230,15 +328,23 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition0, 4, GLES20.GL_SHORT, false, 0, 8);
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition1, 4, GLES20.GL_SHORT, false, 0, 0);
|
||||
GLES20.glUniform4f(htestColor, 0.5f, 0.5f, 1.0f, 1.0f);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 18, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
||||
4, GLES20.GL_SHORT, false, 0, 8);
|
||||
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
||||
4, GLES20.GL_SHORT, false, 0, 0);
|
||||
|
||||
GLES20.glUniform4f(htestColor, 0.5f, 0.5f, 1.0f, 1.0f);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
||||
4, GLES20.GL_SHORT, false, 0, 16);
|
||||
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
||||
4, GLES20.GL_SHORT, false, 0, 8);
|
||||
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition0, 4, GLES20.GL_SHORT, false, 0, 16);
|
||||
GLES20.glVertexAttribPointer(htestVertexPosition1, 4, GLES20.GL_SHORT, false, 0, 8);
|
||||
GLES20.glUniform4f(htestColor, 0.5f, 1.0f, 0.5f, 1.0f);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 18, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user