Add shadowstrength attribute for surface renderer - enables shadows

based on top-down chunk sky light data
This commit is contained in:
Mike Primm 2011-05-20 20:52:34 -05:00
parent 920dea04ee
commit 992a905b0a
3 changed files with 257 additions and 199 deletions

View File

@ -59,6 +59,8 @@ worlds:
prefix: t prefix: t
maximumheight: 127 maximumheight: 127
colorscheme: default colorscheme: default
# Add shadows to world (based on top-down shadows from chunk data)
# shadowstrength: 1.0
#- class: org.dynmap.kzedmap.HighlightTileRenderer #- class: org.dynmap.kzedmap.HighlightTileRenderer
# prefix: ht # prefix: ht
# maximumheight: 127 # maximumheight: 127

View File

@ -89,8 +89,8 @@ public class MapChunkCache {
Object cc = gethandle.invoke(c); Object cc = gethandle.invoke(c);
byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; /* Get big enough buffer for whole chunk */ byte[] buf = new byte[32768 + 16384 + 16384 + 16384]; /* Get big enough buffer for whole chunk */
getchunkdata.invoke(cc, buf, 0, 0, 0, 16, 128, 16, 0); getchunkdata.invoke(cc, buf, 0, 0, 0, 16, 128, 16, 0);
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = CraftChunkSnapshot ss = new CraftChunkSnapshot(chunk.x, chunk.z, buf);
new CraftChunkSnapshot(chunk.x, chunk.z, buf); snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
} catch (Exception x) { } catch (Exception x) {
} }
} }
@ -195,4 +195,19 @@ public class MapChunkCache {
return w.getHighestBlockYAt(x, z); return w.getHighestBlockYAt(x, z);
} }
} }
/* Get sky light level
*/
public int getBlockSkyLight(int x, int y, int z) {
if(snaparray != null) {
CraftChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
if(ss == null) {
return 15;
}
else
return ss.getBlockSkyLight(x & 0xF, y, z & 0xF);
}
else {
return 15;
}
}
} }

View File

@ -29,6 +29,7 @@ public class DefaultTileRenderer implements MapTileRenderer {
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>(); protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
protected Color highlightColor = new Color(255, 0, 0); protected Color highlightColor = new Color(255, 0, 0);
protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */
@Override @Override
public String getName() { public String getName() {
return name; return name;
@ -42,6 +43,19 @@ public class DefaultTileRenderer implements MapTileRenderer {
if (maximumHeight > 127) if (maximumHeight > 127)
maximumHeight = 127; maximumHeight = 127;
} }
o = configuration.get("shadowstrength");
if(o != null) {
double shadowweight = Double.parseDouble(String.valueOf(o));
if(shadowweight > 0.0) {
shadowscale = new int[16];
for(int i = 0; i < 16; i++) {
double v = 256.0 * (1.0 - (shadowweight * (15-i) / 15.0));
shadowscale[i] = (int)v;
if(shadowscale[i] > 256) shadowscale[i] = 256;
if(shadowscale[i] < 0) shadowscale[i] = 0;
}
}
}
colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme")); colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme"));
} }
@ -210,9 +224,14 @@ public class DefaultTileRenderer implements MapTileRenderer {
new Client.Tile(zmtile.getFilename())); new Client.Tile(zmtile.getFilename()));
} }
protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result, protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result,
MapChunkCache cache) { MapChunkCache cache) {
scan(world, x, y, z, seq, isnether, result, cache, 15);
}
private void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result,
MapChunkCache cache, int lightlevel) {
int newlightlevel = 15;
result.setTransparent(); result.setTransparent();
for (;;) { for (;;) {
if (y < 0) { if (y < 0) {
@ -234,6 +253,10 @@ public class DefaultTileRenderer implements MapTileRenderer {
if(colorScheme.datacolors[id] != null) { /* If data colored */ if(colorScheme.datacolors[id] != null) { /* If data colored */
data = cache.getBlockData(x, y, z); data = cache.getBlockData(x, y, z);
} }
if(shadowscale != null) {
newlightlevel = cache.getBlockSkyLight(x, y, z); /* Remember this - light path for next block */
}
switch (seq) { switch (seq) {
case 0: case 0:
x--; x--;
@ -268,16 +291,25 @@ public class DefaultTileRenderer implements MapTileRenderer {
if (c.getAlpha() == 255) { if (c.getAlpha() == 255) {
/* it's opaque - the ray ends here */ /* it's opaque - the ray ends here */
result.setColor(c); result.setColor(c);
if(lightlevel < 15) { /* Not full light? */
shadowColor(result, lightlevel);
}
return; return;
} }
/* this block is transparent, so recurse */ /* this block is transparent, so recurse */
scan(world, x, y, z, seq, isnether, result, cache); scan(world, x, y, z, seq, isnether, result, cache, newlightlevel);
int cr = c.getRed(); int cr = c.getRed();
int cg = c.getGreen(); int cg = c.getGreen();
int cb = c.getBlue(); int cb = c.getBlue();
int ca = c.getAlpha(); int ca = c.getAlpha();
if(lightlevel < 15) {
int scale = shadowscale[lightlevel];
cr = (cr * scale) >> 8;
cg = (cg * scale) >> 8;
cb = (cb * scale) >> 8;
}
cr *= ca; cr *= ca;
cg *= ca; cg *= ca;
cb *= ca; cb *= ca;
@ -287,6 +319,15 @@ public class DefaultTileRenderer implements MapTileRenderer {
} }
} }
} }
lightlevel = newlightlevel; /* Advance - next block uses last block's light */
} }
} }
private final void shadowColor(Color c, int lightlevel) {
int scale = shadowscale[lightlevel];
if(scale == 0)
c.setRGBA(0, 0, 0, c.getAlpha());
else if(scale < 256)
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
(c.getBlue() * scale) >> 8, c.getAlpha());
}
} }