Extrusions: light source calculation with normals (#651)

This commit is contained in:
Gustl22 2019-02-03 20:49:39 +01:00 committed by Emux
parent bab34aab2b
commit 48a5c36c31
No known key found for this signature in database
GPG Key ID: 64ED9980896038C3
5 changed files with 103 additions and 70 deletions

View File

@ -5,13 +5,25 @@ uniform mat4 u_mvp;
uniform vec4 u_color[4]; uniform vec4 u_color[4];
uniform int u_mode; uniform int u_mode;
uniform float u_alpha; uniform float u_alpha;
uniform vec3 u_light;
uniform float u_zlimit; uniform float u_zlimit;
attribute vec4 a_pos; attribute vec4 a_pos;
attribute vec2 a_light; attribute vec2 a_normal;
varying vec4 color; varying vec4 color;
//varying float depth; //varying float depth;
const float ff = 255.0; const float ff = 255.0;
/**
* The diffuse of surface dependent on the light position
*
* @param r_norm - the normal vector of vertex's face
*/
float diffuse(in vec3 r_norm) {
float l = dot(normalize(r_norm), normalize(u_light));
l = clamp((1.0 + l) / 2.0, 0.0, 1.0);
return(0.8 + l * 0.2);
}
void main() { void main() {
// change height by u_alpha // change height by u_alpha
float height = a_pos.z * u_alpha; float height = a_pos.z * u_alpha;
@ -22,30 +34,33 @@ void main() {
//depth = gl_Position.z; //depth = gl_Position.z;
if (u_mode == -1) { if (u_mode == -1) {
; ;
} else if(u_mode >= 0 && u_mode <= 2) {
vec3 r_norm;
if (u_mode == 0) {
// roof / depth pass // roof / depth pass
// color = u_color[0] * u_alpha; r_norm = vec3(0.0, 0.0, 1.0);
}
else if (u_mode == 0) {
// roof / depth pass
color = u_color[0] * u_alpha; color = u_color[0] * u_alpha;
} color.rgb *= diffuse(r_norm);
else if (u_mode == 1) { } else {
float lightX = u_mode == 1 ? a_normal.y : a_normal.x;
r_norm.x = (lightX / ff) * 2.0 - 1.0;
// normal points y left or right (1 or -1)
float dir = - 1.0 + (2.0 * abs(mod(lightX, 2.0)));
// recreate y vector
r_norm.y = dir * sqrt(clamp(1.0 - (r_norm.x * r_norm.x), 0.0, 1.0));
r_norm.z = 0.0;
float z = (0.98 + gl_Position.z * 0.02);
float h = 0.9 + clamp(a_pos.z / 2000.0, 0.0, 0.1);
if (u_mode == 1) {
// sides 1 - use 0xff00 // 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 = u_color[1];
color.rgb *= (0.8 + dir * 0.2) * z * h; } else {
color *= u_alpha;
}
else if (u_mode == 2) {
// sides 2 - use 0x00ff // 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 = u_color[2];
color.rgb *= (0.8 + dir * 0.2) * z * h; }
color.rgb *= diffuse(r_norm) * z * h;
}
color *= u_alpha; color *= u_alpha;
} }
else if (u_mode == 3) { else if (u_mode == 3) {

View File

@ -4,8 +4,9 @@ precision highp float;
uniform mat4 u_mvp; uniform mat4 u_mvp;
uniform vec4 u_color; uniform vec4 u_color;
uniform float u_alpha; uniform float u_alpha;
uniform vec3 u_light;
attribute vec4 a_pos; attribute vec4 a_pos;
attribute vec2 a_light; attribute vec2 a_normal;
varying vec4 color; varying vec4 color;
void main() { void main() {
@ -14,25 +15,27 @@ void main() {
pos.z *= u_alpha; pos.z *= u_alpha;
gl_Position = u_mvp * pos; gl_Position = u_mvp * pos;
// normalize face x/y direction // normalize face x/y direction
vec2 enc = (a_light / 255.0); vec2 enc = (a_normal / 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; vec3 r_norm;
r_norm.xy = fenc * g; // 1² - |xy|² = |z|²
r_norm.z = 1.0 - f / 2.0; r_norm.xy = enc * 2.0 - 1.0;
// normal points up or down (1,-1) // normal points up or down (1,-1)
//// float dir = 1.0 - (2.0 * abs(mod(a_light.x,2.0))); float dir = - 1.0 + (2.0 * abs(mod(a_normal.x, 2.0)));
// recreate face normal vector // recreate z vector
/// vec3 r_norm = vec3(n.xy, dir * (1.0 - length(n.xy))); r_norm.z = dir * sqrt(clamp(1.0 - (r_norm.x * r_norm.x + r_norm.y * r_norm.y), 0.0, 1.0));
vec3 light_dir = normalize(vec3(0.2, 0.2, 1.0)); r_norm = normalize(r_norm);
float l = dot(r_norm, light_dir) * 0.8;
light_dir = normalize(vec3(-0.2, -0.2, 1.0)); float l = dot(r_norm, normalize(u_light));
l += dot(r_norm, light_dir) * 0.2;
// l = (l + (1.0 - r_norm.z))*0.5; //l *= 0.8
l = 0.4 + l * 0.6; //vec3 opp_light_dir = normalize(vec3(-u_light.xy, u_light.z));
//l += dot(r_norm, opp_light_dir) * 0.2;
// [-1,1] to range [0,1]
l = (1.0 + l) / 2.0;
l = 0.75 + l * 0.25;
// extreme fake-ssao by height // extreme fake-ssao by height
l += (clamp(a_pos.z / 2048.0, 0.0, 0.1) - 0.05); l += (clamp(a_pos.z / 2048.0, 0.0, 0.1) - 0.05);

View File

@ -2,7 +2,7 @@
* Copyright 2013 Hannes Janetzek * Copyright 2013 Hannes Janetzek
* Copyright 2017 Izumi Kawashima * Copyright 2017 Izumi Kawashima
* Copyright 2017 devemux86 * Copyright 2017 devemux86
* Copyright 2018 Gustl22 * Copyright 2018-2019 Gustl22
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
* *
@ -45,6 +45,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
protected float mAlpha = 1; protected float mAlpha = 1;
private float mZLimit = Float.MAX_VALUE; private float mZLimit = Float.MAX_VALUE;
private float[] mLightPos = new float[]{0.3f, 0.3f, 1f};
public ExtrusionRenderer(boolean mesh, boolean translucent) { public ExtrusionRenderer(boolean mesh, boolean translucent) {
mMesh = mesh; mMesh = mesh;
@ -58,9 +59,9 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
int aPos; int aPos;
/** /**
* The light indicator of vertex's face as attribute. * The normal of vertex's face as attribute.
*/ */
int aLight; int aNormal;
/** /**
* The alpha value (e.g. for fading animation) as uniform. * The alpha value (e.g. for fading animation) as uniform.
@ -72,6 +73,11 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
*/ */
int uColor; int uColor;
/**
* The lights position vector as uniform.
*/
int uLight;
/** /**
* The shader render mode as uniform. * The shader render mode as uniform.
* <p> * <p>
@ -104,7 +110,8 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
uMode = getUniform("u_mode"); uMode = getUniform("u_mode");
uZLimit = getUniform("u_zlimit"); uZLimit = getUniform("u_zlimit");
aPos = getAttrib("a_pos"); aPos = getAttrib("a_pos");
aLight = getAttrib("a_light"); aNormal = getAttrib("a_normal");
uLight = getUniform("u_light");
} }
} }
@ -164,6 +171,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
gl.depthFunc(GL.LESS); gl.depthFunc(GL.LESS);
gl.uniform1f(s.uAlpha, mAlpha); gl.uniform1f(s.uAlpha, mAlpha);
gl.uniform1f(s.uZLimit, mZLimit); gl.uniform1f(s.uZLimit, mZLimit);
GLUtils.glUniform3fv(s.uLight, 1, mLightPos);
ExtrusionBuckets[] ebs = mExtrusionBucketSet; ExtrusionBuckets[] ebs = mExtrusionBucketSet;
@ -199,7 +207,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
GLState.blend(true); GLState.blend(true);
GLState.enableVertexArrays(s.aPos, s.aLight); GLState.enableVertexArrays(s.aPos, s.aNormal);
for (int i = 0; i < mBucketsCnt; i++) { for (int i = 0; i < mBucketsCnt; i++) {
if (ebs[i].ibo == null) if (ebs[i].ibo == null)
@ -231,7 +239,7 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
gl.vertexAttribPointer(s.aPos, 3, GL.SHORT, gl.vertexAttribPointer(s.aPos, 3, GL.SHORT,
false, RenderBuckets.SHORT_BYTES * 4, eb.getVertexOffset()); false, RenderBuckets.SHORT_BYTES * 4, eb.getVertexOffset());
gl.vertexAttribPointer(s.aLight, 2, GL.UNSIGNED_BYTE, gl.vertexAttribPointer(s.aNormal, 2, GL.UNSIGNED_BYTE,
false, RenderBuckets.SHORT_BYTES * 4, eb.getVertexOffset() + RenderBuckets.SHORT_BYTES * 3); false, RenderBuckets.SHORT_BYTES * 4, eb.getVertexOffset() + RenderBuckets.SHORT_BYTES * 3);
/* draw extruded outlines (mMesh == false) */ /* draw extruded outlines (mMesh == false) */

View File

@ -283,6 +283,13 @@ public class GLUtils {
color[2] = FastMath.clampN((float) (p + (b - p) * change)); color[2] = FastMath.clampN((float) (p + (b - p) * change));
} }
public static void glUniform3fv(int location, int count, float[] val) {
FloatBuffer buf = MapRenderer.getFloatBuffer(count * 3);
buf.put(val);
buf.flip();
gl.uniform3fv(location, count, buf);
}
public static void glUniform4fv(int location, int count, float[] val) { public static void glUniform4fv(int location, int count, float[] val) {
FloatBuffer buf = MapRenderer.getFloatBuffer(count * 4); FloatBuffer buf = MapRenderer.getFloatBuffer(count * 4);
buf.put(val); buf.put(val);

View File

@ -1,6 +1,6 @@
/* /*
* Copyright 2012, 2013 Hannes Janetzek * Copyright 2012, 2013 Hannes Janetzek
* Copyright 2017 Gustl22 * Copyright 2017-2019 Gustl22
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
* *
@ -68,7 +68,7 @@ public class ExtrusionBucket extends RenderBucket {
private KeyMap<Vertex> mVertexMap; private KeyMap<Vertex> mVertexMap;
//private static final int NORMAL_DIR_MASK = 0xFFFFFFFE; private static final int NORMAL_DIR_MASK = 0xFFFFFFFE;
//private int numIndexHits = 0; //private int numIndexHits = 0;
/** /**
@ -214,14 +214,9 @@ public class ExtrusionBucket extends RenderBucket {
double len = Math.sqrt(cx * cx + cy * cy + cz * cz); double len = Math.sqrt(cx * cx + cy * cy + cz * cz);
// packing the normal in two bytes // packing the normal in two bytes
// int mx = FastMath.clamp(127 + (int) ((cx / len) * 128), 0, 0xff); int mx = FastMath.clamp(127 + (int) ((cx / len) * 128), 0, 0xff);
// int my = FastMath.clamp(127 + (int) ((cy / len) * 128), 0, 0xff); int my = FastMath.clamp(127 + (int) ((cy / len) * 128), 0, 0xff);
// short normal = (short) ((my << 8) | (mx & NORMAL_DIR_MASK) | (cz > 0 ? 1 : 0)); short normal = (short) ((my << 8) | (mx & NORMAL_DIR_MASK) | (cz > 0 ? 1 : 0));
double p = Math.sqrt((cz / len) * 8.0 + 8.0);
int mx = FastMath.clamp(127 + (int) ((cx / len / p) * 128), 0, 255);
int my = FastMath.clamp(127 + (int) ((cy / len / p) * 128), 0, 255);
short normal = (short) ((my << 8) | mx);
if (key == null) if (key == null)
key = vertexPool.get(); key = vertexPool.get();
@ -472,10 +467,13 @@ public class ExtrusionBucket extends RenderBucket {
/* vector from previous point */ /* vector from previous point */
float ux, uy; float ux, uy;
// Normalized normal of first point (with vy direction included)
// Normal of vector (x|y) is (y|-x)
float a = (float) Math.sqrt(vx * vx + vy * vy); float a = (float) Math.sqrt(vx * vx + vy * vy);
short color1 = (short) ((1 + vx / a) * 127); short mx1 = (short) ((1 + (vy / a)) * 127);
mx1 = (short) ((mx1 & NORMAL_DIR_MASK) | (-vx > 0 ? 1 : 0));
short fcolor = color1, color2 = 0; short mxStore = mx1, mx2 = 0;
short h = (short) height, mh = (short) minHeight; short h = (short) height, mh = (short) minHeight;
@ -502,7 +500,7 @@ public class ExtrusionBucket extends RenderBucket {
nx = points[pos + 0]; nx = points[pos + 0];
ny = points[pos + 1]; ny = points[pos + 1];
} else { // if (addFace) } else { // if (addFace)
short c = (short) (color1 | fcolor << 8); short c = (short) (mx1 | mxStore << 8);
/* add bottom and top vertex for each point */ /* add bottom and top vertex for each point */
vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), mh, c); vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), mh, c);
vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), h, c); vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), h, c);
@ -515,20 +513,22 @@ public class ExtrusionBucket extends RenderBucket {
vy = ny - cy; vy = ny - cy;
/* set lighting (by direction) */ /* set lighting (by direction) */
// Normal of vector (x|y) is (y|-x)
a = (float) Math.sqrt(vx * vx + vy * vy); a = (float) Math.sqrt(vx * vx + vy * vy);
color2 = (short) ((1 + vx / a) * 127); mx2 = (short) ((1 + (vy / a)) * 127);
mx2 = (short) ((mx2 & NORMAL_DIR_MASK) | (-vx > 0 ? 1 : 0));
short c; short c;
if (even == 0) if (even == 0)
c = (short) (color1 | color2 << 8); c = (short) (mx1 | mx2 << 8);
else else
c = (short) (color2 | color1 << 8); c = (short) (mx2 | mx1 << 8);
/* add bottom and top vertex for each point */ /* add bottom and top vertex for each point */
vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), mh, c); vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), mh, c);
vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), h, c); vertexItems.add((short) (cx * COORD_SCALE), (short) (cy * COORD_SCALE), h, c);
color1 = color2; mx1 = mx2;
/* check if polygon is convex */ /* check if polygon is convex */
if (convex) { if (convex) {