This commit is contained in:
Hannes Janetzek 2013-06-17 02:16:25 +02:00
parent 176f84ff95
commit 8dcb83ee8f

View File

@ -30,15 +30,13 @@ import org.oscim.view.MapView;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.util.Log; import android.util.Log;
/**
* @author Hannes Janetzek
*/
public class ExtrusionRenderLayer extends RenderLayer { public class ExtrusionRenderLayer extends RenderLayer {
private final static String TAG = ExtrusionRenderLayer.class.getName(); private final static String TAG = ExtrusionRenderLayer.class.getName();
private final TileRenderLayer mTileLayer; private final TileRenderLayer mTileLayer;
public ExtrusionRenderLayer(MapView mapView, org.oscim.layers.tile.TileRenderLayer tileRenderLayer) { public ExtrusionRenderLayer(MapView mapView,
org.oscim.layers.tile.TileRenderLayer tileRenderLayer) {
super(mapView); super(mapView);
mTileLayer = tileRenderLayer; mTileLayer = tileRenderLayer;
mTileSet = new TileSet(); mTileSet = new TileSet();
@ -54,29 +52,29 @@ public class ExtrusionRenderLayer extends RenderLayer {
private boolean initialized = false; private boolean initialized = false;
// FIXME sum up size used while filling layer only up to:
//public int mBufferSize = 65536;
private final TileSet mTileSet; private final TileSet mTileSet;
private MapTile[] mTiles; private MapTile[] mTiles;
private int mTileCnt; private int mTileCnt;
@Override private final static int SHADER = 0;
public void update(MapPosition pos, boolean changed, Matrices matrices) {
mMapView.getMapViewPosition().getMapPosition(mMapPosition); private boolean initShader() {
if (!initialized) {
initialized = true; initialized = true;
for (int i = 1; i < 2; i++) { for (int i = 0; i <= SHADER; i++) {
// Set up the program for rendering extrusions if (i == 0) {
shaderProgram[i] = GlUtils.createProgram(extrusionVertexShader, shaderProgram[i] = GlUtils.createProgram(extrusionVertexShader,
extrusionFragmentShader); extrusionFragmentShader);
} else {
shaderProgram[i] = GlUtils.createProgram(extrusionVertexShader,
extrusionFragmentShaderZ);
}
if (shaderProgram[i] == 0) { if (shaderProgram[i] == 0) {
Log.e(TAG, "Could not create extrusion shader program. " + i); Log.e(TAG, "Could not create extrusion shader program. " + i);
return; return false;
} }
hMatrix[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_mvp"); hMatrix[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_mvp");
hColor[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_color"); hColor[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_color");
hAlpha[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_alpha"); hAlpha[i] = GLES20.glGetUniformLocation(shaderProgram[i], "u_alpha");
@ -84,14 +82,27 @@ public class ExtrusionRenderLayer extends RenderLayer {
hVertexPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_pos"); hVertexPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_pos");
hLightPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_light"); hLightPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_light");
} }
return true;
} }
@Override
public void update(MapPosition pos, boolean changed, Matrices matrices) {
mMapView.getMapViewPosition().getMapPosition(mMapPosition);
if (!initialized && !initShader())
return;
if (shaderProgram[0] == 0)
return;
if (mAlpha == 0 || pos.zoomLevel < 16) { if (mAlpha == 0 || pos.zoomLevel < 16) {
isReady = false; isReady = false;
return; return;
} }
int ready = 0; int activeTiles = 0;
mTileLayer.getVisibleTiles(mTileSet); mTileLayer.getVisibleTiles(mTileSet);
MapTile[] tiles = mTileSet.tiles; MapTile[] tiles = mTileSet.tiles;
@ -107,36 +118,35 @@ public class ExtrusionRenderLayer extends RenderLayer {
continue; continue;
if (!el.compiled) { if (!el.compiled) {
// FIXME check 'bytes'? int verticesBytes = el.mNumVertices * 8;
int verticesBytes = el.mNumVertices * 8 * 2;
el.compile(GLRenderer.getShortBuffer(verticesBytes)); el.compile(GLRenderer.getShortBuffer(verticesBytes));
GlUtils.checkGlError("..."); GlUtils.checkGlError("...");
} }
if (el.compiled) if (el.compiled)
mTiles[ready++] = tiles[i]; mTiles[activeTiles++] = tiles[i];
} }
} else if (pos.zoomLevel == 16) { } else if (pos.zoomLevel == 16) {
// check if proxy children are ready // check if proxy children are ready
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
for (byte j = 0; j < 4; j++) { for (byte j = 0; j < 4; j++) {
if ((t.proxies & (1 << j)) != 0) { if ((t.proxies & (1 << j)) == 0)
continue;
MapTile c = t.rel.get(j); MapTile c = t.rel.get(j);
el = getLayer(c); el = getLayer(c);
if (el == null || !el.compiled) if (el == null || !el.compiled)
continue; continue;
mTiles[ready++] = c; mTiles[activeTiles++] = c;
}
} }
} }
} }
mTileCnt = ready; mTileCnt = activeTiles;
isReady = ready > 0; isReady = activeTiles > 0;
if (!isReady) if (!isReady)
mTileLayer.releaseTiles(mTileSet); mTileLayer.releaseTiles(mTileSet);
@ -161,22 +171,19 @@ public class ExtrusionRenderLayer extends RenderLayer {
@Override @Override
public void render(MapPosition pos, Matrices m) { public void render(MapPosition pos, Matrices m) {
// TODO one could render in one pass to texture and then draw the texture // TODO one could render in one pass to texture and then draw the texture
// with alpha... might be faster. // with alpha... might be faster and would allow postprocessing outlines.
MapTile[] tiles = mTiles; MapTile[] tiles = mTiles;
//float div = FastMath.pow(tiles[0].zoomLevel - pos.zoomLevel); int uExtAlpha = hAlpha[SHADER];
int uExtColor = hColor[SHADER];
int shaderMode = 1; int uExtVertexPosition = hVertexPosition[SHADER];
int uExtAlpha = hAlpha[shaderMode]; int uExtLightPosition = hLightPosition[SHADER];
int uExtColor = hColor[shaderMode]; int uExtMatrix = hMatrix[SHADER];
int uExtVertexPosition = hVertexPosition[shaderMode]; int uExtMode = hMode[SHADER];
int uExtLightPosition = hLightPosition[shaderMode];
int uExtMatrix = hMatrix[shaderMode];
int uExtMode = hMode[shaderMode];
if (debug) { if (debug) {
GLState.useProgram(shaderProgram[shaderMode]); GLState.useProgram(shaderProgram[SHADER]);
GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition); GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition);
GLES20.glUniform1i(uExtMode, 0); GLES20.glUniform1i(uExtMode, 0);
@ -220,7 +227,7 @@ public class ExtrusionRenderLayer extends RenderLayer {
GLState.test(true, false); GLState.test(true, false);
GLState.useProgram(shaderProgram[shaderMode]); GLState.useProgram(shaderProgram[SHADER]);
GLState.enableVertexArrays(uExtVertexPosition, -1); GLState.enableVertexArrays(uExtVertexPosition, -1);
if (pos.scale < (1 << 18)) { if (pos.scale < (1 << 18)) {
// chances are high that one moves through a building // chances are high that one moves through a building
@ -335,7 +342,7 @@ public class ExtrusionRenderLayer extends RenderLayer {
m.mvp.addDepthOffset(delta); m.mvp.addDepthOffset(delta);
} }
private final float _a = 0.86f; private final float _a = 0.88f;
private final float _r = 0xe9; private final float _r = 0xe9;
private final float _g = 0xe8; private final float _g = 0xe8;
private final float _b = 0xe6; private final float _b = 0xe6;
@ -375,12 +382,12 @@ public class ExtrusionRenderLayer extends RenderLayer {
+ "attribute vec4 a_pos;" + "attribute vec4 a_pos;"
+ "attribute vec2 a_light;" + "attribute vec2 a_light;"
+ "varying vec4 color;" + "varying vec4 color;"
//+ "varying float z;" + "varying float depth;"
+ "const float ff = 255.0;" + "const float ff = 255.0;"
+ "void main() {" + "void main() {"
// change height by u_alpha // change height by u_alpha
+ " gl_Position = u_mvp * vec4(a_pos.xy, a_pos.z * u_alpha, 1.0);" + " gl_Position = u_mvp * vec4(a_pos.xy, a_pos.z * u_alpha, 1.0);"
//+ " z = gl_Position.z;" //+ " depth = gl_Position.z;"
+ " if (u_mode == 0)" + " if (u_mode == 0)"
// roof / depth pass // roof / depth pass
+ " color = u_color[0] * u_alpha;" + " color = u_color[0] * u_alpha;"
@ -392,14 +399,14 @@ public class ExtrusionRenderLayer extends RenderLayer {
+ " float dir = a_light.y / ff;" + " float dir = a_light.y / ff;"
+ " float z = (0.98 + gl_Position.z * 0.02);" + " float z = (0.98 + gl_Position.z * 0.02);"
+ " color = u_color[1];" + " color = u_color[1];"
+ " color.rgb *= (0.85 + dir * 0.15) * z;" + " color.rgb *= (0.8 + dir * 0.2) * z;"
+ " color *= u_alpha;" + " color *= u_alpha;"
+ " } else if (u_mode == 2){" + " } else if (u_mode == 2){"
// sides 2 - use 0x00ff // sides 2 - use 0x00ff
+ " float dir = a_light.x / ff;" + " float dir = a_light.x / ff;"
+ " float z = (0.98 + gl_Position.z * 0.02);" + " float z = (0.98 + gl_Position.z * 0.02);"
+ " color = u_color[2];" + " color = u_color[2];"
+ " color.rgb *= (0.85 + dir * 0.15) * z;" + " color.rgb *= (0.8 + dir * 0.2) * z;"
+ " color *= u_alpha;" + " color *= u_alpha;"
+ " } else {" + " } else {"
// outline // outline
@ -415,14 +422,13 @@ public class ExtrusionRenderLayer extends RenderLayer {
+ "}"; + "}";
final static String extrusionFragmentShaderZ = "" final static String extrusionFragmentShaderZ = ""
+ "precision highp float;" + "precision mediump float;"
+ "uniform vec4 u_color;" + "varying float depth;"
+ "varying float z;"
+ "void main() {" + "void main() {"
+ "if (z < 0.0)" + "float d = depth * 0.2;"
+ " gl_FragColor = vec4(z * -1.0, 0.0, 0.0, 1.0);" + "if (d < 0.0)"
+ "else" + " d = -d;"
+ " gl_FragColor = vec4(0.0, 0.0, z, 1.0);" + " gl_FragColor = vec4(1.0 - d, 1.0 - d, 1.0 - d, 1.0 - d);"
+ "}"; + "}";
public void setAlpha(float a) { public void setAlpha(float a) {