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

View File

@ -34,6 +34,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
@ -48,7 +49,6 @@ import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.util.FloatMath;
import android.util.Log;
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 SHORT_BYTES = 2;
static final float COORD_MULTIPLIER = 8.0f;
private static final int CACHE_TILES_MAX = 200;
private static final int CACHE_TILES_MAX = 250;
private static final int LIMIT_BUFFERS = 16 * MB;
static final float COORD_MULTIPLIER = 8.0f;
static int CACHE_TILES = CACHE_TILES_MAX;
private final MapView mMapView;
@ -100,7 +100,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static boolean mUpdateColor = false;
// 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
static class TilesData {
@ -145,7 +145,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
* @return curTiles (the previously active tiles)
*/
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
synchronized (GLRenderer.lock) {
GLRenderer.tilelock.lock();
mCurPosition = mapPosition;
@ -193,9 +193,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mUpdateTiles = true;
GLRenderer.tilelock.unlock();
return tmp;
}
}
/**
* called by TileLoader. when tile is removed from cache, reuse its vbo.
@ -236,8 +237,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static boolean mRotate = false;
private static void setMatrix(MapPosition mapPosition, MapTile tile, float div,
int offset) {
private static void setMatrix(float[] matrix, MapPosition mapPosition, MapTile tile,
float div, int offset, boolean project) {
float x, y, scale;
if (mRotate) {
@ -245,31 +246,47 @@ public class GLRenderer implements GLSurfaceView.Renderer {
x = (float) (tile.pixelX - mapPosition.x * 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);
Matrix.translateM(mMVPMatrix, 0,
// translate to center
Matrix.translateM(matrix, 0,
x * 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 {
scale = (float) (2.0 * mapPosition.scale / (mHeight * div));
x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mapPosition.y * div);
mMVPMatrix[12] = x * scale * mAspect;
mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
matrix[12] = x * scale * mAspect;
matrix[13] = -(y + Tile.TILE_SIZE) * scale;
// increase the 'distance' with each tile drawn.
mMVPMatrix[14] = -0.99f + offset * 0.01f; // depthStep; // 0.01f;
mMVPMatrix[0] = scale * mAspect / COORD_MULTIPLIER;
mMVPMatrix[5] = scale / COORD_MULTIPLIER;
matrix[14] = -0.99f + offset * 0.01f;
matrix[0] = scale * mAspect / COORD_MULTIPLIER;
matrix[5] = scale / COORD_MULTIPLIER;
}
}
@ -468,15 +485,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (MapView.debugFrameTime)
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);
// Note: having the impression it is faster to also clear the
@ -485,10 +493,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// memory region afaik
glClear(GLES20.GL_COLOR_BUFFER_BIT
| GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_STENCIL_BUFFER_BIT);
// | GLES20.GL_STENCIL_BUFFER_BIT
);
// get position and current tiles to draw
synchronized (GLRenderer.lock) {
GLRenderer.tilelock.lock();
mapPosition = mCurPosition;
if (mUpdateTiles) {
@ -497,11 +506,28 @@ public class GLRenderer implements GLSurfaceView.Renderer {
curTiles = tmp;
mUpdateTiles = false;
}
}
GLRenderer.tilelock.unlock();
if (drawTiles == null)
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;
MapTile[] tiles = drawTiles.tiles;
@ -547,15 +573,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (updateTextures > 0)
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_POLYGON_OFFSET_FILL);
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && tiles[i].isReady) {
drawTile(mapPosition, tiles[i], 1);
@ -571,7 +590,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
// GlUtils.checkGlError("end draw");
glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
mDrawCount = 0;
mDrawSerial++;
@ -585,20 +605,25 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (scale < 1)
scale = 1;
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix);
else
TextRenderer.beginDraw(s, mRotTMatrix);
// if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
// TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix);
// else
// TextRenderer.beginDraw(s, mRotTMatrix);
s = (float) (1.0 / mHeight) / COORD_MULTIPLIER;
TextRenderer.beginDraw(s, mProjMatrix);
for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null)
continue;
setMatrix(mapPosition, tiles[i], 1, 0);
setMatrix(mMVPMatrix, mapPosition, tiles[i], 1, 0, false);
TextRenderer.drawTile(tiles[i], mMVPMatrix);
}
TextRenderer.endDraw();
// TODO call overlay renderer
if (MapView.debugFrameTime) {
GLES20.glFinish();
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
@ -617,10 +642,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
int z = mapPosition.zoomLevel;
float s = mapPosition.scale;
// mDrawCount is used to calculation z offset.
// (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);
@ -642,20 +670,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (pl != null && pnext < lnext) {
glDisable(GL_BLEND);
pl = PolygonRenderer.drawPolygons(pl, lnext, mMVPMatrix, z, s, !clipped);
pl = PolygonRenderer.drawPolygons(pl, lnext, mMVPMatrix, offset, z, s,
!clipped);
clipped = true;
} else {
// XXX nasty
if (!clipped) {
PolygonRenderer.drawPolygons(null, 0, mMVPMatrix, z, s, true);
PolygonRenderer.drawPolygons(null, 0, mMVPMatrix, offset, z, s, true);
clipped = true;
}
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) {
Log.d(TAG, "SurfaceChanged:" + width + " " + height);
mWidth = width;
mHeight = height;
if (width <= 0 || height <= 0)
return;
@ -735,13 +762,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (mWidth == width || mHeight == height)
changed = false;
mWidth = width;
mHeight = height;
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,
// 1, 100);
Matrix.frustumM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
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);
if (!changed && !mNewSurface) {
@ -749,6 +784,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return;
}
mNewSurface = false;
mBufferMemoryUsage = 0;
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
@ -766,7 +803,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mVBOs.add(new VertexBufferObject(mVboIds[i]));
// Set up textures
TextRenderer.init(numTiles);
TextRenderer.setup(numTiles);
if (mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1],
@ -775,18 +812,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
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");
glClear(GL_STENCIL_BUFFER_BIT);
mMapView.redrawMap();
}
@ -808,8 +837,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
shortBuffer = new ShortBuffer[rotateBuffers];
// add half pixel to tile clip/fill coordinates
// to avoid rounding issues
// add half pixel to tile clip/fill coordinates to avoid rounding issues
short min = -4;
short max = (short) ((Tile.TILE_SIZE << 3) + 4);
mFillCoords = new short[8];
@ -824,7 +852,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
LineRenderer.init();
PolygonRenderer.init();
TextRenderer.init();
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;

View File

@ -14,16 +14,6 @@
*/
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 org.oscim.theme.renderinstruction.Line;
@ -46,6 +36,7 @@ class LineRenderer {
private static int hLineMatrix;
private static int hLineScale;
private static int hLineWidth;
private static int hLineOffset;
static boolean init() {
lineProgram = GlUtils.createProgram(Shaders.lineVertexShader,
@ -55,38 +46,41 @@ class LineRenderer {
return false;
}
hLineMatrix = glGetUniformLocation(lineProgram, "mvp");
hLineScale = glGetUniformLocation(lineProgram, "u_wscale");
hLineWidth = glGetUniformLocation(lineProgram, "u_width");
hLineColor = glGetUniformLocation(lineProgram, "u_color");
hLineMatrix = GLES20.glGetUniformLocation(lineProgram, "u_mvp");
hLineScale = GLES20.glGetUniformLocation(lineProgram, "u_wscale");
hLineWidth = GLES20.glGetUniformLocation(lineProgram, "u_width");
hLineColor = GLES20.glGetUniformLocation(lineProgram, "u_color");
hLineOffset = GLES20.glGetUniformLocation(lineProgram, "u_offset");
hLineVertexPosition = GLES20.glGetAttribLocation(lineProgram, "a_position");
hLineTexturePosition = glGetAttribLocation(lineProgram, "a_st");
hLineTexturePosition = GLES20.glGetAttribLocation(lineProgram, "a_st");
return true;
}
static final boolean mFast = true;
static final boolean mFast = false;
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;
if (layer == null)
return null;
glUseProgram(lineProgram);
GLES20.glUseProgram(lineProgram);
glEnableVertexAttribArray(hLineVertexPosition);
glEnableVertexAttribArray(hLineTexturePosition);
GLES20.glEnableVertexAttribArray(hLineVertexPosition);
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);
glVertexAttribPointer(hLineTexturePosition, 2, GLES20.GL_SHORT,
GLES20.glVertexAttribPointer(hLineTexturePosition, 2, GLES20.GL_SHORT,
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:
float pixel = 2.0f / (scale * z);
@ -137,7 +131,7 @@ class LineRenderer {
GLES20.glUniform1f(hLineWidth, l.width / (scale * z)
+ o.width / s);
glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
}
}
else {
@ -153,12 +147,12 @@ class LineRenderer {
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);
glDisableVertexAttribArray(hLineTexturePosition);
GLES20.glDisableVertexAttribArray(hLineVertexPosition);
GLES20.glDisableVertexAttribArray(hLineTexturePosition);
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
* JobQueue (mapView.addJobs) for loading by MapGenerator class
* JobQueue (mapView.addJobs) for loading by TileGenerator class
*
* @param clear
* ...
@ -116,7 +116,8 @@ public class MapRenderer extends GLSurfaceView {
Log.d(TAG, "CLEAR");
mInitial = true;
synchronized (GLRenderer.lock) {
// FIXME still needed?
GLRenderer.tilelock.lock();
for (MapTile t : mTiles)
clearTile(t);
@ -124,7 +125,7 @@ public class MapRenderer extends GLSurfaceView {
mTiles.clear();
mTilesLoaded.clear();
QuadTree.init();
}
GLRenderer.tilelock.unlock();
}
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
* ...

View File

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

View File

@ -19,17 +19,23 @@ class Shaders {
final static String lineVertexShader = ""
+ "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_st;"
+ "varying vec2 v_st;"
+ "uniform float u_width;"
+ "const float dscale = 8.0/2048.0;"
+ "void main() {"
// scale extrusion to u_width pixel
// just ignore the two most insignificant bits of 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
+ " v_st = u_width * (abs(mod(a_st,4.0)) - 1.0);"
// TODO use bit operations when available (gles 1.3)
@ -50,53 +56,59 @@ class Shaders {
// + " 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 = ""
// + "#extension GL_OES_standard_derivatives : enable\n"
// + "precision mediump float;\n"
// + "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() {"
// + " 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.a *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
// + " gl_FragColor = color;"
// // 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;"
// // + " 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 = ""
+ "precision mediump float;"
+ "uniform mat4 mvp;"
// + "invariant gl_Position;"
+ "uniform mat4 u_mvp;"
+ "uniform float u_offset;"
+ "attribute vec4 a_position;"
+ "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 = ""
@ -116,15 +128,40 @@ class Shaders {
+ "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){"
+ " 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 {"
+ " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
+ " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
+ " vec4 dir = mvp * vec4(vertex.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;"
+ "}";
// 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 = ""
// + "precision highp float; "
// + "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
* MAX_LABELS * VERTICES_PER_SPRITE
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
@ -98,16 +111,6 @@ public class TextRenderer {
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];
TextTexture[] textures = new TextTexture[numTextures];
GLES20.glGenTextures(numTextures, textureIds, 0);