0

lighting and smooth lighting updated for anvil

This commit is contained in:
Aaron Griffith
2012-02-21 15:51:34 -05:00
parent c5f2077d51
commit 4ac7c1222a
4 changed files with 51 additions and 177 deletions

View File

@@ -26,7 +26,7 @@
// increment this value if you've made a change to the c extesion // increment this value if you've made a change to the c extesion
// and want to force users to rebuild // and want to force users to rebuild
#define OVERVIEWER_EXTENSION_VERSION 23 #define OVERVIEWER_EXTENSION_VERSION 24
/* Python PIL, and numpy headers */ /* Python PIL, and numpy headers */
#include <Python.h> #include <Python.h>
@@ -148,6 +148,10 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
{ {
int chunkx = 1, chunky = state->chunky, chunkz = 1; int chunkx = 1, chunky = state->chunky, chunkz = 1;
PyObject *data_array = NULL; PyObject *data_array = NULL;
unsigned int def = 0;
if (type == SKYLIGHT)
def = 15;
if (x >= 16) { if (x >= 16) {
x -= 16; x -= 16;
chunkx++; chunkx++;
@@ -172,12 +176,12 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
chunky--; chunky--;
} }
if (chunky < 0 || chunky >= SECTIONS_PER_CHUNK) if (chunky < 0 || chunky >= SECTIONS_PER_CHUNK)
return 0; return def;
if (!(state->chunks[chunkx][chunkz].loaded)) if (!(state->chunks[chunkx][chunkz].loaded))
{ {
if (load_chunk(state, chunkx - 1, chunkz - 1, 0)) if (load_chunk(state, chunkx - 1, chunkz - 1, 0))
return 0; return def;
} }
switch (type) switch (type)
@@ -197,7 +201,7 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
}; };
if (data_array == NULL) if (data_array == NULL)
return 0; return def;
if (type == BLOCKS) if (type == BLOCKS)
return getArrayShort3D(data_array, x, y, z); return getArrayShort3D(data_array, x, y, z);

View File

