diff --git a/vtm-gdx/src/org/oscim/gdx/GdxAssetAdapter.java b/vtm-gdx/src/org/oscim/gdx/GdxAssetAdapter.java index b0119ddc..6af06f06 100644 --- a/vtm-gdx/src/org/oscim/gdx/GdxAssetAdapter.java +++ b/vtm-gdx/src/org/oscim/gdx/GdxAssetAdapter.java @@ -35,6 +35,7 @@ public class GdxAssetAdapter extends AssetAdapter { try { return file.read(); } catch (GdxRuntimeException e) { + e.printStackTrace(); return null; } } diff --git a/vtm/resources/assets/shaders/extrusion_layer_ext.glsl b/vtm/resources/assets/shaders/extrusion_layer_ext.glsl new file mode 100644 index 00000000..4ae42668 --- /dev/null +++ b/vtm/resources/assets/shaders/extrusion_layer_ext.glsl @@ -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; +} diff --git a/vtm/resources/assets/shaders/extrusion_layer_mesh.glsl b/vtm/resources/assets/shaders/extrusion_layer_mesh.glsl new file mode 100644 index 00000000..34db13b1 --- /dev/null +++ b/vtm/resources/assets/shaders/extrusion_layer_mesh.glsl @@ -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; +} diff --git a/vtm/resources/assets/shaders/line_aa.glsl b/vtm/resources/assets/shaders/line_aa.glsl new file mode 100644 index 00000000..64b06bd2 --- /dev/null +++ b/vtm/resources/assets/shaders/line_aa.glsl @@ -0,0 +1,61 @@ +#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; +} +$$ +#ifndef DESKTOP_QUIRKS +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); +} diff --git a/vtm/resources/assets/shaders/line_aa_proj.glsl b/vtm/resources/assets/shaders/line_aa_proj.glsl new file mode 100644 index 00000000..e2dfb095 --- /dev/null +++ b/vtm/resources/assets/shaders/line_aa_proj.glsl @@ -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); +} diff --git a/vtm/resources/assets/shaders/poly_texture.glsl b/vtm/resources/assets/shaders/poly_texture.glsl new file mode 100644 index 00000000..01c5d144 --- /dev/null +++ b/vtm/resources/assets/shaders/poly_texture.glsl @@ -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); +} diff --git a/vtm/resources/assets/shaders/simple_shader.glsl b/vtm/resources/assets/shaders/simple_shader.glsl new file mode 100644 index 00000000..174ce389 --- /dev/null +++ b/vtm/resources/assets/shaders/simple_shader.glsl @@ -0,0 +1,13 @@ +precision mediump float; +uniform mat4 u_mvp; +attribute vec4 a_pos; +void main() { + gl_Position = u_mvp * a_pos; +} +§ +precision mediump float; +uniform vec4 u_color; +void main() { + gl_FragColor = u_color; +} + diff --git a/vtm/resources/assets/shaders/texture_layer.glsl b/vtm/resources/assets/shaders/texture_layer.glsl new file mode 100644 index 00000000..169d7a4d --- /dev/null +++ b/vtm/resources/assets/shaders/texture_layer.glsl @@ -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); +} diff --git a/vtm/src/org/oscim/backend/AssetAdapter.java b/vtm/src/org/oscim/backend/AssetAdapter.java index 33d06845..ce6fa3f7 100644 --- a/vtm/src/org/oscim/backend/AssetAdapter.java +++ b/vtm/src/org/oscim/backend/AssetAdapter.java @@ -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(); + } } diff --git a/vtm/src/org/oscim/renderer/GLShader.java b/vtm/src/org/oscim/renderer/GLShader.java new file mode 100644 index 00000000..61e06cf8 --- /dev/null +++ b/vtm/src/org/oscim/renderer/GLShader.java @@ -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 { + + } +} diff --git a/vtm/src/org/oscim/renderer/MapRenderer.java b/vtm/src/org/oscim/renderer/MapRenderer.java index 02c748e7..68ea493b 100644 --- a/vtm/src/org/oscim/renderer/MapRenderer.java +++ b/vtm/src/org/oscim/renderer/MapRenderer.java @@ -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); diff --git a/vtm/src/org/oscim/renderer/elements/PolygonLayer.java b/vtm/src/org/oscim/renderer/elements/PolygonLayer.java index 0eed9f1e..4ca4ac79 100644 --- a/vtm/src/org/oscim/renderer/elements/PolygonLayer.java +++ b/vtm/src/org/oscim/renderer/elements/PolygonLayer.java @@ -21,7 +21,6 @@ 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; @@ -145,16 +144,11 @@ public final class PolygonLayer extends RenderElement { // 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); + polygonProgram[i] = ShaderProgram.loadShader("simple_shader"); + //polygonProgram[i] = GLUtils.createProgram(polygonVertexShader, + // polygonFragmentShader); } else if (i == 1) { - polygonProgram[i] = GLUtils.createProgram(textureVertexShader, - textureFragmentShader); - + polygonProgram[i] = ShaderProgram.loadShader("poly_texture"); } if (polygonProgram[i] == 0) { @@ -482,68 +476,68 @@ public final class PolygonLayer extends RenderElement { 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 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 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 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);" - + "}"; + // 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);" + // + "}"; } }