starting to add some perspective

This commit is contained in:
Hannes Janetzek 2012-09-18 15:45:30 +02:00
parent 7ac44bc3df
commit 19344e39cf
7 changed files with 282 additions and 202 deletions

View File

@ -34,6 +34,7 @@ public class MapViewPosition {
private byte mZoomLevel; private byte mZoomLevel;
private float mScale; private float mScale;
private float mRotation; private float mRotation;
private float mTilt;
MapViewPosition(MapView mapView) { MapViewPosition(MapView mapView) {
mMapView = mapView; mMapView = mapView;
@ -43,6 +44,7 @@ public class MapViewPosition {
mZoomLevel = -1; mZoomLevel = -1;
mScale = 1; mScale = 1;
mRotation = 0.0f; mRotation = 0.0f;
mTilt = 0;
} }
/** /**
@ -184,6 +186,10 @@ public class MapViewPosition {
mRotation = f; mRotation = f;
} }
public void setTile(float f) {
mTilt = f;
}
synchronized void setMapCenter(GeoPoint geoPoint) { synchronized void setMapCenter(GeoPoint geoPoint) {
mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude()); mLatitude = MercatorProjection.limitLatitude(geoPoint.getLatitude());
mLongitude = MercatorProjection.limitLongitude(geoPoint.getLongitude()); mLongitude = MercatorProjection.limitLongitude(geoPoint.getLongitude());

View File

@ -34,6 +34,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
@ -48,7 +49,6 @@ import android.opengl.GLES20;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
import android.opengl.Matrix; import android.opengl.Matrix;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.FloatMath;
import android.util.Log; import android.util.Log;
public class GLRenderer implements GLSurfaceView.Renderer { public class GLRenderer implements GLSurfaceView.Renderer {
@ -57,11 +57,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static final int MB = 1024 * 1024; private static final int MB = 1024 * 1024;
private static final int SHORT_BYTES = 2; private static final int SHORT_BYTES = 2;
static final float COORD_MULTIPLIER = 8.0f; private static final int CACHE_TILES_MAX = 250;
private static final int CACHE_TILES_MAX = 200;
private static final int LIMIT_BUFFERS = 16 * MB; private static final int LIMIT_BUFFERS = 16 * MB;
static final float COORD_MULTIPLIER = 8.0f;
static int CACHE_TILES = CACHE_TILES_MAX; static int CACHE_TILES = CACHE_TILES_MAX;
private final MapView mMapView; private final MapView mMapView;
@ -100,7 +100,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static boolean mUpdateColor = false; private static boolean mUpdateColor = false;
// lock to synchronize Main- and GL-Thread // lock to synchronize Main- and GL-Thread
static Object lock = new Object(); static ReentrantLock tilelock = new ReentrantLock();
// used for passing tiles to be rendered from TileLoader(Main-Thread) to GLThread // used for passing tiles to be rendered from TileLoader(Main-Thread) to GLThread
static class TilesData { static class TilesData {
@ -145,56 +145,57 @@ public class GLRenderer implements GLSurfaceView.Renderer {
* @return curTiles (the previously active tiles) * @return curTiles (the previously active tiles)
*/ */
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) { static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
synchronized (GLRenderer.lock) { GLRenderer.tilelock.lock();
mCurPosition = mapPosition; mCurPosition = mapPosition;
// unlock previously active tiles // unlock previously active tiles
for (int i = 0; i < curTiles.cnt; i++) { for (int i = 0; i < curTiles.cnt; i++) {
MapTile t = curTiles.tiles[i]; MapTile t = curTiles.tiles[i];
boolean found = false; boolean found = false;
for (int j = 0; j < tiles.cnt; j++) { for (int j = 0; j < tiles.cnt; j++) {
if (tiles.tiles[j] == t) { if (tiles.tiles[j] == t) {
found = true; found = true;
break; break;
}
} }
if (found)
continue;
for (int j = 0; j < drawTiles.cnt; j++) {
if (drawTiles.tiles[j] == t) {
found = true;
break;
}
}
if (found)
continue;
t.unlock();
}
TilesData tmp = curTiles;
curTiles = tiles;
// lock tiles (and their proxies) to not be removed from cache
for (int i = 0; i < curTiles.cnt; i++) {
MapTile t = curTiles.tiles[i];
if (!t.isActive)
t.lock();
} }
if (found)
continue;
for (int j = 0; j < drawTiles.cnt; j++) { for (int j = 0; j < drawTiles.cnt; j++) {
MapTile t = drawTiles.tiles[j]; if (drawTiles.tiles[j] == t) {
if (!t.isActive) found = true;
t.lock(); break;
}
} }
if (found)
continue;
mUpdateTiles = true; t.unlock();
return tmp;
} }
TilesData tmp = curTiles;
curTiles = tiles;
// lock tiles (and their proxies) to not be removed from cache
for (int i = 0; i < curTiles.cnt; i++) {
MapTile t = curTiles.tiles[i];
if (!t.isActive)
t.lock();
}
for (int j = 0; j < drawTiles.cnt; j++) {
MapTile t = drawTiles.tiles[j];
if (!t.isActive)
t.lock();
}
mUpdateTiles = true;
GLRenderer.tilelock.unlock();
return tmp;
} }
/** /**
@ -236,8 +237,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static boolean mRotate = false; private static boolean mRotate = false;
private static void setMatrix(MapPosition mapPosition, MapTile tile, float div, private static void setMatrix(float[] matrix, MapPosition mapPosition, MapTile tile,
int offset) { float div, int offset, boolean project) {
float x, y, scale; float x, y, scale;
if (mRotate) { if (mRotate) {
@ -245,31 +246,47 @@ public class GLRenderer implements GLSurfaceView.Renderer {
x = (float) (tile.pixelX - mapPosition.x * div); x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mapPosition.y * div); y = (float) (tile.pixelY - mapPosition.y * div);
Matrix.setIdentityM(mMVPMatrix, 0); Matrix.setIdentityM(matrix, 0);
Matrix.scaleM(mMVPMatrix, 0, scale / COORD_MULTIPLIER, // scale to tile coordinates
Matrix.scaleM(matrix, 0, scale / COORD_MULTIPLIER,
scale / COORD_MULTIPLIER, 1); scale / COORD_MULTIPLIER, 1);
Matrix.translateM(mMVPMatrix, 0, // translate to center
Matrix.translateM(matrix, 0,
x * COORD_MULTIPLIER, x * COORD_MULTIPLIER,
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER, -(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
-0.99f + offset * 0.01f); // -0.99f + offset * 0.01f,
-1.000f
);
Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0); // Matrix.setRotateM(mRotTMatrix, 0, -35, 1, 0, 0);
// Matrix.multiplyMM(matrix, 0, mRotTMatrix, 0, matrix, 0);
// Matrix.translateM(matrix, 0, 0, 5000.2f, 0);
Matrix.multiplyMM(matrix, 0, mRotateMatrix, 0, matrix, 0);
float angle = 25;
Matrix.setRotateM(mRotTMatrix, 0, -angle, 1, 0, 0);
Matrix.translateM(mRotTMatrix, 0, 0, (float) Math.tan(Math.toRadians(angle)),
0);
Matrix.multiplyMM(matrix, 0, mRotTMatrix, 0, matrix, 0);
if (project)
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
} }
else { else {
scale = (float) (2.0 * mapPosition.scale / (mHeight * div)); scale = (float) (2.0 * mapPosition.scale / (mHeight * div));
x = (float) (tile.pixelX - mapPosition.x * div); x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mapPosition.y * div); y = (float) (tile.pixelY - mapPosition.y * div);
mMVPMatrix[12] = x * scale * mAspect; matrix[12] = x * scale * mAspect;
mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale; matrix[13] = -(y + Tile.TILE_SIZE) * scale;
// increase the 'distance' with each tile drawn. // increase the 'distance' with each tile drawn.
mMVPMatrix[14] = -0.99f + offset * 0.01f; // depthStep; // 0.01f; matrix[14] = -0.99f + offset * 0.01f;
mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER; matrix[0] = scale * mAspect / COORD_MULTIPLIER;
mMVPMatrix[5] = scale / COORD_MULTIPLIER; matrix[5] = scale / COORD_MULTIPLIER;
} }
} }
@ -468,15 +485,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (MapView.debugFrameTime) if (MapView.debugFrameTime)
start = SystemClock.uptimeMillis(); start = SystemClock.uptimeMillis();
if (mRotate != (mMapView.enableRotation || mMapView.enableCompass)) {
Matrix.setIdentityM(mMVPMatrix, 0);
mRotate = mMapView.enableRotation || mMapView.enableCompass;
}
if (mUpdateColor && mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
mUpdateColor = false;
}
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
// Note: having the impression it is faster to also clear the // Note: having the impression it is faster to also clear the
@ -485,23 +493,41 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// memory region afaik // memory region afaik
glClear(GLES20.GL_COLOR_BUFFER_BIT glClear(GLES20.GL_COLOR_BUFFER_BIT
| GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_STENCIL_BUFFER_BIT); // | GLES20.GL_STENCIL_BUFFER_BIT
);
// get position and current tiles to draw // get position and current tiles to draw
synchronized (GLRenderer.lock) { GLRenderer.tilelock.lock();
mapPosition = mCurPosition; mapPosition = mCurPosition;
if (mUpdateTiles) { if (mUpdateTiles) {
TilesData tmp = drawTiles; TilesData tmp = drawTiles;
drawTiles = curTiles; drawTiles = curTiles;
curTiles = tmp; curTiles = tmp;
mUpdateTiles = false; mUpdateTiles = false;
}
} }
GLRenderer.tilelock.unlock();
if (drawTiles == null) if (drawTiles == null)
return; return;
if (mRotate != (mMapView.enableRotation || mMapView.enableCompass)) {
Matrix.setIdentityM(mMVPMatrix, 0);
mRotate = mMapView.enableRotation || mMapView.enableCompass;
}
if (mRotate) {
// Matrix.setRotateM(mRotTMatrix, 0, -10, 1, 0, 0);
Matrix.setRotateM(mRotateMatrix, 0, mapPosition.angle, 0, 0, 1);
// Matrix.multiplyMM(mRotateMatrix, 0, mRotateMatrix, 0, mRotTMatrix, 0);
Matrix.transposeM(mRotTMatrix, 0, mRotateMatrix, 0);
}
if (mUpdateColor && mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
mUpdateColor = false;
}
int tileCnt = drawTiles.cnt; int tileCnt = drawTiles.cnt;
MapTile[] tiles = drawTiles.tiles; MapTile[] tiles = drawTiles.tiles;
@ -547,15 +573,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (updateTextures > 0) if (updateTextures > 0)
TextRenderer.compileTextures(); TextRenderer.compileTextures();
if (mRotate) {
Matrix.setRotateM(mRotateMatrix, 0, mapPosition.angle, 0, 0, 1);
Matrix.transposeM(mRotTMatrix, 0, mRotateMatrix, 0);
} else {
Matrix.setIdentityM(mRotTMatrix, 0);
}
GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && tiles[i].isReady) { if (tiles[i].isVisible && tiles[i].isReady) {
drawTile(mapPosition, tiles[i], 1); drawTile(mapPosition, tiles[i], 1);
@ -571,7 +590,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
} }
// GlUtils.checkGlError("end draw"); // GlUtils.checkGlError("end draw");
glDisable(GLES20.GL_DEPTH_TEST); GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
mDrawCount = 0; mDrawCount = 0;
mDrawSerial++; mDrawSerial++;
@ -585,20 +605,25 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (scale < 1) if (scale < 1)
scale = 1; scale = 1;
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL) // if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix); // TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix);
else // else
TextRenderer.beginDraw(s, mRotTMatrix); // TextRenderer.beginDraw(s, mRotTMatrix);
s = (float) (1.0 / mHeight) / COORD_MULTIPLIER;
TextRenderer.beginDraw(s, mProjMatrix);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null) if (!tiles[i].isVisible || tiles[i].texture == null)
continue; continue;
setMatrix(mapPosition, tiles[i], 1, 0); setMatrix(mMVPMatrix, mapPosition, tiles[i], 1, 0, false);
TextRenderer.drawTile(tiles[i], mMVPMatrix); TextRenderer.drawTile(tiles[i], mMVPMatrix);
} }
TextRenderer.endDraw(); TextRenderer.endDraw();
// TODO call overlay renderer
if (MapView.debugFrameTime) { if (MapView.debugFrameTime) {
GLES20.glFinish(); GLES20.glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start)); Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
@ -617,10 +642,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
int z = mapPosition.zoomLevel; int z = mapPosition.zoomLevel;
float s = mapPosition.scale; float s = mapPosition.scale;
// mDrawCount is used to calculation z offset. // mDrawCount is used to calculation z offset.
// (used for depth clipping) // (used for depth clipping)
setMatrix(mapPosition, tile, div, mDrawCount++); setMatrix(mMVPMatrix, mapPosition, tile, div, mDrawCount++, true);
GLES20.glPolygonOffset(0, mDrawCount);
float offset = 0.0f;
glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id); glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
@ -642,20 +670,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (pl != null && pnext < lnext) { if (pl != null && pnext < lnext) {
glDisable(GL_BLEND); glDisable(GL_BLEND);
pl = PolygonRenderer.drawPolygons(pl, lnext, mMVPMatrix, z, s, !clipped); pl = PolygonRenderer.drawPolygons(pl, lnext, mMVPMatrix, offset, z, s,
!clipped);
clipped = true; clipped = true;
} else { } else {
// XXX nasty // XXX nasty
if (!clipped) { if (!clipped) {
PolygonRenderer.drawPolygons(null, 0, mMVPMatrix, z, s, true); PolygonRenderer.drawPolygons(null, 0, mMVPMatrix, offset, z, s, true);
clipped = true; clipped = true;
} }
glEnable(GL_BLEND); glEnable(GL_BLEND);
ll = LineRenderer.drawLines(tile, ll, pnext, mMVPMatrix, div, z, s); ll = LineRenderer.drawLines(tile, ll, pnext, mMVPMatrix, offset, div, z,
s);
} }
} }
} }
@ -725,9 +755,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
public void onSurfaceChanged(GL10 glUnused, int width, int height) { public void onSurfaceChanged(GL10 glUnused, int width, int height) {
Log.d(TAG, "SurfaceChanged:" + width + " " + height); Log.d(TAG, "SurfaceChanged:" + width + " " + height);
mWidth = width;
mHeight = height;
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
return; return;
@ -735,13 +762,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (mWidth == width || mHeight == height) if (mWidth == width || mHeight == height)
changed = false; changed = false;
mWidth = width;
mHeight = height;
mAspect = (float) height / width; mAspect = (float) height / width;
Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1); // Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
// Matrix.frustumM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.7f, Matrix.frustumM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
// 1, 100); 0.5f,
1, 4);
// float angle = 35;
// Matrix.setRotateM(mRotTMatrix, 0, -angle, 1, 0, 0);
// Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mRotTMatrix, 0);
// Matrix.translateM(mProjMatrix, 0, 0, (float) Math.tan(Math.toRadians(angle)), 0);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
if (!changed && !mNewSurface) { if (!changed && !mNewSurface) {
@ -749,6 +784,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return; return;
} }
mNewSurface = false;
mBufferMemoryUsage = 0; mBufferMemoryUsage = 0;
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2) int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
@ -766,7 +803,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mVBOs.add(new VertexBufferObject(mVboIds[i])); mVBOs.add(new VertexBufferObject(mVboIds[i]));
// Set up textures // Set up textures
TextRenderer.init(numTiles); TextRenderer.setup(numTiles);
if (mClearColor != null) { if (mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1], glClearColor(mClearColor[0], mClearColor[1],
@ -775,18 +812,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
glClearColor(0.98f, 0.98f, 0.97f, 1.0f); glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
} }
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
// glEnable(GL_SCISSOR_TEST);
// glScissor(0, 0, mWidth, mHeight);
glDisable(GLES20.GL_CULL_FACE);
glBlendFunc(GLES20.GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GlUtils.checkGlError("onSurfaceChanged"); GlUtils.checkGlError("onSurfaceChanged");
glClear(GL_STENCIL_BUFFER_BIT);
mMapView.redrawMap(); mMapView.redrawMap();
} }
@ -808,8 +837,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
shortBuffer = new ShortBuffer[rotateBuffers]; shortBuffer = new ShortBuffer[rotateBuffers];
// add half pixel to tile clip/fill coordinates // add half pixel to tile clip/fill coordinates to avoid rounding issues
// to avoid rounding issues
short min = -4; short min = -4;
short max = (short) ((Tile.TILE_SIZE << 3) + 4); short max = (short) ((Tile.TILE_SIZE << 3) + 4);
mFillCoords = new short[8]; mFillCoords = new short[8];
@ -824,7 +852,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
LineRenderer.init(); LineRenderer.init();
PolygonRenderer.init(); PolygonRenderer.init();
TextRenderer.init();
mNewSurface = true; mNewSurface = true;
// glEnable(GL_SCISSOR_TEST);
// glScissor(0, 0, mWidth, mHeight);
glClearStencil(0);
glDisable(GLES20.GL_CULL_FACE);
glBlendFunc(GLES20.GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} }
private boolean mNewSurface; private boolean mNewSurface;

View File

@ -14,16 +14,6 @@
*/ */
package org.oscim.view.renderer; package org.oscim.view.renderer;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
import static android.opengl.GLES20.glDisableVertexAttribArray;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glUniformMatrix4fv;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import org.oscim.theme.renderinstruction.Line; import org.oscim.theme.renderinstruction.Line;
@ -46,6 +36,7 @@ class LineRenderer {
private static int hLineMatrix; private static int hLineMatrix;
private static int hLineScale; private static int hLineScale;
private static int hLineWidth; private static int hLineWidth;
private static int hLineOffset;
static boolean init() { static boolean init() {
lineProgram = GlUtils.createProgram(Shaders.lineVertexShader, lineProgram = GlUtils.createProgram(Shaders.lineVertexShader,
@ -55,38 +46,41 @@ class LineRenderer {
return false; return false;
} }
hLineMatrix = glGetUniformLocation(lineProgram, "mvp"); hLineMatrix = GLES20.glGetUniformLocation(lineProgram, "u_mvp");
hLineScale = glGetUniformLocation(lineProgram, "u_wscale"); hLineScale = GLES20.glGetUniformLocation(lineProgram, "u_wscale");
hLineWidth = glGetUniformLocation(lineProgram, "u_width"); hLineWidth = GLES20.glGetUniformLocation(lineProgram, "u_width");
hLineColor = glGetUniformLocation(lineProgram, "u_color"); hLineColor = GLES20.glGetUniformLocation(lineProgram, "u_color");
hLineOffset = GLES20.glGetUniformLocation(lineProgram, "u_offset");
hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position"); hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position");
hLineTexturePosition = glGetAttribLocation(lineProgram, "a_st"); hLineTexturePosition = GLES20.glGetAttribLocation(lineProgram, "a_st");
return true; return true;
} }
static final boolean mFast = true; static final boolean mFast = false;
static LineLayer drawLines(MapTile tile, LineLayer layer, int next, float[] matrix, static LineLayer drawLines(MapTile tile, LineLayer layer, int next, float[] matrix,
float div, double zoom, float scale) { float offset, float div, double zoom, float scale) {
float z = 1 / div; float z = 1 / div;
if (layer == null) if (layer == null)
return null; return null;
glUseProgram(lineProgram); GLES20.glUseProgram(lineProgram);
glEnableVertexAttribArray(hLineVertexPosition); GLES20.glEnableVertexAttribArray(hLineVertexPosition);
glEnableVertexAttribArray(hLineTexturePosition); GLES20.glEnableVertexAttribArray(hLineTexturePosition);
glVertexAttribPointer(hLineVertexPosition, 2, GLES20.GL_SHORT, GLES20.glVertexAttribPointer(hLineVertexPosition, 2, GLES20.GL_SHORT,
false, 8, tile.lineOffset + LINE_VERTICES_DATA_POS_OFFSET); false, 8, tile.lineOffset + LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(hLineTexturePosition, 2, GLES20.GL_SHORT, GLES20.glVertexAttribPointer(hLineTexturePosition, 2, GLES20.GL_SHORT,
false, 8, tile.lineOffset + LINE_VERTICES_DATA_TEX_OFFSET); false, 8, tile.lineOffset + LINE_VERTICES_DATA_TEX_OFFSET);
glUniformMatrix4fv(hLineMatrix, 1, false, matrix, 0); GLES20.glUniformMatrix4fv(hLineMatrix, 1, false, matrix, 0);
GLES20.glUniform1f(hLineOffset, offset);
// scale factor to map one pixel on tile to one pixel on screen: // scale factor to map one pixel on tile to one pixel on screen:
float pixel = 2.0f / (scale * z); float pixel = 2.0f / (scale * z);
@ -137,7 +131,7 @@ class LineRenderer {
GLES20.glUniform1f(hLineWidth, l.width / (scale * z) GLES20.glUniform1f(hLineWidth, l.width / (scale * z)
+ o.width / s); + o.width / s);
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
} }
} }
else { else {
@ -153,12 +147,12 @@ class LineRenderer {
GLES20.glUniform1f(hLineWidth, (l.width / s)); GLES20.glUniform1f(hLineWidth, (l.width / s));
} }
glDrawArrays(GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
} }
} }
glDisableVertexAttribArray(hLineVertexPosition); GLES20.glDisableVertexAttribArray(hLineVertexPosition);
glDisableVertexAttribArray(hLineTexturePosition); GLES20.glDisableVertexAttribArray(hLineTexturePosition);
return l; return l;
} }