@@ -100,9 +100,6 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
int x, int y, int z, int *authoratative) { int x, int y, int z, int *authoratative) {
/* placeholders for later data arrays, coordinates */ /* placeholders for later data arrays, coordinates */
PyObject *blocks = NULL;
PyObject *blocklight = NULL;
int local_x = x, local_y = y, local_z = z;
unsigned char block, blocklevel; unsigned char block, blocklevel;
unsigned int average_count = 0, average_gather = 0, coeff = 0; unsigned int average_count = 0, average_gather = 0, coeff = 0;
@@ -110,36 +107,7 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
if (authoratative) if (authoratative)
*authoratative = 0; *authoratative = 0;
/* find out what chunk we're in, and translate accordingly */ block = get_data(state, BLOCKS, x, y, z);
if (x >= 0 && y < 16) {
blocks = state->blocks;
blocklight = self->blocklight;
} else if (x < 0) {
local_x += 16;
blocks = state->left_blocks;
blocklight = self->left_blocklight;
} else if (y >= 16) {
local_y -= 16;
blocks = state->right_blocks;
blocklight = self->right_blocklight;
}
/* make sure we have correctly-ranged coordinates */
if (!(local_x >= 0 && local_x < 16 &&
local_y >= 0 && local_y < 16 &&
local_z >= 0 && local_z < 128)) {
return 0;
}
/* also, make sure we have enough info to correctly calculate lighting */
if (blocks == NULL ||
blocklight == NULL) {
return 0;
}
block = getArrayByte3D(blocks, local_x, local_y, local_z);
if (authoratative == NULL) { if (authoratative == NULL) {
int auth; int auth;
@@ -149,16 +117,8 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
for (dx = -1; dx <= 1; dx += 2) { for (dx = -1; dx <= 1; dx += 2) {
for (dy = -1; dy <= 1; dy += 2) { for (dy = -1; dy <= 1; dy += 2) {
for (dz = -1; dz <= 1; dz += 2) { for (dz = -1; dz <= 1; dz += 2) {
/* skip if block is out of range */
if (x+dx < 0 || x+dx >= 16 ||
y+dy < 0 || y+dy >= 16 ||
z+dz < 0 || z+dz >= 128) {
continue;
}
coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth); coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth);
local_block = getArrayByte3D(blocks, x+dx, y+dy, z+dz); local_block = get_data(state, BLOCKS, x+dx, y+dy, z+dz);
/* only add if the block is transparent, this seems to look better than /* only add if the block is transparent, this seems to look better than
using every block */ using every block */
if (auth && is_transparent(local_block)) { if (auth && is_transparent(local_block)) {
@@ -175,7 +135,7 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
return average_gather / average_count; return average_gather / average_count;
} }
blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); blocklevel = get_data(state, BLOCKLIGHT, x, y, z);
/* no longer a guess */ /* no longer a guess */
if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109) && authoratative) { if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109) && authoratative) {
@@ -191,78 +151,26 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state,
unsigned char *r, unsigned char *g, unsigned char *b) { 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 *skylight = NULL;
PyObject *blocklight = NULL;
int local_x = x, local_y = y, local_z = z;
unsigned char block, skylevel, blocklevel; unsigned char block, skylevel, blocklevel;
/* find out what chunk we're in, and translate accordingly */ block = get_data(state, BLOCKS, x, y, z);
if (x >= 0 && x < 16 && y >= 0 && y < 16) { skylevel = get_data(state, SKYLIGHT, x, y, z);
blocks = state->blocks; blocklevel = get_data(state, BLOCKLIGHT, x, y, z);
skylight = self->skylight;
blocklight = self->blocklight;
} else if (x < 0) {
local_x += 16;
blocks = state->left_blocks;
skylight = self->left_skylight;
blocklight = self->left_blocklight;
} else if (y >= 16) {
local_y -= 16;
blocks = state->right_blocks;
skylight = self->right_skylight;
blocklight = self->right_blocklight;
} else if (y < 0) {
local_y += 16;
blocks = state->up_left_blocks;
skylight = self->up_left_skylight;
blocklight = self->up_left_blocklight;
} else if (x >= 16) {
local_x -= 16;
blocks = state->up_right_blocks;
skylight = self->up_right_skylight;
blocklight = self->up_right_blocklight;
}
/* make sure we have correctly-ranged coordinates */
if (!(local_x >= 0 && local_x < 16 &&
local_y >= 0 && local_y < 16 &&
local_z >= 0 && local_z < 128)) {
self->calculate_light_color(self, 15, 0, r, g, b);
return;
}
/* also, make sure we have enough info to correctly calculate lighting */
if (!blocks ||
!skylight ||
!blocklight) {
self->calculate_light_color(self, 15, 0, r, g, b);
return;
}
block = getArrayByte3D(blocks, local_x, local_y, local_z);
skylevel = getArrayByte3D(skylight, local_x, local_y, local_z);
blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z);
/* special half-step handling, stairs handling */ /* special half-step handling, stairs handling */
if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114) { if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114) {
unsigned int upper_block; unsigned int upper_block;
/* stairs and half-blocks take the skylevel from the upper block if it's transparent */ /* stairs and half-blocks take the skylevel from the upper block if it's transparent */
if (local_z != 127) { int upper_counter = 0;
int upper_counter = 0; /* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */
/* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */ do {
do { upper_counter++;
upper_counter++; upper_block = get_data(state, BLOCKS, x, y + upper_counter, z);
upper_block = getArrayByte3D(blocks, local_x, local_y, local_z + upper_counter); } while (upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109 || upper_block == 114);
} while ((upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109) && local_z < 127); if (is_transparent(upper_block)) {
if (is_transparent(upper_block)) { skylevel = get_data(state, SKYLIGHT, x, y + upper_counter, z);
skylevel = getArrayByte3D(skylight, local_x, local_y, local_z + upper_counter);
}
} else { } else {
upper_block = 0;
skylevel = 15; skylevel = 15;
} }
@@ -287,31 +195,22 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state,
inline int inline int
lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z) { lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z) {
/* 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 < 16) {
unsigned char block = getArrayByte3D(state->blocks, x, y, z); unsigned short block = getArrayShort3D(state->blocks, x, y, z);
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) { if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
/* this face isn't visible, so don't draw anything */ /* this face isn't visible, so don't draw anything */
return 1; return 1;
} }
} else if (skip_sides && (x == -1) && (state->left_blocks != NULL)) { } else if (skip_sides) {
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, state->z); unsigned short block = get_data(state, BLOCKS, x, y, z);
if (!is_transparent(block)) { if (!is_transparent(block)) {
/* the same thing but for adjacent chunks, this solves an /* the same thing but for adjacent chunks, this solves an
ugly black doted line between chunks in night rendermode. ugly black doted line between chunks in night rendermode.
This wouldn't be necessary if the textures were truly This wouldn't be necessary if the textures were truly
tessellate-able */ tessellate-able */
return 1; return 1;
} }
} else if (skip_sides && (y == 16) && (state->right_blocks != NULL)) {
unsigned char block = getArrayByte3D(state->right_blocks, state->x, 0, state->z);
if (!is_transparent(block)) {
/* the same thing but for adjacent chunks, this solves an
ugly black doted line between chunks in night rendermode.
This wouldn't be necessary if the textures were truly
tessellate-able */
return 1;
}
} }
return 0; return 0;
} }
@@ -343,8 +242,8 @@ lighting_start(void *data, RenderState *state, PyObject *support) {
RenderPrimitiveLighting* self; RenderPrimitiveLighting* self;
self = (RenderPrimitiveLighting *)data; self = (RenderPrimitiveLighting *)data;
/* don't skip sides by default */ /* skip sides by default */
self->skip_sides = 0; self->skip_sides = 1;
if (!render_mode_parse_option(support, "strength", "f", &(self->strength))) if (!render_mode_parse_option(support, "strength", "f", &(self->strength)))
return 1; return 1;
@@ -359,17 +258,6 @@ lighting_start(void *data, RenderState *state, PyObject *support) {
self->facemasks[1] = PyTuple_GetItem(self->facemasks_py, 1); self->facemasks[1] = PyTuple_GetItem(self->facemasks_py, 1);
self->facemasks[2] = PyTuple_GetItem(self->facemasks_py, 2); self->facemasks[2] = PyTuple_GetItem(self->facemasks_py, 2);
self->skylight = get_chunk_data(state, CURRENT, SKYLIGHT, 1);
self->blocklight = get_chunk_data(state, CURRENT, BLOCKLIGHT, 1);
self->left_skylight = get_chunk_data(state, DOWN_LEFT, SKYLIGHT, 1);
self->left_blocklight = get_chunk_data(state, DOWN_LEFT, BLOCKLIGHT, 1);
self->right_skylight = get_chunk_data(state, DOWN_RIGHT, SKYLIGHT, 1);
self->right_blocklight = get_chunk_data(state, DOWN_RIGHT, BLOCKLIGHT, 1);
self->up_left_skylight = get_chunk_data(state, UP_LEFT, SKYLIGHT, 1);
self->up_left_blocklight = get_chunk_data(state, UP_LEFT, BLOCKLIGHT, 1);
self->up_right_skylight = get_chunk_data(state, UP_RIGHT, SKYLIGHT, 1);
self->up_right_blocklight = get_chunk_data(state, UP_RIGHT, BLOCKLIGHT, 1);
if (self->night) { if (self->night) {
self->calculate_light_color = calculate_light_color_night; self->calculate_light_color = calculate_light_color_night;
} else { } else {
@@ -401,17 +289,6 @@ lighting_finish(void *data, RenderState *state) {
RenderPrimitiveLighting *self = (RenderPrimitiveLighting *)data; RenderPrimitiveLighting *self = (RenderPrimitiveLighting *)data;
Py_DECREF(self->facemasks_py); Py_DECREF(self->facemasks_py);
Py_DECREF(self->skylight);
Py_DECREF(self->blocklight);
Py_XDECREF(self->left_skylight);
Py_XDECREF(self->left_blocklight);
Py_XDECREF(self->right_skylight);
Py_XDECREF(self->right_blocklight);
Py_XDECREF(self->up_left_skylight);
Py_XDECREF(self->up_left_blocklight);
Py_XDECREF(self->up_right_skylight);
Py_XDECREF(self->up_right_blocklight);
} }
static void static void
@@ -427,13 +304,13 @@ lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyO
* blocks that are transparent for occlusion calculations and * blocks that are transparent for occlusion calculations and
* need per-face shading if the face is drawn. */ * need per-face shading if the face is drawn. */
if ((state->block_pdata & 16) == 16) { if ((state->block_pdata & 16) == 16) {
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[0]); do_shading_with_mask(self, state, x, y+1, z, self->facemasks[0]);
} }
if ((state->block_pdata & 2) == 2) { /* bottom left */ if ((state->block_pdata & 2) == 2) { /* bottom left */
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]); do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
} }
if ((state->block_pdata & 4) == 4) { /* bottom right */ if ((state->block_pdata & 4) == 4) { /* bottom right */
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[2]); do_shading_with_mask(self, state, x, y, z+1, self->facemasks[2]);
} }
/* leaves are transparent for occlusion calculations but they /* leaves are transparent for occlusion calculations but they
* per face-shading to look as in game */ * per face-shading to look as in game */
@@ -442,9 +319,9 @@ lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyO
do_shading_with_mask(self, state, x, y, z, mask_light); do_shading_with_mask(self, state, x, y, z, mask_light);
} else { } else {
/* opaque: do per-face shading */ /* opaque: do per-face shading */
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[0]); do_shading_with_mask(self, state, x, y+1, z, self->facemasks[0]);
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]); do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[2]); do_shading_with_mask(self, state, x, y, z+1, self->facemasks[2]);
} }
} }

