added 'color_light' option to lighting mode
This commit is contained in:
@@ -18,10 +18,37 @@
|
|||||||
#include "overviewer.h"
|
#include "overviewer.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
/* figures out the black_coeff from a given skylight and blocklight,
|
/* figures out the color from a given skylight and blocklight,
|
||||||
used in lighting calculations */
|
used in lighting calculations */
|
||||||
static float calculate_darkness(unsigned char skylight, unsigned char blocklight) {
|
static void
|
||||||
return 1.0f - powf(0.8f, 15.0 - MAX(blocklight, skylight));
|
calculate_light_color(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
unsigned char v = 255 * powf(0.8f, 15.0 - MAX(blocklight, skylight));
|
||||||
|
*r = v;
|
||||||
|
*g = v;
|
||||||
|
*b = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fancy version that uses the colored light texture */
|
||||||
|
static void
|
||||||
|
calculate_light_color_fancy(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
RenderModeLighting *mode = (RenderModeLighting *)(data);
|
||||||
|
unsigned int index;
|
||||||
|
PyObject *color;
|
||||||
|
|
||||||
|
blocklight = MAX(blocklight, skylight);
|
||||||
|
|
||||||
|
index = skylight + blocklight * 16;
|
||||||
|
color = PySequence_GetItem(mode->lightcolor, index);
|
||||||
|
|
||||||
|
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
|
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
|
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
|
|
||||||
|
Py_DECREF(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loads the appropriate light data for the given (possibly non-local)
|
/* loads the appropriate light data for the given (possibly non-local)
|
||||||
@@ -124,9 +151,10 @@ estimate_blocklevel(RenderModeLighting *self, RenderState *state,
|
|||||||
return blocklevel;
|
return blocklevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float
|
inline void
|
||||||
get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
get_lighting_color(RenderModeLighting *self, RenderState *state,
|
||||||
int x, int y, int z) {
|
int x, int y, int z,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
|
||||||
/* placeholders for later data arrays, coordinates */
|
/* placeholders for later data arrays, coordinates */
|
||||||
PyObject *blocks = NULL;
|
PyObject *blocks = NULL;
|
||||||
@@ -157,7 +185,8 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
|||||||
local_y >= 0 && local_y < 16 &&
|
local_y >= 0 && local_y < 16 &&
|
||||||
local_z >= 0 && local_z < 128)) {
|
local_z >= 0 && local_z < 128)) {
|
||||||
|
|
||||||
return self->calculate_darkness(15, 0);
|
self->calculate_light_color(self, 15, 0, r, g, b);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* also, make sure we have enough info to correctly calculate lighting */
|
/* also, make sure we have enough info to correctly calculate lighting */
|
||||||
@@ -165,7 +194,8 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
|||||||
skylight == Py_None || skylight == NULL ||
|
skylight == Py_None || skylight == NULL ||
|
||||||
blocklight == Py_None || blocklight == NULL) {
|
blocklight == Py_None || blocklight == NULL) {
|
||||||
|
|
||||||
return self->calculate_darkness(15, 0);
|
self->calculate_light_color(self, 15, 0, r, g, b);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = getArrayByte3D(blocks, local_x, local_y, local_z);
|
block = getArrayByte3D(blocks, local_x, local_y, local_z);
|
||||||
@@ -203,15 +233,16 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self->calculate_darkness(skylevel, blocklevel);
|
self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shades the drawn block with the given facemask/black_color, based on the
|
/* shades the drawn block with the given facemask, based on the
|
||||||
lighting results from (x, y, z) */
|
lighting results from (x, y, z) */
|
||||||
static inline void
|
static inline void
|
||||||
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
||||||
int x, int y, int z, PyObject *mask) {
|
int x, int y, int z, PyObject *mask) {
|
||||||
float black_coeff;
|
unsigned char r, g, b;
|
||||||
|
float comp_shade_strength;
|
||||||
|
|
||||||
/* first, check for occlusion if the block is in the local chunk */
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
||||||
@@ -241,9 +272,14 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
black_coeff = get_lighting_coefficient(self, state, x, y, z);
|
get_lighting_color(self, state, x, y, z, &r, &g, &b);
|
||||||
black_coeff *= self->shade_strength;
|
comp_shade_strength = 1.0 - self->shade_strength;
|
||||||
alpha_over_full(state->img, self->black_color, mask, black_coeff, state->imgx, state->imgy, 0, 0);
|
|
||||||
|
r += (255 - r) * comp_shade_strength;
|
||||||
|
g += (255 - g) * comp_shade_strength;
|
||||||
|
b += (255 - b) * comp_shade_strength;
|
||||||
|
|
||||||
|
tint_with_mask(state->img, r, g, b, 255, mask, state->imgx, state->imgy, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -264,7 +300,10 @@ rendermode_lighting_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
if (!render_mode_parse_option(options, "shade_strength", "f", &(self->shade_strength)))
|
if (!render_mode_parse_option(options, "shade_strength", "f", &(self->shade_strength)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
self->black_color = PyObject_GetAttrString(state->chunk, "black_color");
|
self->color_light = 0;
|
||||||
|
if (!render_mode_parse_option(options, "color_light", "i", &(self->color_light)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
self->facemasks_py = PyObject_GetAttrString(state->chunk, "facemasks");
|
self->facemasks_py = PyObject_GetAttrString(state->chunk, "facemasks");
|
||||||
// borrowed references, don't need to be decref'd
|
// borrowed references, don't need to be decref'd
|
||||||
self->facemasks[0] = PyTuple_GetItem(self->facemasks_py, 0);
|
self->facemasks[0] = PyTuple_GetItem(self->facemasks_py, 0);
|
||||||
@@ -278,7 +317,20 @@ rendermode_lighting_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
self->right_skylight = PyObject_GetAttrString(state->self, "right_skylight");
|
self->right_skylight = PyObject_GetAttrString(state->self, "right_skylight");
|
||||||
self->right_blocklight = PyObject_GetAttrString(state->self, "right_blocklight");
|
self->right_blocklight = PyObject_GetAttrString(state->self, "right_blocklight");
|
||||||
|
|
||||||
self->calculate_darkness = calculate_darkness;
|
self->calculate_light_color = calculate_light_color;
|
||||||
|
|
||||||
|
if (self->color_light) {
|
||||||
|
self->lightcolor = PyObject_CallMethod(state->textures, "loadLightColor", "");
|
||||||
|
if (self->lightcolor == Py_None) {
|
||||||
|
Py_DECREF(self->lightcolor);
|
||||||
|
self->lightcolor = NULL;
|
||||||
|
self->color_light = 0;
|
||||||
|
} else {
|
||||||
|
self->calculate_light_color = calculate_light_color_fancy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self->lightcolor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -287,7 +339,6 @@ static void
|
|||||||
rendermode_lighting_finish(void *data, RenderState *state) {
|
rendermode_lighting_finish(void *data, RenderState *state) {
|
||||||
RenderModeLighting *self = (RenderModeLighting *)data;
|
RenderModeLighting *self = (RenderModeLighting *)data;
|
||||||
|
|
||||||
Py_DECREF(self->black_color);
|
|
||||||
Py_DECREF(self->facemasks_py);
|
Py_DECREF(self->facemasks_py);
|
||||||
|
|
||||||
Py_DECREF(self->skylight);
|
Py_DECREF(self->skylight);
|
||||||
@@ -352,6 +403,7 @@ rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject
|
|||||||
|
|
||||||
const RenderModeOption rendermode_lighting_options[] = {
|
const RenderModeOption rendermode_lighting_options[] = {
|
||||||
{"shade_strength", "how dark to make the shadows, from 0.0 to 1.0 (default: 1.0)"},
|
{"shade_strength", "how dark to make the shadows, from 0.0 to 1.0 (default: 1.0)"},
|
||||||
|
{"color_light", "whether to use colored light (default: False)"},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,36 @@
|
|||||||
#include "overviewer.h"
|
#include "overviewer.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
/* figures out the black_coeff from a given skylight and blocklight, used in
|
/* figures out the color from a given skylight and blocklight, used in
|
||||||
lighting calculations -- note this is *different* from the one in
|
lighting calculations -- note this is *different* from the one in
|
||||||
rendermode-lighting.c (the "skylight - 11" part) */
|
rendermode-lighting.c (the "skylight - 11" part) */
|
||||||
static float calculate_darkness(unsigned char skylight, unsigned char blocklight) {
|
static void
|
||||||
return 1.0f - powf(0.8f, 15.0 - MAX(blocklight, skylight - 11));
|
calculate_light_color(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
unsigned char v = 255 * powf(0.8f, 15.0 - MAX(blocklight, skylight - 11));
|
||||||
|
*r = v;
|
||||||
|
*g = v;
|
||||||
|
*b = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fancy version that uses the colored light texture */
|
||||||
|
static void
|
||||||
|
calculate_light_color_fancy(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
RenderModeLighting *mode = (RenderModeLighting *)(data);
|
||||||
|
unsigned int index;
|
||||||
|
PyObject *color;
|
||||||
|
|
||||||
|
index = skylight + blocklight * 16;
|
||||||
|
color = PySequence_GetItem(mode->lightcolor, index);
|
||||||
|
|
||||||
|
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
|
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
|
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
|
|
||||||
|
Py_DECREF(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -36,7 +61,9 @@ rendermode_night_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
|
|
||||||
/* override the darkness function with our night version! */
|
/* override the darkness function with our night version! */
|
||||||
self = (RenderModeNight *)data;
|
self = (RenderModeNight *)data;
|
||||||
self->parent.calculate_darkness = calculate_darkness;
|
self->parent.calculate_light_color = calculate_light_color;
|
||||||
|
if (self->parent.color_light)
|
||||||
|
self->parent.calculate_light_color = calculate_light_color_fancy;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ typedef struct {
|
|||||||
/* inherits from normal render mode */
|
/* inherits from normal render mode */
|
||||||
RenderModeNormal parent;
|
RenderModeNormal parent;
|
||||||
|
|
||||||
PyObject *black_color, *facemasks_py;
|
PyObject *facemasks_py;
|
||||||
PyObject *facemasks[3];
|
PyObject *facemasks[3];
|
||||||
|
|
||||||
/* extra data, loaded off the chunk class */
|
/* extra data, loaded off the chunk class */
|
||||||
@@ -166,9 +166,12 @@ typedef struct {
|
|||||||
PyObject *left_skylight, *left_blocklight;
|
PyObject *left_skylight, *left_blocklight;
|
||||||
PyObject *right_skylight, *right_blocklight;
|
PyObject *right_skylight, *right_blocklight;
|
||||||
|
|
||||||
|
/* light color image, loaded if color_light is True */
|
||||||
|
PyObject *lightcolor;
|
||||||
|
|
||||||
/* can be overridden in derived rendermodes to control lighting
|
/* can be overridden in derived rendermodes to control lighting
|
||||||
arguments are skylight, blocklight */
|
arguments are data, skylight, blocklight, return RGB */
|
||||||
float (*calculate_darkness)(unsigned char, unsigned char);
|
void (*calculate_light_color)(void *, unsigned char, unsigned char, unsigned char *, unsigned char *, unsigned char *);
|
||||||
|
|
||||||
/* can be set to 0 in derived modes to indicate that lighting the chunk
|
/* can be set to 0 in derived modes to indicate that lighting the chunk
|
||||||
* sides is actually important. Right now, this is used in cave mode
|
* sides is actually important. Right now, this is used in cave mode
|
||||||
@@ -176,6 +179,7 @@ typedef struct {
|
|||||||
int skip_sides;
|
int skip_sides;
|
||||||
|
|
||||||
float shade_strength;
|
float shade_strength;
|
||||||
|
int color_light;
|
||||||
} RenderModeLighting;
|
} RenderModeLighting;
|
||||||
extern RenderModeInterface rendermode_lighting;
|
extern RenderModeInterface rendermode_lighting;
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ def _find_file(filename, mode="rb", verbose=False):
|
|||||||
for jarpath in jarpaths:
|
for jarpath in jarpaths:
|
||||||
if os.path.exists(jarpath):
|
if os.path.exists(jarpath):
|
||||||
jar = zipfile.ZipFile(jarpath)
|
jar = zipfile.ZipFile(jarpath)
|
||||||
for jarfilename in [filename, 'misc/' + filename]:
|
for jarfilename in [filename, 'misc/' + filename, 'environment/' + filename]:
|
||||||
try:
|
try:
|
||||||
if verbose: logging.info("Found %s in '%s'", jarfilename, jarpath)
|
if verbose: logging.info("Found %s in '%s'", jarfilename, jarpath)
|
||||||
return jar.open(jarfilename)
|
return jar.open(jarfilename)
|
||||||
@@ -2278,6 +2278,20 @@ def getBiomeData(worlddir, chunkX, chunkY):
|
|||||||
currentBiomeData = data
|
currentBiomeData = data
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
lightcolor = None
|
||||||
|
lightcolor_checked = False
|
||||||
|
def loadLightColor():
|
||||||
|
global lightcolor, lightcolor_checked
|
||||||
|
|
||||||
|
if not lightcolor_checked:
|
||||||
|
lightcolor_checked = True
|
||||||
|
try:
|
||||||
|
lightcolor = list(_load_image("light_normal.png").getdata())
|
||||||
|
except:
|
||||||
|
logging.warning("Light color image could not be found.")
|
||||||
|
lightcolor = None
|
||||||
|
return lightcolor
|
||||||
|
|
||||||
# This set holds block ids that require special pre-computing. These are typically
|
# This set holds block ids that require special pre-computing. These are typically
|
||||||
# things that require ancillary data to render properly (i.e. ladder plus orientation)
|
# things that require ancillary data to render properly (i.e. ladder plus orientation)
|
||||||
# A good source of information is:
|
# A good source of information is:
|
||||||
|
|||||||
Reference in New Issue
Block a user