Split lighting and shading - add lightings.txt

This commit is contained in:
Mike Primm 2011-07-09 01:26:47 -05:00
parent 69baafe597
commit a3c00a1026
14 changed files with 387 additions and 151 deletions

30
lightings.txt Normal file
View file

@ -0,0 +1,30 @@
lightings:
# Default lighting - no effects, shadows, day/night
- class: org.dynmap.hdmap.DefaultHDLighting
name: default
# Shadows enabled day mode
- class: org.dynmap.hdmap.ShadowHDLighting
name: shadows
shadowstrength: 1.0
# Night view (default moonight level is 4)
- class: org.dynmap.hdmap.ShadowHDLighting
name: night
shadowstrength: 1.0
ambientlight: 4
# A 'bright' night view (easier to see unlit landscape dimly)
- class: org.dynmap.hdmap.ShadowHDLighting
name: brightnight
shadowstrength: 1.0
ambientlight: 8
# Night and day view
- class: org.dynmap.hdmap.ShadowHDLighting
name: nightandday
shadowstrength: 1.0
ambientlight: 4
night-and-day: true
# 'Bright' Night and day view
- class: org.dynmap.hdmap.ShadowHDLighting
name: brightnightandday
shadowstrength: 1.0
ambientlight: 8
night-and-day: true

View file

@ -1,18 +1,36 @@
shaders: shaders:
- class: org.dynmap.hdmap.DefaultHDShader - class: org.dynmap.hdmap.DefaultHDShader
name: classic name: default
colorscheme: default colorscheme: default
- class: org.dynmap.hdmap.DefaultHDShader - class: org.dynmap.hdmap.DefaultHDShader
name: night name: ovocean
colorscheme: default colorscheme: ovocean
ambientlight: 4
shadowstrength: 1.0
- class: org.dynmap.hdmap.DefaultHDShader - class: org.dynmap.hdmap.DefaultHDShader
name: daynight name: flames
colorscheme: default colorscheme: flames
ambientlight: 4
shadowstrength: 1.0 - class: org.dynmap.hdmap.DefaultHDShader
night-and-day: true name: sk89q
colorscheme: sk89q
- class: org.dynmap.hdmap.DefaultHDShader
name: biome
biomecolored: biome
- class: org.dynmap.hdmap.DefaultHDShader
name: temperature
biomecolored: temperature
- class: org.dynmap.hdmap.DefaultHDShader
name: rainfall
biomecolored: rainfall
- class: org.dynmap.hdmap.DefaultHDShader
name: no_transparency
colorscheme: default
transparency: false

View file

@ -29,7 +29,8 @@
<includes> <includes>
<include>configuration.txt</include> <include>configuration.txt</include>
<include>shaders.txt</include> <include>shaders.txt</include>
<include>perspectives.txt</include></includes></fileSet> <include>perspectives.txt</include>
<include>lightings.txt</include></includes></fileSet>
</fileSets> </fileSets>
<files> <files>
<file> <file>

View file

