diff --git a/src/box2dLight/DirectionalLight.java b/src/box2dLight/DirectionalLight.java index ec5e72c..d521742 100644 --- a/src/box2dLight/DirectionalLight.java +++ b/src/box2dLight/DirectionalLight.java @@ -229,6 +229,14 @@ protected void updateDynamicShadowMeshes() { float l = data.height / (float) Math.tan(height * MathUtils.degRad); float f = 1f / data.shadowsDropped; + + float startColBits = rayHandler.shadowColorInterpolation ? + Color.BLACK.lerp(rayHandler.ambientLight, 1-f).toFloatBits() : + zeroColorBits; + float endColBits = rayHandler.shadowColorInterpolation ? + Color.WHITE.lerp(rayHandler.ambientLight, 1-f).toFloatBits() : + colBits; + if (type == Type.Polygon || type == Type.Chain) { boolean isPolygon = (type == Type.Polygon); ChainShape cShape = isPolygon ? @@ -296,16 +304,16 @@ protected void updateDynamicShadowMeshes() { for (int n : ind.toArray()) { tmpVec.set(tmpVerts.get(n)); - tmpEnd.set(tmpVec).sub(lstart).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(lstart).setLength(l).add(tmpVec); segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; } } else if (type == Type.Circle) { @@ -324,13 +332,13 @@ protected void updateDynamicShadowMeshes() { tmpStart.set(center).add(tmpVec); segments[size++] = tmpStart.x; segments[size++] = tmpStart.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpStart).sub(lstart).limit(l).add(tmpStart); + tmpEnd.set(tmpStart).sub(lstart).setLength(l).add(tmpStart); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; tmpVec.rotateRad(angle); @@ -343,26 +351,26 @@ protected void updateDynamicShadowMeshes() { segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpVec).sub(lstart).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(lstart).setLength(l).add(tmpVec); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; shape.getVertex2(tmpVec); tmpVec.set(body.getWorldPoint(tmpVec)); segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpVec).sub(lstart).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(lstart).setLength(l).add(tmpVec); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; } diff --git a/src/box2dLight/LightData.java b/src/box2dLight/LightData.java index 1b12134..7f53588 100644 --- a/src/box2dLight/LightData.java +++ b/src/box2dLight/LightData.java @@ -22,7 +22,7 @@ public LightData(Object data, float h) { public float getLimit(float distance, float lightHeight, float lightRange) { float l = 0f; if (lightHeight > height) { - l = lightRange * height / (lightHeight - height); + l = distance * height / (lightHeight - height); float diff = lightRange - distance; if (l > diff) l = diff; } else if (lightHeight == 0f) { @@ -30,8 +30,8 @@ public float getLimit(float distance, float lightHeight, float lightRange) { } else { l = lightRange - distance; } - if (l < 0) l = 0f; - return l; + + return l > 0 ? l : 0f; } public static Object getUserData(Fixture fixture) { diff --git a/src/box2dLight/PointLight.java b/src/box2dLight/PointLight.java index e4ae367..d883527 100644 --- a/src/box2dLight/PointLight.java +++ b/src/box2dLight/PointLight.java @@ -88,6 +88,7 @@ void dynamicShadowRender () { protected void updateDynamicShadowMeshes() { int meshInd = 0; + float colBits = rayHandler.ambientLight.toFloatBits(); for (Fixture fixture : affectedFixtures) { LightData data = (LightData)fixture.getUserData(); @@ -97,6 +98,13 @@ protected void updateDynamicShadowMeshes() { float l = 0f; float f = 1f / data.shadowsDropped; + float startColBits = rayHandler.shadowColorInterpolation ? + Color.BLACK.lerp(rayHandler.ambientLight, 1-f).toFloatBits() : + zeroColorBits; + float endColBits = rayHandler.shadowColorInterpolation ? + Color.WHITE.lerp(rayHandler.ambientLight, 1-f).toFloatBits() : + colBits; + Shape fixtureShape = fixture.getShape(); Type type = fixtureShape.getType(); Body body = fixture.getBody(); @@ -170,17 +178,16 @@ protected void updateDynamicShadowMeshes() { float dst = tmpVec.dst(start); l = data.getLimit(dst, height, distance); - - tmpEnd.set(tmpVec).sub(start).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(start).setLength(l).add(tmpVec); segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; } } else if (type == Type.Circle) { @@ -199,13 +206,13 @@ protected void updateDynamicShadowMeshes() { tmpStart.set(center).add(tmpVec); segments[size++] = tmpStart.x; segments[size++] = tmpStart.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpStart).sub(start).limit(l).add(tmpStart); + tmpEnd.set(tmpStart).sub(start).setLength(l).add(tmpStart); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; tmpVec.rotateRad(angle); @@ -220,13 +227,13 @@ protected void updateDynamicShadowMeshes() { segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpVec).sub(start).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(start).setLength(l).add(tmpVec); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; shape.getVertex2(tmpVec); @@ -236,13 +243,13 @@ protected void updateDynamicShadowMeshes() { segments[size++] = tmpVec.x; segments[size++] = tmpVec.y; - segments[size++] = zeroColorBits; + segments[size++] = startColBits; segments[size++] = f; - tmpEnd.set(tmpVec).sub(start).limit(l).add(tmpVec); + tmpEnd.set(tmpVec).sub(start).setLength(l).add(tmpVec); segments[size++] = tmpEnd.x; segments[size++] = tmpEnd.y; - segments[size++] = colBits; + segments[size++] = endColBits; segments[size++] = f; } diff --git a/src/box2dLight/RayHandler.java b/src/box2dLight/RayHandler.java index 7ba048a..a1370ed 100644 --- a/src/box2dLight/RayHandler.java +++ b/src/box2dLight/RayHandler.java @@ -87,6 +87,7 @@ public class RayHandler implements Disposable { /** Experimental mode **/ boolean pseudo3d = false; + boolean shadowColorInterpolation = false; int blurNum = 1; @@ -560,6 +561,16 @@ public void useDefaultViewport() { public void setPseudo3dLight(boolean flag) { pseudo3d = flag; } + + /** + * /!\ Experimental mode with dynamic shadowing in pseudo-3d world + * + * @param flag + */ + public void setPseudo3dLight(boolean flag, boolean interpolateShadows) { + pseudo3d = flag; + shadowColorInterpolation = interpolateShadows; + } /** * Enables/disables lightMap automatic rendering.