Merge branch 'extract_shaders'

This commit is contained in:
Hannes Janetzek 2014-03-27 03:12:45 +01:00
commit ff56d5c67a
28 changed files with 1004 additions and 784 deletions

1
.gitignore vendored
View File

@ -16,6 +16,7 @@ build/
/vtm-android-example/assets/
/vtm-gdx-desktop/assets/
/vtm-gdx-html/war/
/vtm-gdx-html/assets/
/vtm-gdx-html/gwt-unitCache
/vtm-spatialite/
/vtm-spatialite-android/

View File

@ -43,6 +43,11 @@ gwt {
superDev {
noPrecompile=true
}
compiler {
enableClosureCompiler = false; // activates -XenableClosureCompiler
disableClassMetadata = true; // activates -XdisableClassMetadata
disableCastChecking = true; // activates -XdisableCastChecking
}
src += files(sourceSets.main.java.srcDirs)
src += files(project(':vtm').sourceSets.main.allJava.srcDirs)
@ -58,6 +63,23 @@ task jettyDraftWar(type: JettyRunWar) {
webApp=draftWar.archivePath
}
task copyThemeAssets(type: Copy) {
from "$rootDir/vtm-themes/resources/assets"
into "assets"
include '**/*'
}
task copyVtmAssets(type: Copy) {
from "$rootDir/vtm/resources/assets"
into "assets"
include '**/*'
}
tasks.withType(JavaCompile) { compileTask ->
compileTask.dependsOn copyThemeAssets
compileTask.dependsOn copyVtmAssets
}
// Configuring Eclipse classpath
eclipse.classpath {

View File

@ -21,7 +21,7 @@
<super-source path="emu" />
<set-configuration-property name="gdx.assetpath" value="../vtm-themes/resources/assets" />
<set-configuration-property name="gdx.assetpath" value="./assets" />
<!-- for gradle build, commend out for eclipse build/devmode -->
<set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" />

View File

@ -16,6 +16,8 @@
*/
package org.oscim.gdx.client;
import java.util.HashMap;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
@ -23,9 +25,14 @@ import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection;
import org.oscim.gdx.GdxMap;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.renderer.MapRenderer;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.TileSource;
import org.oscim.tiling.source.bitmap.DefaultSources.NaturalEarth;
import org.oscim.tiling.source.bitmap.BitmapTileSource;
import org.oscim.tiling.source.bitmap.DefaultSources;
import org.oscim.tiling.source.bitmap.DefaultSources.StamenToner;
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -66,14 +73,20 @@ class GwtGdxMap extends GdxMap {
float tilt = 0;
float rotation = 0;
String themeName = null;
String mapName = null;
final HashMap<String, String> params = new HashMap<String, String>();
String addOpts = "";
if (Window.Location.getHash() != null) {
String hash = Window.Location.getHash();
hash = hash.substring(1);
String[] pairs = hash.split(",");
String[] urlParams = null;
urlParams = hash.split("&");
if (urlParams.length == 1)
urlParams = hash.split(",");
for (String p : pairs) {
for (String p : urlParams) {
try {
if (p.startsWith("lat="))
lat = Double.parseDouble(p.substring(4));
@ -85,33 +98,82 @@ class GwtGdxMap extends GdxMap {
rotation = Float.parseFloat(p.substring(4));
else if (p.startsWith("tilt="))
tilt = Float.parseFloat(p.substring(5));
else if (p.startsWith("theme="))
themeName = p.substring(6);
else if (p.startsWith("map="))
mapName = p.substring(4);
else {
String[] opt = p.split("=");
if (opt.length > 1)
params.put(opt[0], opt[1]);
else
params.put(opt[0], null);
addOpts += p + "&";
}
} catch (NumberFormatException e) {
}
}
}
final String addParam =
(themeName == null ? "" : ("theme=" + themeName + "&"))
+ (mapName == null ? "" : ("map=" + mapName + "&"))
+ addOpts;
MapPosition p = new MapPosition();
p.setZoomLevel(zoom);
p.setPosition(lat, lon);
log.debug("map position: " + p.x + "/" + p.y + " " + lat + "/" + lon);
p.bearing = rotation;
p.tilt = tilt;
mMap.setMapPosition(p);
//mMap.getViewport().setTilt(tilt);
//mMap.getViewport().setRotation(rotation);
VectorTileLayer l = null;
if (c.getBackgroundLayer() != null || mapName != null) {
BitmapTileSource ts;
if ("toner".equals(mapName))
ts = new StamenToner();
else if ("osm".equals(mapName))
ts = new DefaultSources.OpenStreetMap();
else if ("watercolor".equals(mapName))
ts = new DefaultSources.StamenWatercolor();
else if ("arcgis-shaded".equals(mapName))
ts = new DefaultSources.ArcGISWorldShaded();
else if ("imagico".equals(mapName))
ts = new DefaultSources.ImagicoLandcover();
else
ts = new StamenToner();
mMap.setBackgroundMap(new BitmapTileLayer(mMap, ts));
} else {
String url = c.getTileUrl();
String sourceName = c.getTileSource();
TileSource tileSource;
tileSource = new OSciMap4TileSource(url);
TileSource ts = new OSciMap4TileSource(url);
l = mMap.setBaseMap(ts);
initDefaultLayers(tileSource, false, true, true);
if (themeName == null) {
mMap.setTheme(VtmThemes.DEFAULT);
} else {
if ("osmarender".equals(themeName))
mMap.setTheme(VtmThemes.OSMARENDER);
else if ("tron".equals(themeName))
mMap.setTheme(VtmThemes.TRONRENDER);
else if ("newtron".equals(themeName))
mMap.setTheme(VtmThemes.NEWTRON);
else
mMap.setTheme(VtmThemes.DEFAULT);
}
}
if ("naturalearth".equals(c.getBackgroundLayer()))
mMap.setBackgroundMap(new BitmapTileLayer(mMap, new NaturalEarth()));
if (l != null) {
if (!params.containsKey("nolabel"))
mMap.layers().add(new LabelLayer(mMap, l));
}
mSearchBox = new SearchBox(mMap);
@ -139,9 +201,12 @@ class GwtGdxMap extends GdxMap {
String newURL = Window.Location
.createUrlBuilder()
.setHash("scale=" + pos.zoomLevel + ",rot=" + curRot
+ ",tilt=" + curTilt + ",lat=" + (curLat / 1000f)
+ ",lon=" + (curLon / 1000f))
.setHash(addParam
+ "scale=" + pos.zoomLevel
+ "&rot=" + curRot
+ "&tilt=" + curTilt
+ "&lat=" + (curLat / 1000f)
+ "&lon=" + (curLon / 1000f))
.buildString();
Window.Location.replace(newURL);
}

View File

@ -73,7 +73,13 @@ public class GwtGraphics implements Graphics {
context.viewport(0, 0, config.width, config.height);
// this actually *enables* the option to use std derivatives in shader..
context.getExtension("OES_standard_derivatives");
if (context.getExtension("OES_standard_derivatives") == null) {
}
if (context.getExtension("WEBKIT_WEBGL_depth_texture") == null) {
}
this.gl = config.useDebugGL ? new GwtGL20Debug(context) : new GwtGLAdapter(context);
canvas.setId("gdx-canvas");

View File

@ -35,6 +35,7 @@ public class GdxAssetAdapter extends AssetAdapter {
try {
return file.read();
} catch (GdxRuntimeException e) {
e.printStackTrace();
return null;
}
}

View File

@ -0,0 +1,17 @@
#ifdef GLES
precision mediump float;
#endif
uniform mat4 u_mvp;
attribute vec4 a_pos;
void main() {
gl_Position = u_mvp * a_pos;
}
$$
#ifdef GLES
precision mediump float;
#endif
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}

View File

@ -0,0 +1,59 @@
uniform mat4 u_mvp;
uniform vec4 u_color[4];
uniform int u_mode;
uniform float u_alpha;
attribute vec4 a_pos;
attribute vec2 a_light;
varying vec4 color;
varying float depth;
const float ff = 255.0;
void
main(){
// change height by u_alpha
gl_Position = u_mvp * vec4(a_pos.xy, a_pos.z * u_alpha, 1.0);
// depth = gl_Position.z;
if (u_mode == -1) {
;
// roof / depth pass
// color = u_color[0] * u_alpha;
}
else if (u_mode == 0) {
// roof / depth pass
color = u_color[0] * u_alpha;
}
else if (u_mode == 1) {
// sides 1 - use 0xff00
// scale direction to -0.5<>0.5
float dir = a_light.y / ff;
float z = (0.98 + gl_Position.z * 0.02);
float h = 0.9 + clamp(a_pos.z / 2000.0, 0.0, 0.1);
color = u_color[1];
color.rgb *= (0.8 + dir * 0.2) * z * h;
color *= u_alpha;
}
else if (u_mode == 2) {
// sides 2 - use 0x00ff
float dir = a_light.x / ff;
float z = (0.98 + gl_Position.z * 0.02);
float h = 0.9 + clamp(a_pos.z / 2000.0, 0.0, 0.1);
color = u_color[2];
color.rgb *= (0.8 + dir * 0.2) * z * h;
color *= u_alpha;
}
else if (u_mode == 3) {
// outline
float z = (0.98 - gl_Position.z * 0.02);
color = u_color[3] * z;
}
}
$$
#ifdef GLES
precision mediump float;
#endif
varying vec4 color;
void
main(){
gl_FragColor = color;
}

View File

@ -0,0 +1,50 @@
uniform mat4 u_mvp;
uniform vec4 u_color;
uniform float u_alpha;
attribute vec4 a_pos;
attribute vec2 a_light;
varying vec4 color;
varying float depth;
const float alpha = 1.0;
void
main(){
// change height by u_alpha
vec4 pos = a_pos;
pos.z *= u_alpha;
gl_Position = u_mvp * pos;
// normalize face x/y direction
vec2 enc = (a_light / 255.0);
vec2 fenc = enc * 4.0 - 2.0;
float f = dot(fenc, fenc);
float g = sqrt(1.0 - f / 4.0);
vec3 r_norm;
r_norm.xy = fenc * g;
r_norm.z = 1.0 - f / 2.0;
// normal points up or down (1,-1)
//// float dir = 1.0 - (2.0 * abs(mod(a_light.x,2.0)));
// recreate face normal vector
/// vec3 r_norm = vec3(n.xy, dir * (1.0 - length(n.xy)));
vec3 light_dir = normalize(vec3(0.2, 0.2, 1.0));
float l = dot(r_norm, light_dir) * 0.8;
light_dir = normalize(vec3(-0.2, -0.2, 1.0));
l += dot(r_norm, light_dir) * 0.2;
// l = (l + (1.0 - r_norm.z))*0.5;
l = 0.4 + l * 0.6;
// extreme fake-ssao by height
l += (clamp(a_pos.z / 2048.0, 0.0, 0.1) - 0.05);
color = vec4(u_color.rgb * (clamp(l, 0.0, 1.0) * alpha), u_color.a * alpha);
}
$$
#ifdef GLES
precision mediump float;
#endif
varying vec4 color;
void
main(){
gl_FragColor = color;
}

View File

@ -0,0 +1,61 @@
#ifdef GLES
precision mediump float;
#endif
uniform mat4 u_mvp;
// uniform mat4 u_vp;
// factor to increase line width relative to scale
uniform float u_width;
// xy hold position, zw extrusion vector
attribute vec4 a_pos;
uniform float u_mode;
uniform float u_height;
varying vec2 v_st;
void
main(){
// scale extrusion to u_width pixel
// just ignore the two most insignificant bits.
vec2 dir = a_pos.zw;
gl_Position = u_mvp * vec4(a_pos.xy + (u_width * dir), u_height, 1.0);
// last two bits hold the texture coordinates.
v_st = abs(mod(dir, 4.0)) - 1.0;
}
$$
#ifdef GLES
precision mediump float;
#endif
uniform sampler2D tex;
uniform float u_fade;
uniform float u_mode;
uniform vec4 u_color;
varying vec2 v_st;
void
main(){
float len;
if (u_mode == 2.0) {
// round cap line
#ifdef DESKTOP_QUIRKS
len = length(v_st);
#else
len = texture2D(tex, v_st).a;
#endif
}
else {
// flat cap line
len = abs(v_st.s);
}
// Antialias line-edges:
// - 'len' is 0 at center of line. -> (1.0 - len) is 0 at the
// edges
// - 'u_fade' is 'pixel' / 'width', i.e. the inverse width of
// the
// line in pixel on screen.
// - 'pixel' is 1.5 / relativeScale
// - '(1.0 - len) / u_fade' interpolates the 'pixel' on
// line-edge
// between 0 and 1 (it is greater 1 for all inner pixel).
gl_FragColor = u_color * clamp((1.0 - len) / u_fade, 0.0, 1.0);
// -> nicer for thin lines
// gl_FragColor = u_color * clamp((1.0 - (len * len)) / u_fade, 0.0, 1.0);
}

View File

@ -0,0 +1,60 @@
#ifndef DESKTOP_QUIRKS
precision mediump float;
#endif
uniform mat4 u_mvp;
// uniform mat4 u_vp;
// factor to increase line width relative to scale
uniform float u_width;
// xy hold position, zw extrusion vector
attribute vec4 a_pos;
uniform float u_mode;
uniform float u_height;
varying vec2 v_st;
void
main(){
// scale extrusion to u_width pixel
// just ignore the two most insignificant bits.
vec2 dir = a_pos.zw;
gl_Position = u_mvp * vec4(a_pos.xy + (u_width * dir), u_height, 1.0);
// last two bits hold the texture coordinates.
v_st = abs(mod(dir, 4.0)) - 1.0;
}
$$
#extension GL_OES_standard_derivatives : enable
#ifndef DESKTOP_QUIRKS
precision mediump float;
#endif
uniform sampler2D tex;
uniform float u_mode;
uniform vec4 u_color;
uniform float u_fade;
varying vec2 v_st;
void
main(){
float len;
float fuzz;
if (u_mode == 2.0) {
/* round cap line */
#ifdef DESKTOP_QUIRKS
len = length(v_st);
#else
len = texture2D(tex, v_st).a;
#endif
vec2 st_width = fwidth(v_st);
fuzz = max(st_width.s, st_width.t);
}
else {
/* flat cap line */
len = abs(v_st.s);
fuzz = fwidth(v_st.s);
}
// u_mode == 0.0 -> thin line
// len = len * clamp(u_mode, len, 1.0);
if (fuzz > 2.0)
gl_FragColor = u_color * 0.5;
else
gl_FragColor = u_color * clamp((1.0 - len) / max(u_fade, fuzz), 0.0, 1.0);
// gl_FragColor = u_color * clamp((1.0 - len), 0.0, 1.0);
}

View File

@ -0,0 +1,53 @@
#ifdef GLES
precision mediump float;
#endif
uniform mat4 u_mvp;
uniform vec4 u_color;
uniform float u_pscale;
uniform float u_width;
attribute vec4 a_pos0;
attribute vec4 a_pos1;
attribute vec2 a_len0;
attribute vec2 a_len1;
attribute float a_flip;
varying vec2 v_st;
void
main(){
vec4 pos;
if (a_flip == 0.0) {
// vec2 dir = u_width * a_pos0.zw;
pos = vec4(a_pos0.xy + (u_width * a_pos0.zw), 0.0, 1.0);
v_st = vec2(a_len0.x / u_pscale, 1.0);
}
else {
// vec2 dir = u_width * a_pos1.zw;
pos = vec4(a_pos1.xy - (u_width * a_pos1.zw), 0.0, 1.0);
v_st = vec2(a_len1.x / u_pscale, -1.0);
}
gl_Position = u_mvp * pos;
}
$$
#extension GL_OES_standard_derivatives : enable
#ifdef GLES
precision mediump float;
#endif
uniform vec4 u_color;
uniform vec4 u_bgcolor;
uniform float u_pwidth;
varying vec2 v_st;
void
main(){
/* distance on perpendicular to the line */
float dist = abs(v_st.t);
float fuzz = fwidth(v_st.t);
float fuzz_p = fwidth(v_st.s);
float line_w = smoothstep(0.0, fuzz, 1.0 - dist);
float stipple_w = smoothstep(0.0, fuzz, u_pwidth - dist);
/* triangle waveform in the range 0..1 for regular pattern */
float phase = abs(mod(v_st.s, 2.0) - 1.0);
/* interpolate between on/off phase, 0.5 = equal phase length */
float stipple_p = smoothstep(0.5 - fuzz_p, 0.5 + fuzz_p, phase);
gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));
}

View File

@ -0,0 +1,21 @@
#ifdef GLES
precision mediump float;
#endif
uniform mat4 u_mvp;
uniform float u_height;
attribute vec2 a_pos;
void
main(){
gl_Position = u_mvp * vec4(a_pos, u_height, 1.0);
}
$$
#ifdef GLES
precision mediump float;
#endif
uniform vec4 u_color;
void
main(){
gl_FragColor = u_color;
}

View File

@ -0,0 +1,22 @@
precision mediump float;
uniform mat4 u_mvp;
uniform vec2 u_scale;
attribute vec4 a_pos;
varying vec2 v_st;
varying vec2 v_st2;
void main() {
v_st = clamp(a_pos.xy, 0.0, 1.0) * (2.0 / u_scale.y);
v_st2 = clamp(a_pos.xy, 0.0, 1.0) * (4.0 / u_scale.y);
gl_Position = u_mvp * a_pos;
}
§
precision mediump float;
uniform vec4 u_color;
uniform sampler2D tex;
uniform vec2 u_scale;
varying vec2 v_st;
varying vec2 v_st2;
void main() {
gl_FragColor = mix(texture2D(tex, v_st), texture2D(tex, v_st2), u_scale.x);
}

View File

@ -0,0 +1,28 @@
#ifdef GLES
precision mediump float;
#endif
uniform mat4 u_mvp;
uniform vec2 u_scale;
attribute vec4 a_pos;
varying vec2 v_st;
varying vec2 v_st2;
void
main(){
v_st = clamp(a_pos.xy, 0.0, 1.0) * (2.0 / u_scale.y);
v_st2 = clamp(a_pos.xy, 0.0, 1.0) * (4.0 / u_scale.y);
gl_Position = u_mvp * a_pos;
}
$$
#ifdef GLES
precision mediump float;
#endif
uniform vec4 u_color;
uniform sampler2D tex;
uniform vec2 u_scale;
varying vec2 v_st;
varying vec2 v_st2;
void
main(){
gl_FragColor = mix(texture2D(tex, v_st), texture2D(tex, v_st2), u_scale.x);
}

View File

@ -0,0 +1,25 @@
#ifdef GLES
precision mediump float;
#endif
attribute vec2 vertex;
attribute vec2 tex_coord;
uniform mat4 u_mvp;
varying vec2 tex_c;
void
main(){
gl_Position = u_mvp * vec4(vertex, 0.0, 1.0);
tex_c = tex_coord;
}
$$
#ifdef GLES
precision mediump float;
#endif
uniform sampler2D tex;
uniform float u_alpha;
varying vec2 tex_c;
void
main(){
gl_FragColor = texture2D(tex, tex_c) * u_alpha;
}

View File

@ -0,0 +1,37 @@
#ifdef GLES
precision highp float;
#endif
attribute vec4 vertex;
attribute vec2 tex_coord;
uniform mat4 u_mv;
uniform mat4 u_proj;
uniform float u_scale;
uniform vec2 u_div;
varying vec2 tex_c;
const float coord_scale = 1.0/8.0;
void
main(){
vec4 pos;
vec2 dir = vertex.zw;
if (mod(vertex.x, 2.0) == 0.0) {
pos = u_proj * (u_mv * vec4(vertex.xy + dir * u_scale, 0.0, 1.0));
}
else { // place as billboard
vec4 center = u_mv * vec4(vertex.xy, 0.0, 1.0);
pos = u_proj * (center + vec4(dir * coord_scale, 0.0, 0.0));
}
gl_Position = pos;
tex_c = tex_coord * u_div;
}
$$
#ifdef GLES
precision highp float;
#endif
uniform sampler2D tex;
varying vec2 tex_c;
void
main(){
gl_FragColor = texture2D(tex, tex_c.xy);
}

View File

@ -16,7 +16,10 @@
*/
package org.oscim.backend;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* The Class AssetAdapter.
@ -33,4 +36,25 @@ public abstract class AssetAdapter {
* @return the input stream
*/
public abstract InputStream openFileAsStream(String name);
public String openTextFile(String name) {
StringBuilder sb = new StringBuilder();
InputStream is = g.openFileAsStream(name);
if (is == null)
return null;
BufferedReader r = new BufferedReader(new InputStreamReader(is));
String line;
try {
while ((line = r.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}

View File

@ -66,10 +66,10 @@ public class ExtrusionRenderer extends LayerRenderer {
for (int i = 0; i <= SHADER; i++) {
if (i == 0) {
shaderProgram[i] = GLUtils.createProgram(extrusionVertexShader,
shaderProgram[i] = GLShader.createProgram(extrusionVertexShader,
extrusionFragmentShader);
} else {
shaderProgram[i] = GLUtils.createProgram(extrusionVertexShader,
shaderProgram[i] = GLShader.createProgram(extrusionVertexShader,
extrusionFragmentShaderZ);
}

View File

@ -0,0 +1,129 @@
package org.oscim.renderer;
import java.nio.IntBuffer;
import org.oscim.backend.AssetAdapter;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class GLShader {
final static Logger log = LoggerFactory.getLogger(GLShader.class);
static GL20 GL;
public int program;
protected boolean create(String vertexSource, String fragmentSource) {
program = createProgram(vertexSource, fragmentSource);
return program != 0;
}
protected boolean create(String fileName) {
program = loadShader(fileName);
return program != 0;
}
protected int getAttrib(String name) {
int loc = GL.glGetAttribLocation(program, name);
if (loc < 0)
log.debug("missing attribute: {}", name);
return loc;
}
protected int getUniform(String name) {
int loc = GL.glGetUniformLocation(program, name);
if (loc < 0)
log.debug("missing uniform: {}", name);
return loc;
}
public boolean useProgram() {
return GLState.useProgram(program);
}
public static int loadShader(String file) {
String path = "shaders/" + file + ".glsl";
String vs = AssetAdapter.g.openTextFile(path);
if (vs == null)
throw new IllegalArgumentException("shader file not found: " + path);
// TODO ...
int fsStart = vs.indexOf('$');
if (fsStart < 0 || vs.charAt(fsStart + 1) != '$')
throw new IllegalArgumentException("not a shader file " + path);
String fs = vs.substring(fsStart + 2);
vs = vs.substring(0, fsStart);
int shader = createProgram(vs, fs);
if (shader == 0) {
System.out.println(vs + " \n\n" + fs);
}
return shader;
}
public static int loadShader(int shaderType, String source) {
int shader = GL.glCreateShader(shaderType);
if (shader != 0) {
GL.glShaderSource(shader, source);
GL.glCompileShader(shader);
IntBuffer compiled = MapRenderer.getIntBuffer(1);
GL.glGetShaderiv(shader, GL20.GL_COMPILE_STATUS, compiled);
compiled.position(0);
if (compiled.get() == 0) {
log.error("Could not compile shader " + shaderType + ":");
log.error(GL.glGetShaderInfoLog(shader));
GL.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
public static int createProgram(String vertexSource, String fragmentSource) {
String defs = "";
if (GLAdapter.GDX_DESKTOP_QUIRKS)
defs += "#define DESKTOP_QUIRKS 1\n";
else
defs += "#define GLES 1\n";
int vertexShader = loadShader(GL20.GL_VERTEX_SHADER, defs + vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GL20.GL_FRAGMENT_SHADER, defs + fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GL.glCreateProgram();
if (program != 0) {
GLUtils.checkGlError("glCreateProgram");
GL.glAttachShader(program, vertexShader);
GLUtils.checkGlError("glAttachShader");
GL.glAttachShader(program, pixelShader);
GLUtils.checkGlError("glAttachShader");
GL.glLinkProgram(program);
IntBuffer linkStatus = MapRenderer.getIntBuffer(1);
GL.glGetProgramiv(program, GL20.GL_LINK_STATUS, linkStatus);
linkStatus.position(0);
if (linkStatus.get() != GL20.GL_TRUE) {
log.error("Could not link program: ");
log.error(GL.glGetProgramInfoLog(program));
GL.glDeleteProgram(program);
program = 0;
}
}
return program;
}
public static class SimpleShader {
}
}

View File

@ -142,88 +142,6 @@ public class GLUtils {
GL20.GL_REPEAT);
}
/**
* @param shaderType
* shader type
* @param source
* shader code
* @return gl identifier
*/
public static int loadShader(int shaderType, String source) {
if (GLAdapter.GDX_DESKTOP_QUIRKS) {
// Strip precision modifer
int start = source.indexOf("precision");
if (start >= 0) {
int end = source.indexOf(';', start) + 1;
if (start > 0)
source = source.substring(0, start) + source.substring(end);
else
source = source.substring(end);
}
}
int shader = GL.glCreateShader(shaderType);
if (shader != 0) {
GL.glShaderSource(shader, source);
GL.glCompileShader(shader);
IntBuffer compiled = MapRenderer.getIntBuffer(1);
GL.glGetShaderiv(shader, GL20.GL_COMPILE_STATUS, compiled);
compiled.position(0);
if (compiled.get() == 0) {
log.error("Could not compile shader " + shaderType + ":");
log.error(GL.glGetShaderInfoLog(shader));
GL.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
/**
* @param vertexSource
* ...
* @param fragmentSource
* ...
* @return gl identifier
*/
public static int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GL20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GL20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GL.glCreateProgram();
if (program != 0) {
checkGlError("glCreateProgram");
GL.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GL.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GL.glLinkProgram(program);
IntBuffer linkStatus = MapRenderer.getIntBuffer(1);
GL.glGetProgramiv(program, GL20.GL_LINK_STATUS, linkStatus);
linkStatus.position(0);
if (linkStatus.get() != GL20.GL_TRUE) {
log.error("Could not link program: ");
log.error(GL.glGetProgramInfoLog(program));
GL.glDeleteProgram(program);
program = 0;
}
}
return program;
}
/**
* @param op
* ...
*/
public static void checkGlError(String op) {
//GL = GLAdapter.get();

View File

@ -324,6 +324,7 @@ public class MapRenderer {
GLState.init(GL);
GLUtils.init(GL);
GLShader.GL = GL;
// Set up some vertex buffer objects
BufferObject.init(GL, 200);

View File

@ -20,8 +20,8 @@ import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
import org.oscim.renderer.MapRenderer;
import org.oscim.renderer.elements.TextureItem.TexturePool;
@ -164,57 +164,50 @@ public class BitmapLayer extends TextureLayer {
//textures = null;
}
static class Shader extends GLShader {
int uMVP, uAlpha, aPos, aTexCoord;
Shader(String shaderFile) {
if (!create(shaderFile))
return;
uMVP = getUniform("u_mvp");
uAlpha = getUniform("u_alpha");
aPos = getAttrib("vertex");
aTexCoord = getAttrib("tex_coord");
}
@Override
public boolean useProgram() {
if (super.useProgram()) {
GLState.enableVertexArrays(aPos, aTexCoord);
return true;
}
return false;
}
}
public static final class Renderer {
private static int mTextureProgram;
private static int hTextureMVMatrix;
private static int hTextureProjMatrix;
private static int hTextureVertex;
private static int hTextureScale;
private static int hTextureScreenScale;
private static int hTextureTexCoord;
private static int hAlpha;
public final static int INDICES_PER_SPRITE = 6;
final static int VERTICES_PER_SPRITE = 4;
final static int SHORTS_PER_VERTICE = 6;
static Shader shader;
static void init() {
mTextureProgram = GLUtils.createProgram(textVertexShader,
textFragmentShader);
hTextureMVMatrix = GL.glGetUniformLocation(mTextureProgram, "u_mv");
hTextureProjMatrix = GL.glGetUniformLocation(mTextureProgram, "u_proj");
hTextureScale = GL.glGetUniformLocation(mTextureProgram, "u_scale");
hTextureScreenScale = GL.glGetUniformLocation(mTextureProgram, "u_swidth");
hTextureVertex = GL.glGetAttribLocation(mTextureProgram, "vertex");
hTextureTexCoord = GL.glGetAttribLocation(mTextureProgram, "tex_coord");
hAlpha = GL.glGetUniformLocation(mTextureProgram, "u_alpha");
shader = new Shader("texture_alpha");
}
public static RenderElement draw(RenderElement renderElement, GLViewport v, float scale,
float alpha) {
//GLState.test(false, false);
public static RenderElement draw(RenderElement renderElement, GLViewport v,
float scale, float alpha) {
GLState.blend(true);
GLState.useProgram(mTextureProgram);
GLState.enableVertexArrays(hTextureTexCoord, hTextureVertex);
Shader s = shader;
s.useProgram();
TextureLayer tl = (TextureLayer) renderElement;
if (tl.fixed)
GL.glUniform1f(hTextureScale, (float) Math.sqrt(scale));
else
GL.glUniform1f(hTextureScale, 1);
GL.glUniform1f(hTextureScreenScale, 1f / v.getWidth());
GL.glUniform1f(hAlpha, alpha);
v.proj.setAsUniform(hTextureProjMatrix);
v.mvp.setAsUniform(hTextureMVMatrix);
GL.glUniform1f(s.uAlpha, alpha);
v.mvp.setAsUniform(s.uMVP);
MapRenderer.bindQuadIndicesVBO(true);
@ -229,10 +222,10 @@ public class BitmapLayer extends TextureLayer {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
int off = (t.offset + i) * 8 + tl.offset;
GL.glVertexAttribPointer(hTextureVertex, 4,
GL.glVertexAttribPointer(s.aPos, 2,
GL20.GL_SHORT, false, 12, off);
GL.glVertexAttribPointer(hTextureTexCoord, 2,
GL.glVertexAttribPointer(s.aTexCoord, 2,
GL20.GL_SHORT, false, 12, off + 8);
int numVertices = t.vertices - i;
@ -248,26 +241,5 @@ public class BitmapLayer extends TextureLayer {
return renderElement.next;
}
private final static String textVertexShader = ""
+ "precision mediump float; "
+ "attribute vec4 vertex;"
+ "attribute vec2 tex_coord;"
+ "uniform mat4 u_mv;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_Position = u_mv * vec4(vertex.xy, 0.0, 1.0);"
+ " tex_c = tex_coord;"
+ "}";
private final static String textFragmentShader = ""
+ "precision mediump float;"
+ "uniform sampler2D tex;"
+ "uniform float u_alpha;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_FragColor = texture2D(tex, tex_c.xy) * u_alpha;"
+ "}";
}
}

View File

@ -25,6 +25,7 @@ import org.oscim.backend.canvas.Paint.Cap;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.MercatorProjection;
import org.oscim.core.Tile;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
@ -614,6 +615,31 @@ public final class LineLayer extends RenderElement {
return vertexItem;
}
static class Shader extends GLShader {
int uMVP, uFade, uWidth, uColor, uMode, uHeight, aPos;
Shader(String shaderFile) {
if (!create(shaderFile))
return;
uMVP = getUniform("u_mvp");
uFade = getUniform("u_fade");
uWidth = getUniform("u_width");
uColor = getUniform("u_color");
uMode = getUniform("u_mode");
uHeight = getUniform("u_height");
aPos = getAttrib("a_pos");
}
@Override
public boolean useProgram() {
if (super.useProgram()) {
GLState.enableVertexArrays(aPos, -1);
return true;
}
return false;
}
}
public static final class Renderer {
/* TODO:
* http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html */
@ -629,46 +655,13 @@ public final class LineLayer extends RenderElement {
private final static int SHADER_FLAT = 1;
private final static int SHADER_PROJ = 0;
/* shader handles */
private static int[] lineProgram = new int[2];
private static int[] hLineVertexPosition = new int[2];
private static int[] hLineColor = new int[2];
private static int[] hLineMatrix = new int[2];
private static int[] hLineFade = new int[2];
private static int[] hLineWidth = new int[2];
private static int[] hLineMode = new int[2];
private static int[] hLineHeight = new int[2];
public static int mTexID;
private static Shader[] shaders = { null, null };
static boolean init() {
lineProgram[0] = GLUtils.createProgram(lineVertexShader,
lineFragmentShader);
if (lineProgram[0] == 0) {
log.error("Could not create line program.");
//return false;
}
lineProgram[1] = GLUtils.createProgram(lineVertexShader,
lineSimpleFragmentShader);
if (lineProgram[1] == 0) {
log.error("Could not create simple line program.");
return false;
}
for (int i = 0; i < 2; i++) {
if (lineProgram[i] == 0)
continue;
hLineMatrix[i] = GL.glGetUniformLocation(lineProgram[i], "u_mvp");
hLineFade[i] = GL.glGetUniformLocation(lineProgram[i], "u_fade");
hLineWidth[i] = GL.glGetUniformLocation(lineProgram[i], "u_width");
hLineColor[i] = GL.glGetUniformLocation(lineProgram[i], "u_color");
hLineMode[i] = GL.glGetUniformLocation(lineProgram[i], "u_mode");
hLineHeight[i] = GL.glGetUniformLocation(lineProgram[i], "u_height");
hLineVertexPosition[i] = GL.glGetAttribLocation(lineProgram[i], "a_pos");
}
shaders[0] = new Shader("line_aa_proj");
shaders[1] = new Shader("line_aa");
/* create lookup table as texture for 'length(0..1,0..1)'
* using mirrored wrap mode for 'length(-1..1,-1..1)' */
@ -702,7 +695,10 @@ public final class LineLayer extends RenderElement {
* account. only used when tilt is 0. */
int mode = v.pos.tilt < 1 ? 1 : 0;
GLState.useProgram(lineProgram[mode]);
Shader s = shaders[mode];
s.useProgram();
//GLState.useProgram(lineProgram[mode]);
GLState.blend(true);
/* Somehow we loose the texture after an indefinite
@ -712,18 +708,16 @@ public final class LineLayer extends RenderElement {
if (!GLAdapter.GDX_DESKTOP_QUIRKS)
GLState.bindTex2D(mTexID);
int uLineFade = hLineFade[mode];
int uLineMode = hLineMode[mode];
int uLineColor = hLineColor[mode];
int uLineWidth = hLineWidth[mode];
int uLineHeight = hLineHeight[mode];
int uLineFade = s.uFade;
int uLineMode = s.uMode;
int uLineColor = s.uColor;
int uLineWidth = s.uWidth;
int uLineHeight = s.uHeight;
GLState.enableVertexArrays(hLineVertexPosition[mode], -1);
GL.glVertexAttribPointer(hLineVertexPosition[mode], 4, GL20.GL_SHORT,
GL.glVertexAttribPointer(s.aPos, 4, GL20.GL_SHORT,
false, 0, layers.offset[LINE]);
v.mvp.setAsUniform(hLineMatrix[mode]);
v.mvp.setAsUniform(s.uMVP);
/* Line scale factor for non fixed lines: Within a zoom-
* level lines would be scaled by the factor 2 by view-matrix.
@ -865,130 +859,5 @@ public final class LineLayer extends RenderElement {
return l;
}
private final static String lineVertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 u_mvp;"
//+ "uniform mat4 u_vp;"
/* factor to increase line width relative to scale */
+ "uniform float u_width;"
/* xy hold position, zw extrusion vector */
+ "attribute vec4 a_pos;"
+ "uniform float u_mode;"
+ "uniform float u_height;"
+ "varying vec2 v_st;"
+ "void main() {"
/* scale extrusion to u_width pixel
* just ignore the two most insignificant bits. */
+ " vec2 dir = a_pos.zw;"
+ " gl_Position = u_mvp * vec4(a_pos.xy + (u_width * dir), u_height, 1.0);"
/* last two bits hold the texture coordinates. */
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
+ "}";
private final static String lineVertexShader2 = ""
+ "precision highp float;"
+ "uniform mat4 u_mvp;"
+ "uniform mat4 u_vp;"
/* factor to increase line width relative to scale */
+ "uniform float u_width;"
/* xy hold position, zw extrusion vector */
+ "attribute vec4 a_pos;"
+ "uniform float u_mode;"
+ "varying vec2 v_st;"
+ "void main() {"
/* scale extrusion to u_width pixel */
/* just ignore the two most insignificant bits. */
+ " vec2 dir = a_pos.zw;"
+ " vec4 pos = u_vp * vec4(a_pos.xy + (u_width * dir), 0.0, 0.0);"
+ " vec4 orig = u_vp * vec4(a_pos.xy, 0.0, 0.0);"
+ " float len = length(orig - pos);"
//+ " if (len < 0.0625){"
+ " pos = u_mvp * vec4(a_pos.xy + (u_width * dir) / (len * 4.0), 0.0, 1.0);"
//+ " }"
//+ " else pos = u_mvp * vec4(a_pos.xy + (u_width * dir), 0.0, 1.0);"
+ " gl_Position = pos;"
/* last two bits hold the texture coordinates. */
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
+ "}";
/** Antialising for orthonogonal projection */
private final static String lineSimpleFragmentShader = ""
+ "precision mediump float;"
+ "uniform sampler2D tex;"
+ "uniform float u_fade;"
+ "uniform float u_mode;"
+ "uniform vec4 u_color;"
+ "varying vec2 v_st;"
+ "void main() {"
+ "float len;"
+ " if (u_mode == 2.0){"
/* round cap line */
+ (GLAdapter.GDX_DESKTOP_QUIRKS
? " len = length(v_st);"
: " len = texture2D(tex, v_st).a;")
+ " } else {"
/* flat cap line */
+ " len = abs(v_st.s);"
+ " }"
/* u_mode == 0.0 -> thin line */
//+ " len = len * clamp(u_mode, len, 1.0);"
/* use 'max' to avoid branching, need to check performance */
//+ (GLAdapter.GDX_DESKTOP_QUIRKS
// ? " float len = max((1.0 - u_mode) * abs(v_st.s), u_mode * length(v_st));"
// : " float len = max((1.0 - u_mode) * abs(v_st.s), u_mode * texture2D(tex, v_st).a);")
/* Antialias line-edges:
* - 'len' is 0 at center of line. -> (1.0 - len) is 0 at the
* edges
* - 'u_fade' is 'pixel' / 'width', i.e. the inverse width of
* the
* line in pixel on screen.
* - 'pixel' is 1.5 / relativeScale
* - '(1.0 - len) / u_fade' interpolates the 'pixel' on
* line-edge
* between 0 and 1 (it is greater 1 for all inner pixel). */
+ " gl_FragColor = u_color * clamp((1.0 - len) / u_fade, 0.0, 1.0);"
/* -> nicer for thin lines */
//+ " gl_FragColor = u_color * clamp((1.0 - (len * len)) / u_fade, 0.0, 1.0);"
+ "}";
private final static String lineFragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n"
+ "precision mediump float;"
+ "uniform sampler2D tex;"
+ "uniform float u_mode;"
+ "uniform vec4 u_color;"
+ "uniform float u_fade;"
+ "varying vec2 v_st;"
+ "void main() {"
+ " float len;"
+ " float fuzz;"
+ " if (u_mode == 2.0){"
/* round cap line */
+ (GLAdapter.GDX_DESKTOP_QUIRKS
? " len = length(v_st);"
: " len = texture2D(tex, v_st).a;")
+ " vec2 st_width = fwidth(v_st);"
+ " fuzz = max(st_width.s, st_width.t);"
+ " } else {"
/* flat cap line */
+ " len = abs(v_st.s);"
+ " fuzz = fwidth(v_st.s);"
+ " }"
/* u_mode == 0.0 -> thin line */
//+ " len = len * clamp(u_mode, len, 1.0);"
+ " if (fuzz > 2.0)"
+ " gl_FragColor = u_color * 0.5;" //vec4(1.0, 1.0, 1.0, 1.0);"
+ " else"
+ " gl_FragColor = u_color * clamp((1.0 - len) / max(u_fade, fuzz), 0.0, 1.0);"
//+ " gl_FragColor = u_color * clamp((1.0 - len), 0.0, 1.0);"
+ "}";
}
}

View File

@ -22,6 +22,7 @@ import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.core.GeometryBuffer;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
@ -250,49 +251,45 @@ public final class LineTexLayer extends RenderElement {
sbuf.position(sbuf.position() + 6);
}
static class Shader extends GLShader {
int uMVP, uColor, uWidth, uBgColor, uScale;
int uPatternWidth, uPatternScale;
int aPos0, aPos1, aLen0, aLen1, aFlip;
Shader(String shaderFile) {
if (!create(shaderFile))
return;
uMVP = getUniform("u_mvp");
uScale = getUniform("u_scale");
uColor = getUniform("u_color");
uWidth = getUniform("u_width");
uBgColor = getUniform("u_bgcolor");
uPatternWidth = getUniform("u_pwidth");
uPatternScale = getUniform("u_pscale");
aPos0 = getAttrib("a_pos0");
aPos1 = getAttrib("a_pos1");
aLen0 = getAttrib("a_len0");
aLen1 = getAttrib("a_len1");
aFlip = getAttrib("a_flip");
}
}
public final static class Renderer {
private static Shader shader;
/* factor to normalize extrusion vector and scale to coord scale */
private final static float COORD_SCALE_BY_DIR_SCALE =
MapRenderer.COORD_SCALE / LineLayer.DIR_SCALE;
private static int shader;
private static int hVertexPosition0;
private static int hVertexPosition1;
private static int hVertexLength0;
private static int hVertexLength1;
private static int hVertexFlip;
private static int hMatrix;
private static int hTexColor;
private static int hBgColor;
//private static int hScale;
private static int hWidth;
private static int hPatternScale;
private static int hPatternWidth;
private static int mVertexFlipID;
public static void init() {
shader = GLUtils.createProgram(vertexShader, fragmentShader);
if (shader == 0) {
log.error("Could not create program.");
return;
}
hMatrix = GL.glGetUniformLocation(shader, "u_mvp");
hTexColor = GL.glGetUniformLocation(shader, "u_color");
hBgColor = GL.glGetUniformLocation(shader, "u_bgcolor");
//hScale = GL.glGetUniformLocation(shader, "u_scale");
hWidth = GL.glGetUniformLocation(shader, "u_width");
hPatternScale = GL.glGetUniformLocation(shader, "u_pscale");
hPatternWidth = GL.glGetUniformLocation(shader, "u_pwidth");
hVertexPosition0 = GL.glGetAttribLocation(shader, "a_pos0");
hVertexPosition1 = GL.glGetAttribLocation(shader, "a_pos1");
hVertexLength0 = GL.glGetAttribLocation(shader, "a_len0");
hVertexLength1 = GL.glGetAttribLocation(shader, "a_len1");
hVertexFlip = GL.glGetAttribLocation(shader, "a_flip");
shader = new Shader("linetex_layer");
int[] vboIds = GLUtils.glGenBuffers(1);
mVertexFlipID = vboIds[0];
@ -327,28 +324,35 @@ public final class LineTexLayer extends RenderElement {
public static RenderElement draw(RenderElement curLayer, GLViewport v,
float div, ElementLayers layers) {
if (shader == 0)
return curLayer.next;
//if (shader == 0)
// return curLayer.next;
GLState.blend(true);
GLState.useProgram(shader);
//GLState.useProgram(shader);
shader.useProgram();
GLState.enableVertexArrays(-1, -1);
GL.glEnableVertexAttribArray(hVertexPosition0);
GL.glEnableVertexAttribArray(hVertexPosition1);
GL.glEnableVertexAttribArray(hVertexLength0);
GL.glEnableVertexAttribArray(hVertexLength1);
GL.glEnableVertexAttribArray(hVertexFlip);
int aLen0 = shader.aLen0;
int aLen1 = shader.aLen1;
int aPos0 = shader.aPos0;
int aPos1 = shader.aPos1;
int aFlip = shader.aFlip;
v.mvp.setAsUniform(hMatrix);
GL.glEnableVertexAttribArray(aPos0);
GL.glEnableVertexAttribArray(aPos1);
GL.glEnableVertexAttribArray(aLen0);
GL.glEnableVertexAttribArray(aLen1);
GL.glEnableVertexAttribArray(aFlip);
v.mvp.setAsUniform(shader.uMVP);
int maxIndices = MapRenderer.maxQuads * 6;
MapRenderer.bindQuadIndicesVBO(true);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, mVertexFlipID);
GL.glVertexAttribPointer(hVertexFlip, 1,
GL.glVertexAttribPointer(shader.aFlip, 1,
GL20.GL_BYTE, false, 0, 0);
layers.vbo.bind();
@ -364,19 +368,21 @@ public final class LineTexLayer extends RenderElement {
LineTexLayer ll = (LineTexLayer) l;
LineStyle line = ll.line.current();
GLUtils.setColor(hTexColor, line.stippleColor, 1);
GLUtils.setColor(hBgColor, line.color, 1);
GLUtils.setColor(shader.uColor, line.stippleColor, 1);
GLUtils.setColor(shader.uBgColor, line.color, 1);
float pScale = (int) (s + 0.5f);
if (pScale < 1)
pScale = 1;
GL.glUniform1f(hPatternScale, (MapRenderer.COORD_SCALE * line.stipple) / pScale);
GL.glUniform1f(hPatternWidth, line.stippleWidth);
GL.glUniform1f(shader.uPatternScale,
(MapRenderer.COORD_SCALE * line.stipple) / pScale);
GL.glUniform1f(shader.uPatternWidth, line.stippleWidth);
//GL.glUniform1f(hScale, scale);
/* keep line width fixed */
GL.glUniform1f(hWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE);
GL.glUniform1f(shader.uWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE);
/* add offset vertex */
int vOffset = -STRIDE;
@ -392,20 +398,16 @@ public final class LineTexLayer extends RenderElement {
/* i / 6 * (24 shorts per block * 2 short bytes) */
int add = (l.offset + i * 8) + vOffset;
GL.glVertexAttribPointer(hVertexPosition0,
4, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aPos0, 4, GL20.GL_SHORT, false, STRIDE,
add + STRIDE);
GL.glVertexAttribPointer(hVertexLength0,
2, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aLen0, 2, GL20.GL_SHORT, false, STRIDE,
add + STRIDE + LEN_OFFSET);
GL.glVertexAttribPointer(hVertexPosition1,
4, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aPos1, 4, GL20.GL_SHORT, false, STRIDE,
add);
GL.glVertexAttribPointer(hVertexLength1,
2, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aLen1, 2, GL20.GL_SHORT, false, STRIDE,
add + LEN_OFFSET);
GL.glDrawElements(GL20.GL_TRIANGLES, numIndices,
@ -421,20 +423,16 @@ public final class LineTexLayer extends RenderElement {
/* i / 6 * (24 shorts per block * 2 short bytes) */
int add = (l.offset + i * 8) + vOffset;
GL.glVertexAttribPointer(hVertexPosition0,
4, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aPos0, 4, GL20.GL_SHORT, false, STRIDE,
add + 2 * STRIDE);
GL.glVertexAttribPointer(hVertexLength0,
2, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aLen0, 2, GL20.GL_SHORT, false, STRIDE,
add + 2 * STRIDE + LEN_OFFSET);
GL.glVertexAttribPointer(hVertexPosition1,
4, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aPos1, 4, GL20.GL_SHORT, false, STRIDE,
add + STRIDE);
GL.glVertexAttribPointer(hVertexLength1,
2, GL20.GL_SHORT, false, STRIDE,
GL.glVertexAttribPointer(aLen1, 2, GL20.GL_SHORT, false, STRIDE,
add + STRIDE + LEN_OFFSET);
GL.glDrawElements(GL20.GL_TRIANGLES, numIndices,
@ -445,107 +443,15 @@ public final class LineTexLayer extends RenderElement {
MapRenderer.bindQuadIndicesVBO(false);
GL.glDisableVertexAttribArray(hVertexPosition0);
GL.glDisableVertexAttribArray(hVertexPosition1);
GL.glDisableVertexAttribArray(hVertexLength0);
GL.glDisableVertexAttribArray(hVertexLength1);
GL.glDisableVertexAttribArray(hVertexFlip);
GL.glDisableVertexAttribArray(aPos0);
GL.glDisableVertexAttribArray(aPos1);
GL.glDisableVertexAttribArray(aLen0);
GL.glDisableVertexAttribArray(aLen1);
GL.glDisableVertexAttribArray(aFlip);
//GL.glBindTexture(GL20.GL_TEXTURE_2D, 0);
return l;
}
final static String vertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 u_mvp;"
+ "uniform vec4 u_color;"
+ "uniform float u_pscale;"
+ "uniform float u_width;"
+ "attribute vec4 a_pos0;"
+ "attribute vec4 a_pos1;"
+ "attribute vec2 a_len0;"
+ "attribute vec2 a_len1;"
+ "attribute float a_flip;"
+ "varying vec2 v_st;"
+ "void main() {"
+ " vec4 pos;"
+ " if (a_flip == 0.0){"
//+ " vec2 dir = u_width * a_pos0.zw;"
+ " pos = vec4(a_pos0.xy + (u_width * a_pos0.zw), 0.0, 1.0);"
+ " v_st = vec2(a_len0.x / u_pscale, 1.0);"
+ " } else {"
//+ " vec2 dir = u_width * a_pos1.zw;"
+ " pos = vec4(a_pos1.xy - (u_width * a_pos1.zw), 0.0, 1.0);"
+ " v_st = vec2(a_len1.x / u_pscale, -1.0);"
+ " }"
+ " gl_Position = u_mvp * pos;"
+ "}";
//*
final static String fragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n"
+ " precision mediump float;"
+ " uniform vec4 u_color;"
+ " uniform vec4 u_bgcolor;"
+ " uniform float u_pwidth;"
+ " varying vec2 v_st;"
+ " void main() {"
/* distance on perpendicular to the line */
+ " float dist = abs(v_st.t);"
+ " float fuzz = fwidth(v_st.t);"
+ " float fuzz_p = fwidth(v_st.s);"
+ " float line_w = smoothstep(0.0, fuzz, 1.0 - dist);"
+ " float stipple_w = smoothstep(0.0, fuzz, u_pwidth - dist);"
/* triangle waveform in the range 0..1 for regular pattern */
+ " float phase = abs(mod(v_st.s, 2.0) - 1.0);"
/* interpolate between on/off phase, 0.5 = equal phase length */
+ " float stipple_p = smoothstep(0.5 - fuzz_p, 0.5 + fuzz_p, phase);"
+ " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));"
+ " } "; //*/
/* final static String fragmentShader = ""
* + "#extension GL_OES_standard_derivatives : enable\n"
* + " precision mediump float;"
* + " uniform sampler2D tex;"
* + " uniform float u_scale;"
* + " uniform vec4 u_color;"
* + " uniform vec4 u_bgcolor;"
* + " varying vec2 v_st;"
* + " void main() {"
* + " float len = texture2D(tex, v_st).a;"
* + " float tex_w = abs(v_st.t);"
* + " vec2 st_width = fwidth(v_st);"
* + " float fuzz = max(st_width.s, st_width.t);"
* //+ " float fuzz = fwidth(v_st.t);"
* //+ " float line_w = 1.0 - smoothstep(1.0 - fuzz, 1.0, tex_w);"
* //+ " float stipple_w = 1.0 - smoothstep(0.7 - fuzz, 0.7, tex_w);"
* +
* " float stipple_p = 1.0 - smoothstep(1.0 - fuzz, 1.0, length(vec2(len*u_scale, v_st.t)));"
* + " gl_FragColor = u_bgcolor * stipple_p;"
* // +
* " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));"
* + "}"; // */
/* final static String fragmentShader = ""
* + "#extension GL_OES_standard_derivatives : enable\n"
* + " precision mediump float;"
* + " uniform sampler2D tex;"
* + " uniform vec4 u_color;"
* + " uniform vec4 u_bgcolor;"
* + " uniform float u_pwidth;"
* + " varying vec2 v_st;"
* + " void main() {"
* + " float dist = texture2D(tex, v_st).a;"
* + " float tex_w = abs(v_st.t);"
* + " vec2 st_width = fwidth(v_st);"
* + " float fuzz = max(st_width.s, st_width.t);"
* + " float line_w = (1.0 - smoothstep(1.0 - fuzz, 1.0, tex_w));"
* +
* " float stipple_w = (1.0 - smoothstep(u_pwidth - fuzz, u_pwidth, tex_w));"
* + " float stipple_p = smoothstep(0.495, 0.505, dist);"
* +
* " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));"
* + " } "; // */
}
}

View File

@ -23,6 +23,7 @@ import org.oscim.backend.canvas.Color;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.MercatorProjection;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
@ -104,36 +105,38 @@ public class MeshLayer extends RenderElement {
}
public static class Renderer {
private static int shaderProgram;
private static int hMatrix;
private static int hColor;
private static int hHeightOffset;
private static int hVertexPosition;
static Shader shader;
static boolean init() {
shaderProgram = GLUtils.createProgram(vertexShader, fragmentShader);
if (shaderProgram == 0)
return false;
hMatrix = GL.glGetUniformLocation(shaderProgram, "u_mvp");
hColor = GL.glGetUniformLocation(shaderProgram, "u_color");
hHeightOffset = GL.glGetUniformLocation(shaderProgram, "u_height");
hVertexPosition = GL.glGetAttribLocation(shaderProgram, "a_pos");
shader = new Shader("mesh_layer_2D");
return true;
}
public static RenderElement draw(RenderElement l, GLViewport v) {
static class Shader extends GLShader {
int uMVP, uColor, uHeight, aPos;
Shader(String shaderFile) {
if (!create(shaderFile))
return;
uMVP = getUniform("u_mvp");
uColor = getUniform("u_color");
uHeight = getUniform("u_height");
aPos = getAttrib("a_pos");
}
}
public static RenderElement draw(RenderElement l, GLViewport v) {
GLState.blend(true);
GLState.useProgram(shaderProgram);
Shader s = shader;
s.useProgram();
GLState.enableVertexArrays(s.aPos, -1);
GLState.enableVertexArrays(hVertexPosition, -1);
v.mvp.setAsUniform(hMatrix);
v.mvp.setAsUniform(s.uMVP);
float heightOffset = 0;
GL.glUniform1f(hHeightOffset, heightOffset);
GL.glUniform1f(s.uHeight, heightOffset);
for (; l != null && l.type == RenderElement.MESH; l = l.next) {
MeshLayer ml = (MeshLayer) l;
@ -144,25 +147,25 @@ public class MeshLayer extends RenderElement {
if (ml.heightOffset != heightOffset) {
heightOffset = ml.heightOffset;
GL.glUniform1f(hHeightOffset, heightOffset /
GL.glUniform1f(s.uHeight, heightOffset /
MercatorProjection.groundResolution(v.pos));
}
ml.indicesVbo.bind();
if (ml.area == null)
GLUtils.setColor(hColor, Color.BLUE, 0.4f);
GLUtils.setColor(s.uColor, Color.BLUE, 0.4f);
else
GLUtils.setColor(hColor, ml.area.color, 1);
GLUtils.setColor(s.uColor, ml.area.color, 1);
GL.glVertexAttribPointer(hVertexPosition, 2, GL20.GL_SHORT,
GL.glVertexAttribPointer(s.aPos, 2, GL20.GL_SHORT,
false, 0, ml.offset);
GL.glDrawElements(GL20.GL_TRIANGLES, ml.numIndices,
GL20.GL_UNSIGNED_SHORT, 0);
if (dbg) {
GLUtils.setColor(hColor, Color.GRAY, 0.4f);
GLUtils.setColor(s.uColor, Color.GRAY, 0.4f);
GL.glDrawElements(GL20.GL_LINES, ml.numIndices,
GL20.GL_UNSIGNED_SHORT, 0);
}
@ -172,21 +175,5 @@ public class MeshLayer extends RenderElement {
return l;
}
private final static String vertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 u_mvp;"
+ "uniform float u_height;"
+ "attribute vec2 a_pos;"
+ "void main() {"
+ " gl_Position = u_mvp * vec4(a_pos, u_height, 1.0);"
+ "}";
private final static String fragmentShader = ""
+ "precision mediump float;"
+ "uniform vec4 u_color;"
+ "void main() {"
+ " gl_FragColor = u_color;"
+ "}";
}
}

View File

@ -16,15 +16,10 @@
*/
package org.oscim.renderer.elements;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile;
import org.oscim.renderer.GLMatrix;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
@ -37,7 +32,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Special Renderer for drawing tile polygons using a stencil buffer method
* Special Renderer for drawing tile polygons using the stencil buffer method
*/
public final class PolygonLayer extends RenderElement {
static final Logger log = LoggerFactory.getLogger(PolygonLayer.class);
@ -118,9 +113,25 @@ public final class PolygonLayer extends RenderElement {
si.used = outPos;
}
static class Shader extends GLShader {
int uMVP, uColor, uScale, aPos;
Shader(String shaderFile) {
if (!create(shaderFile))
return;
uMVP = getUniform("u_mvp");
aPos = getAttrib("a_pos");
if (shaderFile == "polygon_layer_tex")
uScale = getUniform("u_scale");
else
uColor = getUniform("u_color");
}
}
public static final class Renderer {
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
private static final int STENCIL_BITS = 8;
private final static int CLIP_BIT = 0x80;
@ -128,45 +139,12 @@ public final class PolygonLayer extends RenderElement {
private static AreaStyle[] mAreaFills;
private static int numShaders = 2;
private static int polyShader = 0;
private static int texShader = 1;
private static int[] polygonProgram = new int[numShaders];
private static int[] hPolygonVertexPosition = new int[numShaders];
private static int[] hPolygonMatrix = new int[numShaders];
private static int[] hPolygonColor = new int[numShaders];
private static int[] hPolygonScale = new int[numShaders];
private static Shader polyShader;
private static Shader texShader;
static boolean init() {
for (int i = 0; i < numShaders; i++) {
// Set up the program for rendering polygons
if (i == 0) {
if (GLAdapter.debugView)
polygonProgram[i] = GLUtils.createProgram(polygonVertexShaderZ,
polygonFragmentShaderZ);
else
polygonProgram[i] = GLUtils.createProgram(polygonVertexShader,
polygonFragmentShader);
} else if (i == 1) {
polygonProgram[i] = GLUtils.createProgram(textureVertexShader,
textureFragmentShader);
}
if (polygonProgram[i] == 0) {
log.error("Could not create polygon program.");
return false;
}
hPolygonMatrix[i] = GL.glGetUniformLocation(polygonProgram[i], "u_mvp");
hPolygonColor[i] = GL.glGetUniformLocation(polygonProgram[i], "u_color");
hPolygonScale[i] = GL.glGetUniformLocation(polygonProgram[i], "u_scale");
hPolygonVertexPosition[i] = GL.glGetAttribLocation(polygonProgram[i], "a_pos");
}
polyShader = new Shader("base_shader");
texShader = new Shader("polygon_layer_tex");
mAreaFills = new AreaStyle[STENCIL_BITS];
@ -181,17 +159,18 @@ public final class PolygonLayer extends RenderElement {
/* do not modify stencil buffer */
GL.glStencilMask(0x00);
int shader = polyShader;
//int shader = polyShader;
Shader s = setShader(polyShader, v, false);
for (int c = start; c < end; c++) {
AreaStyle a = mAreaFills[c].current();
if (enableTexture && a.texture != null) {
shader = texShader;
setShader(texShader, v);
s = setShader(texShader, v, false);
float num = FastMath.clamp((Tile.SIZE / a.texture.width) >> 1, 1, Tile.SIZE);
float transition = Interpolation.exp5.apply(FastMath.clamp(scale - 1, 0, 1));
GL.glUniform2f(hPolygonScale[1], transition, div / num);
GL.glUniform2f(s.uScale, transition, div / num);
//if (a.texture.alpha);
GLState.blend(true);
@ -208,17 +187,17 @@ public final class PolygonLayer extends RenderElement {
}
GLState.blend(true);
GLUtils.setColor(hPolygonColor[shader], a.color, f);
GLUtils.setColor(s.uColor, a.color, f);
} else if (a.blendScale > 0 && a.blendScale <= zoom) {
/* blend colors (not alpha) */
GLState.blend(false);
if (a.blendScale == zoom)
GLUtils.setColorBlend(hPolygonColor[shader],
a.color, a.blendColor, scale - 1.0f);
GLUtils.setColorBlend(s.uColor, a.color,
a.blendColor, scale - 1.0f);
else
GLUtils.setColor(hPolygonColor[shader], a.blendColor, 1);
GLUtils.setColor(s.uColor, a.blendColor, 1);
} else {
if (a.color < 0xff000000)
@ -226,38 +205,37 @@ public final class PolygonLayer extends RenderElement {
else
GLState.blend(false);
GLUtils.setColor(hPolygonColor[shader], a.color, 1);
GLUtils.setColor(s.uColor, a.color, 1);
}
// set stencil buffer mask used to draw this layer
// also check that clip bit is set to avoid overdraw
// of other tiles
/* set stencil buffer mask used to draw this layer
* also check that clip bit is set to avoid overdraw
* of other tiles */
GL.glStencilFunc(GL20.GL_EQUAL, 0xff, CLIP_BIT | 1 << c);
/* draw tile fill coordinates */
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
if (shader != polyShader) {
// disable texture shader
setShader(polyShader, v);
shader = polyShader;
}
/* disable texture shader */
if (s != polyShader)
s = setShader(polyShader, v, false);
}
}
// current layer to fill (0 - STENCIL_BITS-1)
private static int mCount;
private static void setShader(int shader, GLViewport v) {
GLState.useProgram(polygonProgram[shader]);
private static Shader setShader(Shader shader, GLViewport v, boolean first) {
if (shader.useProgram() || first) {
GLState.enableVertexArrays(hPolygonVertexPosition[shader], -1);
GLState.enableVertexArrays(shader.aPos, -1);
GL.glVertexAttribPointer(hPolygonVertexPosition[shader], 2,
GL20.GL_SHORT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
GL.glVertexAttribPointer(shader.aPos, 2,
GL20.GL_SHORT, false, 0, 0);
v.mvp.setAsUniform(hPolygonMatrix[shader]);
v.mvp.setAsUniform(shader.uMVP);
}
return shader;
}
/**
@ -287,14 +265,14 @@ public final class PolygonLayer extends RenderElement {
GLState.test(false, true);
setShader(polyShader, v);
setShader(polyShader, v, first);
int zoom = v.pos.zoomLevel;
float scale = (float) v.pos.getZoomScale();
int cur = mCount;
// reset start when only one layer left in stencil buffer
/* reset start when only one layer left in stencil buffer */
if (first || cur > 5)
cur = 0;
@ -304,7 +282,7 @@ public final class PolygonLayer extends RenderElement {
for (; l != null && l.type == RenderElement.POLYGON; l = l.next) {
PolygonLayer pl = (PolygonLayer) l;
// fade out polygon layers (set in RenderTheme)
/* fade out polygon layers (set in RenderTheme) */
if (pl.area.fadeScale > 0 && pl.area.fadeScale > zoom)
continue;
@ -312,18 +290,18 @@ public final class PolygonLayer extends RenderElement {
drawStencilRegion(first, clipMode);
first = false;
// op for stencil method polygon drawing
/* op for stencil method polygon drawing */
GL.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_INVERT);
}
mAreaFills[cur] = pl.area.current();
// set stencil mask to draw to
/* set stencil mask to draw to */
GL.glStencilMask(1 << cur++);
GL.glDrawArrays(GL20.GL_TRIANGLE_FAN, l.offset, l.numVertices);
// draw up to 7 layers into stencil buffer
/* draw up to 7 layers into stencil buffer */
if (cur == STENCIL_BITS - 1) {
fillPolygons(v, start, cur, zoom, scale, div);
start = cur = 0;
@ -336,12 +314,12 @@ public final class PolygonLayer extends RenderElement {
if (clipMode > 0) {
if (first) {
drawStencilRegion(first, clipMode);
// disable writes to stencil buffer
/* disable writes to stencil buffer */
GL.glStencilMask(0x00);
// enable writes to color buffer
/* enable writes to color buffer */
GL.glColorMask(true, true, true, true);
} else {
// set test for clip to tile region
/* set test for clip to tile region */
GL.glStencilFunc(GL20.GL_EQUAL, CLIP_BIT, CLIP_BIT);
}
}
@ -352,12 +330,12 @@ public final class PolygonLayer extends RenderElement {
}
public static void clip(GLViewport v) {
setShader(polyShader, v);
setShader(polyShader, v, true);
drawStencilRegion(true, 1);
// disable writes to stencil buffer
/* disable writes to stencil buffer */
GL.glStencilMask(0x00);
// enable writes to color buffer
/* enable writes to color buffer */
GL.glColorMask(true, true, true, true);
}
@ -419,10 +397,11 @@ public final class PolygonLayer extends RenderElement {
* and 'alpha' to fake a fade effect.
*/
public static void drawOver(GLViewport v, int color, float alpha) {
setShader(polyShader, v);
// TODO true could be avoided when same shader and vbo
setShader(polyShader, v, true);
if (color != 0) {
GLUtils.setColor(hPolygonColor[0], color, alpha);
GLUtils.setColor(polyShader.uColor, color, alpha);
GLState.blend(true);
} else {
/* disable drawing to framebuffer (will be re-enabled in fill) */
@ -447,103 +426,39 @@ public final class PolygonLayer extends RenderElement {
GL.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;
//private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
//private static float[] debugFillColor2 = { .8f, .8f, .8f, .8f };
//private static FloatBuffer mDebugFill;
static void debugDraw(GLMatrix m, float[] coords, int color) {
GLState.test(false, false);
if (mDebugFill == null) {
mDebugFill = ByteBuffer
.allocateDirect(32)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mDebugFill.put(coords);
//static void debugDraw(GLMatrix m, float[] coords, int color) {
// GLState.test(false, false);
// if (mDebugFill == null) {
// mDebugFill = ByteBuffer
// .allocateDirect(32)
// .order(ByteOrder.nativeOrder())
// .asFloatBuffer();
// mDebugFill.put(coords);
// }
//
// GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
//
// mDebugFill.position(0);
// GLState.useProgram(polygonProgram[0]);
// GL.glEnableVertexAttribArray(hPolygonVertexPosition[0]);
//
// GL.glVertexAttribPointer(hPolygonVertexPosition[0], 2, GL20.GL_FLOAT,
// false, 0, mDebugFill);
//
// m.setAsUniform(hPolygonMatrix[0]);
//
// if (color == 0)
// GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor);
// else
// GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor2);
//
// GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
//
// GLUtils.checkGlError("draw debug");
//}
}
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
mDebugFill.position(0);
GLState.useProgram(polygonProgram[0]);
GL.glEnableVertexAttribArray(hPolygonVertexPosition[0]);
GL.glVertexAttribPointer(hPolygonVertexPosition[0], 2, GL20.GL_FLOAT,
false, 0, mDebugFill);
m.setAsUniform(hPolygonMatrix[0]);
if (color == 0)
GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor);
else
GLUtils.glUniform4fv(hPolygonColor[0], 1, debugFillColor2);
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
GLUtils.checkGlError("draw debug");
}
private final static String polygonVertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 u_mvp;"
+ "attribute vec4 a_pos;"
+ "void main() {"
+ " gl_Position = u_mvp * a_pos;"
+ "}";
private final static String polygonFragmentShader = ""
+ "precision mediump float;"
+ "uniform vec4 u_color;"
+ "void main() {"
+ " gl_FragColor = u_color;"
+ "}";
private final static String polygonVertexShaderZ = ""
+ "precision highp float;"
+ "uniform mat4 u_mvp;"
+ "attribute vec4 a_pos;"
+ "varying float z;"
+ "void main() {"
+ " gl_Position = u_mvp * a_pos;"
+ " z = gl_Position.z;"
+ "}";
private final static String polygonFragmentShaderZ = ""
+ "precision highp float;"
+ "uniform vec4 u_color;"
+ "varying float z;"
+ "void main() {"
+ "if (z < -1.0)"
+ " gl_FragColor = vec4(0.0, z + 2.0, 0.0, 1.0)*0.8;"
+ "else if (z < 0.0)"
+ " gl_FragColor = vec4(z + 1.0, 0.0, 0.0, 1.0)*0.8;"
+ "else if (z < 1.0)"
+ " gl_FragColor = vec4(0.0, 0.0, z, 1.0)*0.8;"
+ "else"
+ " gl_FragColor = vec4(0.0, z - 1.0, 0.0, 1.0)*0.8;"
+ "}";
private final static String textureVertexShader = ""
+ "precision mediump float;"
+ "uniform mat4 u_mvp;"
+ "uniform vec2 u_scale;"
+ "attribute vec4 a_pos;"
+ "varying vec2 v_st;"
+ "varying vec2 v_st2;"
+ "void main() {"
+ " v_st = clamp(a_pos.xy, 0.0, 1.0) * (2.0 / u_scale.y);"
+ " v_st2 = clamp(a_pos.xy, 0.0, 1.0) * (4.0 / u_scale.y);"
+ " gl_Position = u_mvp * a_pos;"
+ "}";
private final static String textureFragmentShader = ""
+ "precision mediump float;"
+ "uniform vec4 u_color;"
+ "uniform sampler2D tex;"
+ "uniform vec2 u_scale;"
+ "varying vec2 v_st;"
+ "varying vec2 v_st2;"
+ "void main() {"
+ " gl_FragColor = mix(texture2D(tex, v_st), texture2D(tex, v_st2), u_scale.x);"
+ "}";
}
}

View File

@ -21,8 +21,8 @@ import static org.oscim.renderer.MapRenderer.COORD_SCALE;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport;
import org.oscim.renderer.MapRenderer;
import org.oscim.renderer.elements.TextureItem.TexturePool;
@ -113,56 +113,60 @@ public abstract class TextureLayer extends RenderElement {
buf[pos + 23] = v1;
}
static class Shader extends GLShader {
int uMV, uProj, uScale, uTexSize, aPos, aTexCoord;
Shader() {
if (!create("texture_layer"))
return;
uMV = getUniform("u_mv");
uProj = getUniform("u_proj");
uScale = getUniform("u_scale");
uTexSize = getUniform("u_div");
aPos = getAttrib("vertex");
aTexCoord = getAttrib("tex_coord");
}
@Override
public boolean useProgram() {
if (super.useProgram()) {
GLState.enableVertexArrays(aPos, aTexCoord);
return true;
}
return false;
}
}
public static final class Renderer {
public final static boolean debug = false;
private static int mTextureProgram;
private static int hTextureMVMatrix;
private static int hTextureProjMatrix;
private static int hTextureVertex;
private static int hTextureScale;
private static int hTextureTexCoord;
private static int hTextureSize;
private static Shader shader;
static void init() {
mTextureProgram = GLUtils.createProgram(textVertexShader,
textFragmentShader);
hTextureMVMatrix = GL.glGetUniformLocation(mTextureProgram, "u_mv");
hTextureProjMatrix = GL.glGetUniformLocation(mTextureProgram, "u_proj");
hTextureScale = GL.glGetUniformLocation(mTextureProgram, "u_scale");
hTextureSize = GL.glGetUniformLocation(mTextureProgram, "u_div");
hTextureVertex = GL.glGetAttribLocation(mTextureProgram, "vertex");
hTextureTexCoord = GL.glGetAttribLocation(mTextureProgram, "tex_coord");
shader = new Shader();
/* FIXME pool should be disposed on exit... */
pool.init(0);
}
public static RenderElement draw(RenderElement l, GLViewport v, float scale) {
shader.useProgram();
GLState.test(false, false);
GLState.blend(true);
GLState.useProgram(mTextureProgram);
GLState.enableVertexArrays(hTextureTexCoord, hTextureVertex);
TextureLayer tl = (TextureLayer) l;
if (tl.fixed)
GL.glUniform1f(hTextureScale, 1 / scale);
else
GL.glUniform1f(hTextureScale, 1);
GL.glUniform1f(shader.uScale, tl.fixed ? 1 / scale : 1);
v.proj.setAsUniform(hTextureProjMatrix);
v.mvp.setAsUniform(hTextureMVMatrix);
v.proj.setAsUniform(shader.uProj);
v.mvp.setAsUniform(shader.uMV);
MapRenderer.bindQuadIndicesVBO(true);
for (TextureItem t = tl.textures; t != null; t = t.next) {
GL.glUniform2f(hTextureSize,
GL.glUniform2f(shader.uTexSize,
1f / (t.width * COORD_SCALE),
1f / (t.height * COORD_SCALE));
t.bind();
@ -175,10 +179,10 @@ public abstract class TextureLayer extends RenderElement {
* / 6(indices) == 8) */
int off = (t.offset + i) * 8 + tl.offset;
GL.glVertexAttribPointer(hTextureVertex, 4,
GL.glVertexAttribPointer(shader.aPos, 4,
GL20.GL_SHORT, false, 12, off);
GL.glVertexAttribPointer(hTextureTexCoord, 2,
GL.glVertexAttribPointer(shader.aTexCoord, 2,
GL20.GL_SHORT, false, 12, off + 8);
int numVertices = t.vertices - i;
@ -194,38 +198,5 @@ public abstract class TextureLayer extends RenderElement {
return l.next;
}
private final static double COORD_DIV = 1.0 / MapRenderer.COORD_SCALE;
private final static String textVertexShader = ""
+ "precision highp float;"
+ "attribute vec4 vertex;"
+ "attribute vec2 tex_coord;"
+ "uniform mat4 u_mv;"
+ "uniform mat4 u_proj;"
+ "uniform float u_scale;"
+ "uniform vec2 u_div;"
+ "varying vec2 tex_c;"
+ "const float coord_scale = " + COORD_DIV + ";"
+ "void main() {"
+ " vec4 pos;"
+ " vec2 dir = vertex.zw;"
+ " if (mod(vertex.x, 2.0) == 0.0){"
+ " pos = u_proj * (u_mv * vec4(vertex.xy + dir * u_scale, 0.0, 1.0));"
+ " } else {" // place as billboard
+ " vec4 center = u_mv * vec4(vertex.xy, 0.0, 1.0);"
+ " pos = u_proj * (center + vec4(dir * coord_scale, 0.0, 0.0));"
+ " }"
+ " gl_Position = pos;"
+ " tex_c = tex_coord * u_div;"
+ "}";
private final static String textFragmentShader = ""
+ "precision highp float;"
+ "uniform sampler2D tex;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_FragColor = texture2D(tex, tex_c.xy);"
+ "}";
}
}