@ -48,6 +48,7 @@ public class DynmapPlugin extends JavaPlugin {
public ConfigurationNode configuration; public ConfigurationNode configuration;
public ConfigurationNode shaderconfig; public ConfigurationNode shaderconfig;
public ConfigurationNode perspectiveconfig; public ConfigurationNode perspectiveconfig;
public ConfigurationNode lightingsconfig;
public HashSet<String> enabledTriggers = new HashSet<String>(); public HashSet<String> enabledTriggers = new HashSet<String>();
public PermissionProvider permissions; public PermissionProvider permissions;
public ComponentManager componentManager = new ComponentManager(); public ComponentManager componentManager = new ComponentManager();
@ -86,6 +87,9 @@ public class DynmapPlugin extends JavaPlugin {
org.bukkit.util.config.Configuration bukkitPerspectiveConfig = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "perspectives.txt")); org.bukkit.util.config.Configuration bukkitPerspectiveConfig = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "perspectives.txt"));
bukkitPerspectiveConfig.load(); bukkitPerspectiveConfig.load();
perspectiveconfig = new ConfigurationNode(bukkitPerspectiveConfig); perspectiveconfig = new ConfigurationNode(bukkitPerspectiveConfig);
org.bukkit.util.config.Configuration bukkitLightingsConfig = new org.bukkit.util.config.Configuration(new File(this.getDataFolder(), "lightings.txt"));
bukkitLightingsConfig.load();
lightingsconfig = new ConfigurationNode(bukkitLightingsConfig);
Log.verbose = configuration.getBoolean("verbose", true); Log.verbose = configuration.getBoolean("verbose", true);
@ -99,7 +103,7 @@ public class DynmapPlugin extends JavaPlugin {
playerList = new PlayerList(getServer(), getFile("hiddenplayers.txt"), configuration); playerList = new PlayerList(getServer(), getFile("hiddenplayers.txt"), configuration);
playerList.load(); playerList.load();
mapManager = new MapManager(this, configuration, shaderconfig, perspectiveconfig); mapManager = new MapManager(this, configuration, shaderconfig, perspectiveconfig, lightingsconfig);
mapManager.startRendering(); mapManager.startRendering();
loadWebserver(); loadWebserver();

View file

@ -319,13 +319,15 @@ public class MapManager {
} }
} }
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration, ConfigurationNode shadercfg, ConfigurationNode perspectivecfg) { public MapManager(DynmapPlugin plugin, ConfigurationNode configuration, ConfigurationNode shadercfg, ConfigurationNode perspectivecfg,
ConfigurationNode lightingscfg) {
plug_in = plugin; plug_in = plugin;
mapman = this; mapman = this;
/* Initialize HD map manager */ /* Initialize HD map manager */
hdmapman = new HDMapManager(); hdmapman = new HDMapManager();
hdmapman.loadHDShaders(shadercfg); hdmapman.loadHDShaders(shadercfg);
hdmapman.loadHDPerspectives(perspectivecfg); hdmapman.loadHDPerspectives(perspectivecfg);
hdmapman.loadHDLightings(lightingscfg);
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() { this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
@Override @Override

View file

@ -0,0 +1,54 @@
package org.dynmap.hdmap;
import java.util.HashSet;
import org.dynmap.Color;
import org.dynmap.ColorScheme;
import org.dynmap.ConfigurationNode;
import org.dynmap.hdmap.DefaultHDShader.BiomeColorOption;
import org.json.simple.JSONObject;
import static org.dynmap.JSONUtils.s;
public class DefaultHDLighting implements HDLighting {
private String name;
public DefaultHDLighting(ConfigurationNode configuration) {
name = (String) configuration.get("name");
}
/* Get lighting name */
public String getName() { return name; }
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
for(Color oc: outcolor)
oc.setColor(incolor);
}
/* Test if Biome Data is needed for this renderer */
public boolean isBiomeDataNeeded() { return false; }
/* Test if raw biome temperature/rainfall data is needed */
public boolean isRawBiomeDataNeeded() { return false; }
/* Test if highest block Y data is needed */
public boolean isHightestBlockYDataNeeded() { return false; }
/* Tet if block type data needed */
public boolean isBlockTypeDataNeeded() { return false; }
/* Test if night/day is enabled for this renderer */
public boolean isNightAndDayEnabled() { return false; }
/* Test if sky light level needed */
public boolean isSkyLightLevelNeeded() { return false; }
/* Test if emitted light level needed */
public boolean isEmittedLightLevelNeeded() { return false; }
/* Add shader's contributions to JSON for map object */
public void addClientConfiguration(JSONObject mapObject) {
s(mapObject, "lighting", name);
s(mapObject, "nightandday", isNightAndDayEnabled());
}
}

View file

@ -1,7 +1,6 @@
package org.dynmap.hdmap; package org.dynmap.hdmap;
import static org.dynmap.JSONUtils.s; import static org.dynmap.JSONUtils.s;
import java.util.HashSet;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.ColorScheme; import org.dynmap.ColorScheme;
@ -14,12 +13,6 @@ public class DefaultHDShader implements HDShader {
private String name; private String name;
protected ColorScheme colorScheme; protected ColorScheme colorScheme;
protected HashSet<Integer> highlightBlocks = new HashSet<Integer>();
protected Color highlightColor = new Color(255, 0, 0);
protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */
protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */
protected boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
protected boolean transparency; /* Is transparency support active? */ protected boolean transparency; /* Is transparency support active? */
public enum BiomeColorOption { public enum BiomeColorOption {
NONE, BIOME, TEMPERATURE, RAINFALL NONE, BIOME, TEMPERATURE, RAINFALL
@ -28,30 +21,7 @@ public class DefaultHDShader implements HDShader {
public DefaultHDShader(ConfigurationNode configuration) { public DefaultHDShader(ConfigurationNode configuration) {
name = (String) configuration.get("name"); name = (String) configuration.get("name");
double shadowweight = configuration.getDouble("shadowstrength", 0.0);
if(shadowweight > 0.0) {
shadowscale = new int[16];
shadowscale[15] = 256;
/* Normal brightness weight in MC is a 20% relative dropoff per step */
for(int i = 14; i >= 0; i--) {
double v = shadowscale[i+1] * (1.0 - (0.2 * shadowweight));
shadowscale[i] = (int)v;
if(shadowscale[i] > 256) shadowscale[i] = 256;
if(shadowscale[i] < 0) shadowscale[i] = 0;
}
}
int v = configuration.getInteger("ambientlight", -1);
if(v >= 0) {
lightscale = new int[16];
for(int i = 0; i < 16; i++) {
if(i < (15-v))
lightscale[i] = 0;
else
lightscale[i] = i - (15-v);
}
}
colorScheme = ColorScheme.getScheme(configuration.getString("colorscheme", "default")); colorScheme = ColorScheme.getScheme(configuration.getString("colorscheme", "default"));
night_and_day = configuration.getBoolean("night-and-day", false);
transparency = configuration.getBoolean("transparency", true); /* Default on */ transparency = configuration.getBoolean("transparency", true); /* Default on */
String biomeopt = configuration.getString("biomecolored", "none"); String biomeopt = configuration.getString("biomecolored", "none");
if(biomeopt.equals("biome")) { if(biomeopt.equals("biome")) {
@ -68,30 +38,60 @@ public class DefaultHDShader implements HDShader {
} }
} }
public boolean isBiomeDataNeeded() { return biomecolored == BiomeColorOption.BIOME; } @Override
public boolean isRawBiomeDataNeeded() { return (biomecolored == BiomeColorOption.RAINFALL) || (biomecolored == BiomeColorOption.TEMPERATURE); }; public boolean isBiomeDataNeeded() {
public boolean isNightAndDayEnabled() { return night_and_day; } return biomecolored == BiomeColorOption.BIOME;
public boolean isSkyLightLevelNeeded() { return (lightscale != null); } }
public boolean isEmittedLightLevelNeeded() { return (shadowscale != null); }
public boolean isHightestBlockYDataNeeded() { return false; }
public boolean isBlockTypeDataNeeded() { return true; }
public String getName() { return name; }
private class OurRendererState implements HDShaderState { @Override
private Color color = new Color(); public boolean isRawBiomeDataNeeded() {
private Color daycolor; return (biomecolored == BiomeColorOption.RAINFALL) || (biomecolored == BiomeColorOption.TEMPERATURE);
}
@Override
public boolean isHightestBlockYDataNeeded() {
return false;
}
@Override
public boolean isBlockTypeDataNeeded() {
return true;
}
@Override
public boolean isSkyLightLevelNeeded() {
return false;
}
@Override
public boolean isEmittedLightLevelNeeded() {
return false;
}
@Override
public String getName() {
return name;
}
private class OurShaderState implements HDShaderState {
private Color color[];
protected MapIterator mapiter; protected MapIterator mapiter;
protected HDMap map; protected HDMap map;
private Color tmpcolor = new Color(); private Color tmpcolor[];
private Color tmpdaycolor = new Color();
private int pixelodd; private int pixelodd;
private HDLighting lighting;
private OurRendererState(MapIterator mapiter, HDMap map) { private OurShaderState(MapIterator mapiter, HDMap map) {
this.mapiter = mapiter; this.mapiter = mapiter;
this.map = map; this.map = map;
if(night_and_day) { this.lighting = map.getLighting();
daycolor = new Color(); if(lighting.isNightAndDayEnabled()) {
color = new Color[] { new Color(), new Color() };
tmpcolor = new Color[] { new Color(), new Color() };
}
else {
color = new Color[] { new Color() };
tmpcolor = new Color[] { new Color() };
} }
} }
/** /**
@ -107,13 +107,18 @@ public class DefaultHDShader implements HDShader {
public HDMap getMap() { public HDMap getMap() {
return map; return map;
} }
/**
* Get our lighting
*/
public HDLighting getLighting() {
return lighting;
}
/** /**
* Reset renderer state for new ray * Reset renderer state for new ray
*/ */
public void reset(HDPerspectiveState ps) { public void reset(HDPerspectiveState ps) {
color.setTransparent(); for(Color c: color)
if(daycolor != null) c.setTransparent();
daycolor.setTransparent();
pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1); pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1);
} }
@ -129,6 +134,7 @@ public class DefaultHDShader implements HDShader {
* @return true if ray is done, false if ray needs to continue * @return true if ray is done, false if ray needs to continue
*/ */
public boolean processBlock(HDPerspectiveState ps) { public boolean processBlock(HDPerspectiveState ps) {
int i;
int blocktype = ps.getBlockTypeID(); int blocktype = ps.getBlockTypeID();
if(blocktype == 0) if(blocktype == 0)
return false; return false;
@ -140,75 +146,44 @@ public class DefaultHDShader implements HDShader {
switch(ps.getLastBlockStep()) { switch(ps.getLastBlockStep()) {
case X_PLUS: case X_PLUS:
case X_MINUS: case X_MINUS:
seq = 1; seq = 0;
break; break;
case Z_PLUS: case Z_PLUS:
case Z_MINUS: case Z_MINUS:
seq = 3; seq = 2;
break; break;
default: default:
if(((pixelodd + mapiter.getY()) & 0x03) == 0) if(((pixelodd + mapiter.getY()) & 0x03) == 0)
seq = 2; seq = 3;
else else
seq = 0; seq = 1;
break; break;
} }
Color c = colors[seq]; Color c = colors[seq];
if (c.getAlpha() > 0) { if (c.getAlpha() > 0) {
/* Handle light level, if needed */ /* Handle light level, if needed */
int lightlevel = 15, lightlevel_day = 15; lighting.applyLighting(ps, this, c, tmpcolor);
if(shadowscale != null) {
lightlevel = lightlevel_day = ps.getSkyLightLevel();
if(lightscale != null)
lightlevel = lightscale[lightlevel];
if((lightlevel < 15) || (lightlevel_day < 15)) {
int emitted = ps.getEmittedLightLevel();
lightlevel = Math.max(emitted, lightlevel);
lightlevel_day = Math.max(emitted, lightlevel_day);
}
}
/* Figure out our color, with lighting if needed */
tmpcolor.setColor(c);
if(lightlevel < 15) {
shadowColor(tmpcolor, lightlevel);
}
if(daycolor != null) {
if(lightlevel_day == lightlevel) {
tmpdaycolor.setColor(tmpcolor);
}
else {
tmpdaycolor.setColor(c);
if(lightlevel_day < 15) {
shadowColor(tmpdaycolor, lightlevel_day);
}
}
}
/* Blend color with accumulated color (weighted by alpha) */ /* Blend color with accumulated color (weighted by alpha) */
if(!transparency) { /* No transparency support */ if(!transparency) { /* No transparency support */
color.setARGB(tmpcolor.getARGB() | 0xFF000000); for(i = 0; i < color.length; i++)
if(daycolor != null) color[i].setARGB(tmpcolor[i].getARGB() | 0xFF000000);
daycolor.setARGB(tmpdaycolor.getARGB() | 0xFF000000);
return true; /* We're done */ return true; /* We're done */
} }
/* If no previous color contribution, use new color */ /* If no previous color contribution, use new color */
else if(color.isTransparent()) { else if(color[0].isTransparent()) {
color.setColor(tmpcolor); for(i = 0; i < color.length; i++)
if(daycolor != null) color[i].setColor(tmpcolor[i]);
daycolor.setColor(tmpdaycolor); return (color[0].getAlpha() == 255);
return (color.getAlpha() == 255);
} }
/* Else, blend and generate new alpha */ /* Else, blend and generate new alpha */
else { else {
int alpha = color.getAlpha(); int alpha = color[0].getAlpha();
int alpha2 = tmpcolor.getAlpha() * (255-alpha) / 255; int alpha2 = tmpcolor[0].getAlpha() * (255-alpha) / 255;
int talpha = alpha + alpha2; int talpha = alpha + alpha2;
color.setRGBA((tmpcolor.getRed()*alpha2 + color.getRed()*alpha) / talpha, for(i = 0; i < color.length; i++)
(tmpcolor.getGreen()*alpha2 + color.getGreen()*alpha) / talpha, color[i].setRGBA((tmpcolor[i].getRed()*alpha2 + color[i].getRed()*alpha) / talpha,
(tmpcolor.getBlue()*alpha2 + color.getBlue()*alpha) / talpha, talpha); (tmpcolor[i].getGreen()*alpha2 + color[i].getGreen()*alpha) / talpha,
if(daycolor != null) (tmpcolor[i].getBlue()*alpha2 + color[i].getBlue()*alpha) / talpha, talpha);
daycolor.setRGBA((tmpdaycolor.getRed()*alpha2 + daycolor.getRed()*alpha) / talpha,
(tmpdaycolor.getGreen()*alpha2 + daycolor.getGreen()*alpha) / talpha,
(tmpdaycolor.getBlue()*alpha2 + daycolor.getBlue()*alpha) / talpha, talpha);
return (talpha >= 254); /* If only one short, no meaningful contribution left */ return (talpha >= 254); /* If only one short, no meaningful contribution left */
} }
} }
@ -226,27 +201,17 @@ public class DefaultHDShader implements HDShader {
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer * @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
*/ */
public void getRayColor(Color c, int index) { public void getRayColor(Color c, int index) {
if(index == 0) c.setColor(color[index]);
c.setColor(color);
else if((index == 1) && (daycolor != null))
c.setColor(daycolor);
} }
/** /**
* Clean up state object - called after last ray completed * Clean up state object - called after last ray completed
*/ */
public void cleanup() { public void cleanup() {
} }
private final void shadowColor(Color c, int lightlevel) {
int scale = shadowscale[lightlevel];
if(scale < 256)
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
(c.getBlue() * scale) >> 8, c.getAlpha());
}
} }
private class OurBiomeRendererState extends OurRendererState { private class OurBiomeShaderState extends OurShaderState {
private OurBiomeRendererState(MapIterator mapiter, HDMap map) { private OurBiomeShaderState(MapIterator mapiter, HDMap map) {
super(mapiter, map); super(mapiter, map);
} }
protected Color[] getBlockColors(int blocktype, int blockdata) { protected Color[] getBlockColors(int blocktype, int blockdata) {
@ -257,8 +222,8 @@ public class DefaultHDShader implements HDShader {
} }
} }
private class OurBiomeRainfallRendererState extends OurRendererState { private class OurBiomeRainfallShaderState extends OurShaderState {
private OurBiomeRainfallRendererState(MapIterator mapiter, HDMap map) { private OurBiomeRainfallShaderState(MapIterator mapiter, HDMap map) {
super(mapiter, map); super(mapiter, map);
} }
protected Color[] getBlockColors(int blocktype, int blockdata) { protected Color[] getBlockColors(int blocktype, int blockdata) {
@ -266,8 +231,8 @@ public class DefaultHDShader implements HDShader {
} }
} }
private class OurBiomeTempRendererState extends OurRendererState { private class OurBiomeTempShaderState extends OurShaderState {
private OurBiomeTempRendererState(MapIterator mapiter, HDMap map) { private OurBiomeTempShaderState(MapIterator mapiter, HDMap map) {
super(mapiter, map); super(mapiter, map);
} }
protected Color[] getBlockColors(int blocktype, int blockdata) { protected Color[] getBlockColors(int blocktype, int blockdata) {
@ -284,13 +249,13 @@ public class DefaultHDShader implements HDShader {
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) { public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter) {
switch(biomecolored) { switch(biomecolored) {
case NONE: case NONE:
return new OurRendererState(mapiter, map); return new OurShaderState(mapiter, map);
case BIOME: case BIOME:
return new OurBiomeRendererState(mapiter, map); return new OurBiomeShaderState(mapiter, map);
case RAINFALL: case RAINFALL:
return new OurBiomeRainfallRendererState(mapiter, map); return new OurBiomeRainfallShaderState(mapiter, map);
case TEMPERATURE: case TEMPERATURE:
return new OurBiomeTempRendererState(mapiter, map); return new OurBiomeTempShaderState(mapiter, map);
} }
return null; return null;
} }
@ -298,6 +263,5 @@ public class DefaultHDShader implements HDShader {
/* Add shader's contributions to JSON for map object */ /* Add shader's contributions to JSON for map object */
public void addClientConfiguration(JSONObject mapObject) { public void addClientConfiguration(JSONObject mapObject) {
s(mapObject, "shader", name); s(mapObject, "shader", name);
s(mapObject, "nightandday", night_and_day);
} }
} }

View file

@ -0,0 +1,29 @@
package org.dynmap.hdmap;
import org.dynmap.Color;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.MapIterator;
import org.json.simple.JSONObject;
public interface HDLighting {
/* Get lighting name */
String getName();
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor);
/* Test if Biome Data is needed for this renderer */
boolean isBiomeDataNeeded();
/* Test if raw biome temperature/rainfall data is needed */
boolean isRawBiomeDataNeeded();
/* Test if highest block Y data is needed */
boolean isHightestBlockYDataNeeded();
/* Tet if block type data needed */
boolean isBlockTypeDataNeeded();
/* Test if night/day is enabled for this renderer */
boolean isNightAndDayEnabled();
/* Test if sky light level needed */
boolean isSkyLightLevelNeeded();
/* Test if emitted light level needed */
boolean isEmittedLightLevelNeeded();
/* Add shader's contributions to JSON for map object */
void addClientConfiguration(JSONObject mapObject);
}

View file

@ -21,6 +21,7 @@ public class HDMap extends MapType {
private String prefix; private String prefix;
private HDPerspective perspective; private HDPerspective perspective;
private HDShader shader; private HDShader shader;
private HDLighting lighting;
private ConfigurationNode configuration; private ConfigurationNode configuration;
public HDMap(ConfigurationNode configuration) { public HDMap(ConfigurationNode configuration) {
@ -43,12 +44,20 @@ public class HDMap extends MapType {
name = null; name = null;
return; return;
} }
String lightingid = configuration.getString("lighting", "default");
lighting = MapManager.mapman.hdmapman.lightings.get(lightingid);
if(lighting == null) {
Log.severe("HDMap '"+name+"' loading invalid lighting '" + lighting + "' - map disabled");
name = null;
return;
}
prefix = configuration.getString("prefix", name); prefix = configuration.getString("prefix", name);
this.configuration = configuration; this.configuration = configuration;
} }
public HDShader getShader() { return shader; } public HDShader getShader() { return shader; }
public HDPerspective getPerspective() { return perspective; } public HDPerspective getPerspective() { return perspective; }
public HDLighting getLighting() { return lighting; }
@Override @Override
public MapTile[] getTiles(Location loc) { public MapTile[] getTiles(Location loc) {
@ -77,7 +86,7 @@ public class HDMap extends MapType {
public List<String> baseZoomFilePrefixes() { public List<String> baseZoomFilePrefixes() {
ArrayList<String> s = new ArrayList<String>(); ArrayList<String> s = new ArrayList<String>();
s.add(prefix); s.add(prefix);
if(shader.isNightAndDayEnabled()) if(lighting.isNightAndDayEnabled())
s.add(prefix + "_day"); s.add(prefix + "_day");
return s; return s;
} }
@ -117,6 +126,7 @@ public class HDMap extends MapType {
perspective.addClientConfiguration(o); perspective.addClientConfiguration(o);
shader.addClientConfiguration(o); shader.addClientConfiguration(o);
lighting.addClientConfiguration(o);
a(worldObject, "maps", o); a(worldObject, "maps", o);

View file

@ -20,16 +20,20 @@ import org.dynmap.utils.MapIterator;
public class HDMapManager { public class HDMapManager {
public HashMap<String, HDShader> shaders = new HashMap<String, HDShader>(); public HashMap<String, HDShader> shaders = new HashMap<String, HDShader>();
public HashMap<String, HDPerspective> perspectives = new HashMap<String, HDPerspective>(); public HashMap<String, HDPerspective> perspectives = new HashMap<String, HDPerspective>();
public HashMap<String, HDLighting> lightings = new HashMap<String, HDLighting>();
public HashSet<HDMap> maps = new HashSet<HDMap>(); public HashSet<HDMap> maps = new HashSet<HDMap>();
public HashMap<String, ArrayList<HDMap>> maps_by_world_perspective = new HashMap<String, ArrayList<HDMap>>(); public HashMap<String, ArrayList<HDMap>> maps_by_world_perspective = new HashMap<String, ArrayList<HDMap>>();
public void loadHDShaders(ConfigurationNode shadercfg) { public void loadHDShaders(ConfigurationNode shadercfg) {
Log.verboseinfo("Loading shaders..."); Log.verboseinfo("Loading shaders...");
for(HDShader shader : shadercfg.<HDShader>createInstances("shaders", new Class<?>[0], new Object[0])) { for(HDShader shader : shadercfg.<HDShader>createInstances("shaders", new Class<?>[0], new Object[0])) {
if(shader.getName() == null) continue;
if(shaders.containsKey(shader.getName())) { if(shaders.containsKey(shader.getName())) {
Log.severe("Duplicate shader name '" + shader.getName() + "' - shader ignored"); Log.severe("Duplicate shader name '" + shader.getName() + "' - shader ignored");
} }
shaders.put(shader.getName(), shader); else {
shaders.put(shader.getName(), shader);
}
} }
Log.info("Loaded " + shaders.size() + " shaders."); Log.info("Loaded " + shaders.size() + " shaders.");
} }
@ -37,14 +41,31 @@ public class HDMapManager {
public void loadHDPerspectives(ConfigurationNode perspectivecfg) { public void loadHDPerspectives(ConfigurationNode perspectivecfg) {
Log.verboseinfo("Loading perspectives..."); Log.verboseinfo("Loading perspectives...");
for(HDPerspective perspective : perspectivecfg.<HDPerspective>createInstances("perspectives", new Class<?>[0], new Object[0])) { for(HDPerspective perspective : perspectivecfg.<HDPerspective>createInstances("perspectives", new Class<?>[0], new Object[0])) {
if(perspective.getName() == null) continue;
if(perspectives.containsKey(perspective.getName())) { if(perspectives.containsKey(perspective.getName())) {
Log.severe("Duplicate perspective name '" + perspective.getName() + "' - perspective ignored"); Log.severe("Duplicate perspective name '" + perspective.getName() + "' - perspective ignored");
} }
perspectives.put(perspective.getName(), perspective); else {
perspectives.put(perspective.getName(), perspective);
}
} }
Log.info("Loaded " + perspectives.size() + " perspectives."); Log.info("Loaded " + perspectives.size() + " perspectives.");
} }
public void loadHDLightings(ConfigurationNode lightingcfg) {
Log.verboseinfo("Loading lightings...");
for(HDLighting lighting : lightingcfg.<HDLighting>createInstances("lightings", new Class<?>[0], new Object[0])) {
if(lighting.getName() == null) continue;
if(lightings.containsKey(lighting.getName())) {
Log.severe("Duplicate lighting name '" + lighting.getName() + "' - lighting ignored");
}
else {
lightings.put(lighting.getName(), lighting);
}
}
Log.info("Loaded " + lightings.size() + " lightings.");
}
/** /**
* Initialize shader states for all shaders for given tile * Initialize shader states for all shaders for given tile
*/ */
@ -102,10 +123,11 @@ public class HDMapManager {
HDMap hdmap = (HDMap)map; HDMap hdmap = (HDMap)map;
if(hdmap.getPerspective() == t.perspective) { if(hdmap.getPerspective() == t.perspective) {
HDShader sh = hdmap.getShader(); HDShader sh = hdmap.getShader();
flags[BIOMEDATAFLAG] |= sh.isBiomeDataNeeded(); HDLighting lt = hdmap.getLighting();
flags[HIGHESTZFLAG] |= sh.isHightestBlockYDataNeeded(); flags[BIOMEDATAFLAG] |= sh.isBiomeDataNeeded() | lt.isBiomeDataNeeded();
flags[RAWBIOMEFLAG] |= sh.isRawBiomeDataNeeded(); flags[HIGHESTZFLAG] |= sh.isHightestBlockYDataNeeded() | lt.isHightestBlockYDataNeeded();
flags[BLOCKTYPEFLAG] |= sh.isBlockTypeDataNeeded(); flags[RAWBIOMEFLAG] |= sh.isRawBiomeDataNeeded() | lt.isRawBiomeDataNeeded();
flags[BLOCKTYPEFLAG] |= sh.isBlockTypeDataNeeded() | lt.isBlockTypeDataNeeded();
} }
} }
} }

View file

@ -8,7 +8,7 @@ import org.dynmap.utils.MapIterator;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
public interface HDShader { public interface HDShader {
/* Get renderer name */ /* Get shader name */
String getName(); String getName();
/** /**
* Get renderer state object for use rendering a tile * Get renderer state object for use rendering a tile
@ -26,8 +26,6 @@ public interface HDShader {
boolean isHightestBlockYDataNeeded(); boolean isHightestBlockYDataNeeded();
/* Tet if block type data needed */ /* Tet if block type data needed */
boolean isBlockTypeDataNeeded(); boolean isBlockTypeDataNeeded();
/* Test if night/day is enabled for this renderer */
boolean isNightAndDayEnabled();
/* Test if sky light level needed */ /* Test if sky light level needed */
boolean isSkyLightLevelNeeded(); boolean isSkyLightLevelNeeded();
/* Test if emitted light level needed */ /* Test if emitted light level needed */

View file

@ -12,6 +12,10 @@ public interface HDShaderState {
* Get our shader * Get our shader
*/ */
HDShader getShader(); HDShader getShader();
/**
* Get our lighting
*/
HDLighting getLighting();
/** /**
* Get our map * Get our map
*/ */

View file

@ -363,13 +363,14 @@ public class IsoHDPerspective implements HDPerspective {
for(int i = 0; i < numshaders; i++) { for(int i = 0; i < numshaders; i++) {
HDShader shader = shaderstate[i].getShader(); HDShader shader = shaderstate[i].getShader();
if(shader.isEmittedLightLevelNeeded()) HDLighting lighting = shaderstate[i].getLighting();
if(shader.isEmittedLightLevelNeeded() || lighting.isEmittedLightLevelNeeded())
need_emittedlightlevel = true; need_emittedlightlevel = true;
if(shader.isSkyLightLevelNeeded()) if(shader.isSkyLightLevelNeeded() || lighting.isSkyLightLevelNeeded())
need_skylightlevel = true; need_skylightlevel = true;
im[i] = KzedMap.allocateBufferedImage(tileWidth, tileHeight); im[i] = KzedMap.allocateBufferedImage(tileWidth, tileHeight);
argb_buf[i] = im[i].argb_buf; argb_buf[i] = im[i].argb_buf;
if(shader.isNightAndDayEnabled()) { if(lighting.isNightAndDayEnabled()) {
dayim[i] = KzedMap.allocateBufferedImage(tileWidth, tileHeight); dayim[i] = KzedMap.allocateBufferedImage(tileWidth, tileHeight);
day_argb_buf[i] = dayim[i].argb_buf; day_argb_buf[i] = dayim[i].argb_buf;
} }

View file

@ -0,0 +1,99 @@
package org.dynmap.hdmap;
import static org.dynmap.JSONUtils.s;
import org.dynmap.Color;
import org.dynmap.ConfigurationNode;
import org.dynmap.Log;
import org.json.simple.JSONObject;
public class ShadowHDLighting extends DefaultHDLighting {
protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */
protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */
protected boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
public ShadowHDLighting(ConfigurationNode configuration) {
super(configuration);
double shadowweight = configuration.getDouble("shadowstrength", 0.0);
if(shadowweight > 0.0) {
shadowscale = new int[16];
shadowscale[15] = 256;
/* Normal brightness weight in MC is a 20% relative dropoff per step */
for(int i = 14; i >= 0; i--) {
double v = shadowscale[i+1] * (1.0 - (0.2 * shadowweight));
shadowscale[i] = (int)v;
if(shadowscale[i] > 256) shadowscale[i] = 256;
if(shadowscale[i] < 0) shadowscale[i] = 0;
}
}
int v = configuration.getInteger("ambientlight", -1);
if((v >= 0) && (v < 15)) {
lightscale = new int[16];
for(int i = 0; i < 16; i++) {
if(i < (15-v))
lightscale[i] = 0;
else
lightscale[i] = i - (15-v);
}
}
night_and_day = configuration.getBoolean("night-and-day", false);
if(night_and_day) {
if(lightscale == null) {
Log.severe("night-and-day in lighting '" + getName() + "' requires ambientlight<15");
night_and_day = false;
}
}
}
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
int lightlevel = 15, lightlevel_day = 15;
/* If processing for shadows, use sky light level as base lighting */
if(shadowscale != null) {
lightlevel = lightlevel_day = ps.getSkyLightLevel();
}
/* If ambient light, adjust base lighting for it */
if(lightscale != null)
lightlevel = lightscale[lightlevel];
/* If we're below max, see if emitted light helps */
if((lightlevel < 15) || (lightlevel_day < 15)) {
int emitted = ps.getEmittedLightLevel();
lightlevel = Math.max(emitted, lightlevel);
lightlevel_day = Math.max(emitted, lightlevel_day);
}
/* Figure out our color, with lighting if needed */
outcolor[0].setColor(incolor);
if(lightlevel < 15) {
shadowColor(outcolor[0], lightlevel);
}
if(outcolor.length > 1) {
if(lightlevel_day == lightlevel) {
outcolor[1].setColor(outcolor[0]);
}
else {
outcolor[1].setColor(incolor);
if(lightlevel_day < 15) {
shadowColor(outcolor[1], lightlevel_day);
}
}
}
}
private final void shadowColor(Color c, int lightlevel) {
int scale = shadowscale[lightlevel];
if(scale < 256)
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
(c.getBlue() * scale) >> 8, c.getAlpha());
}
/* Test if night/day is enabled for this renderer */
public boolean isNightAndDayEnabled() { return night_and_day; }
/* Test if sky light level needed */
public boolean isSkyLightLevelNeeded() { return (shadowscale != null); }
/* Test if emitted light level needed */
public boolean isEmittedLightLevelNeeded() { return (shadowscale != null) || (lightscale != null); }
}