View File

@@ -21,13 +21,6 @@ typedef struct {
PyObject *facemasks_py; PyObject *facemasks_py;
PyObject *facemasks[3]; PyObject *facemasks[3];
/* extra data, loaded off the chunk class */
PyObject *skylight, *blocklight;
PyObject *left_skylight, *left_blocklight;
PyObject *right_skylight, *right_blocklight;
PyObject *up_left_skylight, *up_left_blocklight;
PyObject *up_right_skylight, *up_right_blocklight;
/* light color image, loaded if color_light is True */ /* light color image, loaded if color_light is True */
PyObject *lightcolor; PyObject *lightcolor;

View File

@@ -69,53 +69,53 @@ static struct SmoothLightingFace lighting_rules[] = {
*/ */
/* top */ /* top */
{0, 0, 1, { {0, 1, 0, {
{0, 6, {0, 6,
-1, 0, 0, -1, 0, 0,
0, -1, 0}, 0, 0, -1},
{12, 0, {12, 0,
1, 0, 0, 1, 0, 0,
0, -1, 0}, 0, 0, -1},
{24, 6, {24, 6,
1, 0, 0, 1, 0, 0,
0, 1, 0}, 0, 0, 1},
{12, 12, {12, 12,
-1, 0, 0, -1, 0, 0,
0, 1, 0}, 0, 0, 1},
}, },
top_touchups, 3}, top_touchups, 3},
/* left */ /* left */
{-1, 0, 0, { {-1, 0, 0, {
{0, 18, {0, 18,
0, -1, 0, 0, 0, -1,
0, 0, -1}, 0, -1, 0},
{0, 6, {0, 6,
0, -1, 0, 0, 0, -1,
0, 0, 1}, 0, 1, 0},
{12, 12, {12, 12,
0, 1, 0, 0, 0, 1,
0, 0, 1}, 0, 1, 0},
{12, 24, {12, 24,
0, 1, 0, 0, 0, 1,
0, 0, -1}, 0, -1, 0},
}, },
NULL, 0}, NULL, 0},
/* right */ /* right */
{0, 1, 0, { {0, 0, 1, {
{24, 6, {24, 6,
1, 0, 0, 1, 0, 0,
0, 0, 1}, 0, 1, 0},
{12, 12, {12, 12,
-1, 0, 0, -1, 0, 0,
0, 0, 1}, 0, 1, 0},
{12, 24, {12, 24,
-1, 0, 0, -1, 0, 0,
0, 0, -1}, 0, -1, 0},
{24, 18, {24, 18,
1, 0, 0, 1, 0, 0,
0, 0, -1}, 0, -1, 0},
}, },
NULL, 0}, NULL, 0},
}; };