View File

@ -91,7 +91,7 @@ public class MapRenderer extends GLSurfaceView {
*/ */
/** /**
* Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to * Update list of visible tiles and passes them to MapRenderer, when not available tiles are created and added to
* JobQueue (mapView.addJobs) for loading by MapGenerator class * JobQueue (mapView.addJobs) for loading by TileGenerator class
* *
* @param clear * @param clear
* ... * ...
@ -116,15 +116,16 @@ public class MapRenderer extends GLSurfaceView {
Log.d(TAG, "CLEAR"); Log.d(TAG, "CLEAR");
mInitial = true; mInitial = true;
synchronized (GLRenderer.lock) { // FIXME still needed?
GLRenderer.tilelock.lock();
for (MapTile t : mTiles) for (MapTile t : mTiles)
clearTile(t); clearTile(t);
mTiles.clear(); mTiles.clear();
mTilesLoaded.clear(); mTilesLoaded.clear();
QuadTree.init(); QuadTree.init();
} GLRenderer.tilelock.unlock();
} }
if (mInitial) { if (mInitial) {
@ -469,7 +470,7 @@ public class MapRenderer extends GLSurfaceView {
} }
/** /**
* called from MapWorker Thread when tile is loaded by MapGenerator * called from MapWorker Thread when tile is loaded by TileGenerator
* *
* @param jobTile * @param jobTile
* ... * ...

View File

@ -51,6 +51,7 @@ class PolygonRenderer {
private static int polygonProgram; private static int polygonProgram;
private static int hPolygonVertexPosition; private static int hPolygonVertexPosition;
private static int hPolygonMatrix; private static int hPolygonMatrix;
private static int hPolygonOffset;
private static int hPolygonColor; private static int hPolygonColor;
static boolean init() { static boolean init() {
@ -62,9 +63,10 @@ class PolygonRenderer {
// Log.e(TAG, "Could not create polygon program."); // Log.e(TAG, "Could not create polygon program.");
return false; return false;
} }
hPolygonMatrix = glGetUniformLocation(polygonProgram, "mvp"); hPolygonMatrix = glGetUniformLocation(polygonProgram, "u_mvp");
hPolygonVertexPosition = glGetAttribLocation(polygonProgram, "a_position");
hPolygonColor = glGetUniformLocation(polygonProgram, "u_color"); hPolygonColor = glGetUniformLocation(polygonProgram, "u_color");
hPolygonOffset = glGetUniformLocation(polygonProgram, "u_offset");
hPolygonVertexPosition = glGetAttribLocation(polygonProgram, "a_position");
mFillPolys = new PolygonLayer[STENCIL_BITS]; mFillPolys = new PolygonLayer[STENCIL_BITS];
@ -80,7 +82,7 @@ class PolygonRenderer {
// do not modify stencil buffer // do not modify stencil buffer
glStencilMask(0); glStencilMask(0);
glEnable(GLES20.GL_DEPTH_TEST); // glEnable(GLES20.GL_DEPTH_TEST);
for (int c = 0; c < count; c++) { for (int c = 0; c < count; c++) {
PolygonLayer l = mFillPolys[c]; PolygonLayer l = mFillPolys[c];
@ -149,7 +151,7 @@ class PolygonRenderer {
} }
static PolygonLayer drawPolygons(PolygonLayer layer, int next, static PolygonLayer drawPolygons(PolygonLayer layer, int next,
float[] matrix, double zoom, float scale, boolean clip) { float[] matrix, float offset, double zoom, float scale, boolean clip) {
int cnt = 0; int cnt = 0;
glUseProgram(polygonProgram); glUseProgram(polygonProgram);
@ -160,7 +162,7 @@ class PolygonRenderer {
POLYGON_VERTICES_DATA_POS_OFFSET); POLYGON_VERTICES_DATA_POS_OFFSET);
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
GLES20.glUniform1f(hPolygonOffset, offset);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
PolygonLayer l = layer; PolygonLayer l = layer;
@ -206,7 +208,7 @@ class PolygonRenderer {
// stencil op for stencil method polygon drawing // stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
glDisable(GLES20.GL_DEPTH_TEST); // glDisable(GLES20.GL_DEPTH_TEST);
} }
mFillPolys[cnt] = l; mFillPolys[cnt] = l;

View File

@ -19,17 +19,23 @@ class Shaders {
final static String lineVertexShader = "" final static String lineVertexShader = ""
+ "precision mediump float;" + "precision mediump float;"
+ "uniform mat4 mvp;" // + "invariant gl_Position;"
+ "uniform mat4 u_mvp;"
+ "uniform float u_width;"
+ "uniform float u_offset;"
+ "attribute vec2 a_position;" + "attribute vec2 a_position;"
+ "attribute vec2 a_st;" + "attribute vec2 a_st;"
+ "varying vec2 v_st;" + "varying vec2 v_st;"
+ "uniform float u_width;"
+ "const float dscale = 8.0/2048.0;" + "const float dscale = 8.0/2048.0;"
+ "void main() {" + "void main() {"
// scale extrusion to u_width pixel // scale extrusion to u_width pixel
// just ignore the two most insignificant bits of a_st :) // just ignore the two most insignificant bits of a_st :)
+ " vec2 dir = dscale * u_width * a_st;" + " vec2 dir = dscale * u_width * a_st;"
+ " gl_Position = mvp * vec4(a_position + dir, 0.0,1.0);" + " vec4 pos = u_mvp * vec4(a_position + dir, 0.0,1.0);"
+ " pos.z = 0.0;"
// + " gl_Position = vec4(pos.xy, u_offset, 1.0);"
+ " gl_Position = pos;"
// + " gl_Position = mvp * vec4(a_position + dir, 0.0,1.0);"
// last two bits of a_st hold the texture coordinates // last two bits of a_st hold the texture coordinates
+ " v_st = u_width * (abs(mod(a_st,4.0)) - 1.0);" + " v_st = u_width * (abs(mod(a_st,4.0)) - 1.0);"
// TODO use bit operations when available (gles 1.3) // TODO use bit operations when available (gles 1.3)
@ -50,53 +56,59 @@ class Shaders {
// + " v_st = u_width * a_st;" // + " v_st = u_width * a_st;"
// + "}"; // + "}";
final static String lineFragmentShader = ""
+ "precision mediump float;"
+ "uniform float u_wscale;"
+ "uniform float u_width;"
+ "uniform vec4 u_color;"
+ "varying vec2 v_st;"
+ "const float zero = 0.0;"
+ "void main() {"
+ " float len;"
+ " if (v_st.t == zero)"
+ " len = abs(v_st.s);"
+ " else "
+ " len = length(v_st);"
// fade to alpha. u_wscale is the width in pixel which should be faded,
// u_width - len the position of this fragment on the perpendicular to
// this line segment
+ " gl_FragColor = smoothstep(zero, u_wscale, u_width - len) * u_color;"
+ "}";
// final static String lineFragmentShader = "" // final static String lineFragmentShader = ""
// + "#extension GL_OES_standard_derivatives : enable\n" // + "precision mediump float;"
// + "precision mediump float;\n"
// + "uniform float u_wscale;" // + "uniform float u_wscale;"
// + "uniform float u_width;" // + "uniform float u_width;"
// + "uniform vec4 u_color;" // + "uniform vec4 u_color;"
// + "varying vec2 v_st;" // + "varying vec2 v_st;"
// + "const float zero = 0.0;" // + "const float zero = 0.0;"
// + "void main() {" // + "void main() {"
// + " vec4 color = u_color;"
// + " float width = u_width;"
// + " float len;" // + " float len;"
// + " if (v_st.t == zero)" // + " if (v_st.t == zero)"
// + " len = abs(v_st.s);" // + " len = abs(v_st.s);"
// + " else " // + " else "
// + " len = length(v_st);" // + " len = length(v_st);"
// + " vec2 st_width = fwidth(v_st);" // // fade to alpha. u_wscale is the width in pixel which should be faded,
// + " float fuzz = max(st_width.s, st_width.t) * 1.5;" // // u_width - len the position of this fragment on the perpendicular to
// + " color.a *= smoothstep(zero, fuzz + u_wscale, u_width - len);" // // this line segment
// + " gl_FragColor = color;" // + " gl_FragColor = smoothstep(zero, u_wscale, u_width - len) * u_color;"
// // + " gl_FragColor = u_color;"
// + "}"; // + "}";
final static String lineFragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n"
+ "precision mediump float;\n"
+ "uniform float u_wscale;"
+ "uniform float u_width;"
+ "uniform vec4 u_color;"
+ "varying vec2 v_st;"
+ "const float zero = 0.0;"
+ "void main() {"
+ " vec4 color = u_color;"
+ " float width = u_width;"
+ " float len;"
+ " if (v_st.t == zero)"
+ " len = abs(v_st.s);"
+ " else "
+ " len = length(v_st);"
+ " vec2 st_width = fwidth(v_st);"
+ " float fuzz = max(st_width.s, st_width.t) * 1.5;"
+ " color *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
+ " gl_FragColor = color;"
+ "}";
final static String polygonVertexShader = "" final static String polygonVertexShader = ""
+ "precision mediump float;" + "precision mediump float;"
+ "uniform mat4 mvp;" // + "invariant gl_Position;"
+ "uniform mat4 u_mvp;"
+ "uniform float u_offset;"
+ "attribute vec4 a_position;" + "attribute vec4 a_position;"
+ "void main() {" + "void main() {"
+ " gl_Position = mvp * a_position;" + " vec4 pos = u_mvp * a_position;"
+ " pos.z = 0.0;"
+ " gl_Position = pos;"
// + " gl_Position = mvp * a_position;"
+ "}"; + "}";
final static String polygonFragmentShader = "" final static String polygonFragmentShader = ""
@ -116,15 +128,40 @@ class Shaders {
+ "varying vec2 tex_c;" + "varying vec2 tex_c;"
+ "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);" + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
+ "void main() {" + "void main() {"
+ " vec4 pos;"
+ " if (mod(vertex.x, 2.0) == 0.0){" + " if (mod(vertex.x, 2.0) == 0.0){"
+ " gl_Position = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);" + " pos = rotation * (mvp * vec4(vertex.xy + vertex.zw, 0.0, 1.0));"
+ " } else {" + " } else {"
+ " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);" + " vec4 dir = mvp * vec4(vertex.xy, 0.0, 1.0);"
+ " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);" + " pos = rotation * (dir + vec4(vertex.zw * scale, 0.0, 0.0));"
+ " }" + " }"
+ " pos.z = 0.0;"
+ " gl_Position = pos;"
+ " tex_c = tex_coord * div;" + " tex_c = tex_coord * div;"
+ "}"; + "}";
// final static String textVertexShader = ""
// + "precision highp float; "
// + "attribute vec4 vertex;"
// + "attribute vec2 tex_coord;"
// + "uniform mat4 mvp;"
// + "uniform mat4 rotation;"
// + "uniform float scale;"
// + "varying vec2 tex_c;"
// + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
// + "void main() {"
// + " vec4 pos;"
// + " if (mod(vertex.x, 2.0) == 0.0){"
// + " pos = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
// + " } else {"
// + " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
// + " pos = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
// + " }"
// + " pos.z = 0.0;"
// + " gl_Position = pos;"
// + " tex_c = tex_coord * div;"
// + "}";
// final static String textVertexShader = "" // final static String textVertexShader = ""
// + "precision highp float; " // + "precision highp float; "
// + "attribute vec4 vertex;" // + "attribute vec4 vertex;"

View File

@ -79,7 +79,20 @@ public class TextRenderer {
}; };
static boolean init(int numTextures) { static void init() {
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
Shaders.textFragmentShader);
hTextUVPMatrix = GLES20.glGetUniformLocation(mTextProgram, "mvp");
hTextRotationMatrix = GLES20.glGetUniformLocation(mTextProgram, "rotation");
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
}
static boolean setup(int numTextures) {
int bufferSize = numTextures int bufferSize = numTextures
* MAX_LABELS * VERTICES_PER_SPRITE * MAX_LABELS * VERTICES_PER_SPRITE
* SHORTS_PER_VERTICE * (Short.SIZE / 8); * SHORTS_PER_VERTICE * (Short.SIZE / 8);
@ -98,16 +111,6 @@ public class TextRenderer {
mShortBuffer = buf.asShortBuffer(); mShortBuffer = buf.asShortBuffer();
// } // }
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
Shaders.textFragmentShader);
hTextUVPMatrix = GLES20.glGetUniformLocation(mTextProgram, "mvp");
hTextRotationMatrix = GLES20.glGetUniformLocation(mTextProgram, "rotation");
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
int[] textureIds = new int[numTextures]; int[] textureIds = new int[numTextures];
TextTexture[] textures = new TextTexture[numTextures]; TextTexture[] textures = new TextTexture[numTextures];
GLES20.glGenTextures(numTextures, textureIds, 0); GLES20.glGenTextures(numTextures, textureIds, 0);