smooth-lighting triangles now pull lighting data correctly for each vertex
This commit is contained in:
@@ -369,7 +369,7 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
|||||||
* http://www.gidforums.com/t-20838.html )
|
* http://www.gidforums.com/t-20838.html )
|
||||||
*/
|
*/
|
||||||
PyObject *
|
PyObject *
|
||||||
draw_triangle(PyObject *dest,
|
draw_triangle(PyObject *dest, int inclusive,
|
||||||
int x0, int y0,
|
int x0, int y0,
|
||||||
unsigned char r0, unsigned char g0, unsigned char b0,
|
unsigned char r0, unsigned char g0, unsigned char b0,
|
||||||
int x1, int y1,
|
int x1, int y1,
|
||||||
@@ -433,7 +433,8 @@ draw_triangle(PyObject *dest,
|
|||||||
beta = beta_norm * ((a20 * x) + (b20 * y) + c20);
|
beta = beta_norm * ((a20 * x) + (b20 * y) + c20);
|
||||||
gamma = gamma_norm * ((a01 * x) + (b01 * y) + c01);
|
gamma = gamma_norm * ((a01 * x) + (b01 * y) + c01);
|
||||||
|
|
||||||
if (alpha >= 0 && beta >= 0 && gamma >= 0) {
|
if (alpha >= 0 && beta >= 0 && gamma >= 0 &&
|
||||||
|
(inclusive || (alpha * beta * gamma > 0))) {
|
||||||
unsigned int r = alpha * r0 + beta * r1 + gamma * r2;
|
unsigned int r = alpha * r0 + beta * r1 + gamma * r2;
|
||||||
unsigned int g = alpha * g0 + beta * g1 + gamma * g2;
|
unsigned int g = alpha * g0 + beta * g1 + gamma * g2;
|
||||||
unsigned int b = alpha * b0 + beta * b1 + gamma * b2;
|
unsigned int b = alpha * b0 + beta * b1 + gamma * b2;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
|||||||
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||||
unsigned char sb, unsigned char sa,
|
unsigned char sb, unsigned char sa,
|
||||||
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
||||||
PyObject *draw_triangle(PyObject *dest,
|
PyObject *draw_triangle(PyObject *dest, int inclusive,
|
||||||
int x0, int y0,
|
int x0, int y0,
|
||||||
unsigned char r0, unsigned char g0, unsigned char b0,
|
unsigned char r0, unsigned char g0, unsigned char b0,
|
||||||
int x1, int y1,
|
int x1, int y1,
|
||||||
|
|||||||
@@ -236,6 +236,39 @@ get_lighting_color(RenderModeLighting *self, RenderState *state,
|
|||||||
self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b);
|
self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* does per-face occlusion checking for do_shading_with_mask */
|
||||||
|
inline int
|
||||||
|
rendermode_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 */
|
||||||
|
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
||||||
|
unsigned char block = getArrayByte3D(state->blocks, 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 */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (skip_sides && (x == -1) && (state->left_blocks != Py_None)) {
|
||||||
|
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, 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;
|
||||||
|
}
|
||||||
|
} else if (skip_sides && (y == 16) && (state->right_blocks != Py_None)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* shades the drawn block with the given facemask, 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
|
||||||
@@ -244,33 +277,9 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
|||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
float comp_shade_strength;
|
float comp_shade_strength;
|
||||||
|
|
||||||
/* first, check for occlusion if the block is in the local chunk */
|
/* check occlusion */
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
if (rendermode_lighting_is_face_occluded(state, self->skip_sides, x, y, z))
|
||||||
unsigned char block = getArrayByte3D(state->blocks, x, y, z);
|
return;
|
||||||
|
|
||||||
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
|
|
||||||
/* this face isn't visible, so don't draw anything */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (self->skip_sides && (x == -1) && (state->left_blocks != Py_None)) {
|
|
||||||
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, 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;
|
|
||||||
}
|
|
||||||
} else if (self->skip_sides && (y == 16) && (state->right_blocks != Py_None)) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_lighting_color(self, state, x, y, z, &r, &g, &b);
|
get_lighting_color(self, state, x, y, z, &r, &g, &b);
|
||||||
comp_shade_strength = 1.0 - self->shade_strength;
|
comp_shade_strength = 1.0 - self->shade_strength;
|
||||||
|
|||||||
@@ -18,10 +18,144 @@
|
|||||||
#include "overviewer.h"
|
#include "overviewer.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
/* structure representing one corner of a face (see below) */
|
||||||
|
struct SmoothLightingCorner {
|
||||||
|
/* where this corner shows up on each block texture */
|
||||||
|
int imgx, imgy;
|
||||||
|
|
||||||
|
/* the two block offsets that (together) determine the 4 blocks to use */
|
||||||
|
int dx1, dy1, dz1;
|
||||||
|
int dx2, dy2, dz2;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* structure for rule table handling lighting */
|
||||||
|
struct SmoothLightingFace {
|
||||||
|
/* offset from current coordinate to the block this face points towards
|
||||||
|
used for occlusion calculations, and as a base for later */
|
||||||
|
int dx, dy, dz;
|
||||||
|
|
||||||
|
/* the points that form the corners of this face */
|
||||||
|
struct SmoothLightingCorner corners[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the lighting face rule list! */
|
||||||
|
static struct SmoothLightingFace lighting_rules[] = {
|
||||||
|
/* top */
|
||||||
|
{0, 0, 1, {
|
||||||
|
{0, 6,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, -1, 0},
|
||||||
|
{12, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
0, -1, 0},
|
||||||
|
{24, 6,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 1, 0},
|
||||||
|
{12, 12,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 1, 0},
|
||||||
|
}},
|
||||||
|
/* left */
|
||||||
|
{-1, 0, 0, {
|
||||||
|
{12, 24,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{0, 18,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{0, 6,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 12,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
}},
|
||||||
|
/* right */
|
||||||
|
{0, 1, 0, {
|
||||||
|
{12, 12,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 24,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{24, 18,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{24, 6,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* helpers for indexing the rule list */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FACE_TOP = 0,
|
||||||
|
FACE_LEFT = 1,
|
||||||
|
FACE_RIGHT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_shading_with_rule(RenderModeSmoothLighting *self, RenderState *state, struct SmoothLightingFace face) {
|
||||||
|
int i;
|
||||||
|
RenderModeLighting *lighting = (RenderModeLighting *)self;
|
||||||
|
int x = state->imgx, y = state->imgy;
|
||||||
|
struct SmoothLightingCorner *pts = face.corners;
|
||||||
|
unsigned char pts_r[4] = {0, 0, 0, 0};
|
||||||
|
unsigned char pts_g[4] = {0, 0, 0, 0};
|
||||||
|
unsigned char pts_b[4] = {0, 0, 0, 0};
|
||||||
|
int cx = state->x + face.dx;
|
||||||
|
int cy = state->y + face.dy;
|
||||||
|
int cz = state->z + face.dz;
|
||||||
|
|
||||||
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
|
if (rendermode_lighting_is_face_occluded(state, 0, cx, cy, cz))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* calculate the lighting colors for each point */
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
unsigned char r, g, b;
|
||||||
|
unsigned int rgather = 0, ggather = 0, bgather = 0;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state, cx, cy, cz,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx1, cy+pts[i].dy1, cz+pts[i].dz1,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx2, cy+pts[i].dy2, cz+pts[i].dz2,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
/* FIXME special far corner handling */
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx1+pts[i].dx2, cy+pts[i].dy1+pts[i].dy2, cz+pts[i].dz1+pts[i].dz2,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
pts_r[i] = rgather / 4;
|
||||||
|
pts_g[i] = ggather / 4;
|
||||||
|
pts_b[i] = bgather / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw the face */
|
||||||
|
draw_triangle(state->img, 1,
|
||||||
|
x+pts[0].imgx, y+pts[0].imgy, pts_r[0], pts_g[0], pts_b[0],
|
||||||
|
x+pts[1].imgx, y+pts[1].imgy, pts_r[1], pts_g[1], pts_b[1],
|
||||||
|
x+pts[2].imgx, y+pts[2].imgy, pts_r[2], pts_g[2], pts_b[2]);
|
||||||
|
draw_triangle(state->img, 0,
|
||||||
|
x+pts[0].imgx, y+pts[0].imgy, pts_r[0], pts_g[0], pts_b[0],
|
||||||
|
x+pts[2].imgx, y+pts[2].imgy, pts_r[2], pts_g[2], pts_b[2],
|
||||||
|
x+pts[3].imgx, y+pts[3].imgy, pts_r[3], pts_g[3], pts_b[3]);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rendermode_smooth_lighting_start(void *data, RenderState *state, PyObject *options) {
|
rendermode_smooth_lighting_start(void *data, RenderState *state, PyObject *options) {
|
||||||
RenderModeNight* self;
|
|
||||||
|
|
||||||
/* first, chain up */
|
/* first, chain up */
|
||||||
int ret = rendermode_lighting.start(data, state, options);
|
int ret = rendermode_lighting.start(data, state, options);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@@ -50,9 +184,10 @@ rendermode_smooth_lighting_hidden(void *data, RenderState *state, int x, int y,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
rendermode_smooth_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
|
rendermode_smooth_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
|
||||||
int x = state->imgx, y = state->imgy;
|
RenderModeSmoothLighting *self = (RenderModeSmoothLighting *)data;
|
||||||
|
|
||||||
if (is_transparent(state->block))
|
/* special case for leaves -- these are also smooth-lit! */
|
||||||
|
if (state->block != 18 && is_transparent(state->block))
|
||||||
{
|
{
|
||||||
/* transparent blocks are rendered as usual, with flat lighting */
|
/* transparent blocks are rendered as usual, with flat lighting */
|
||||||
rendermode_lighting.draw(data, state, src, mask, mask_light);
|
rendermode_lighting.draw(data, state, src, mask, mask_light);
|
||||||
@@ -65,35 +200,9 @@ rendermode_smooth_lighting_draw(void *data, RenderState *state, PyObject *src, P
|
|||||||
* lighting mode draws */
|
* lighting mode draws */
|
||||||
rendermode_normal.draw(data, state, src, mask, mask_light);
|
rendermode_normal.draw(data, state, src, mask, mask_light);
|
||||||
|
|
||||||
/* draw a triangle on top of each block */
|
do_shading_with_rule(self, state, lighting_rules[FACE_TOP]);
|
||||||
draw_triangle(state->img,
|
do_shading_with_rule(self, state, lighting_rules[FACE_LEFT]);
|
||||||
x+12, y, 255, 0, 0,
|
do_shading_with_rule(self, state, lighting_rules[FACE_RIGHT]);
|
||||||
x+24, y+6, 0, 255, 0,
|
|
||||||
x, y+6, 0, 0, 255);
|
|
||||||
draw_triangle(state->img,
|
|
||||||
x+24, y+6, 255, 0, 0,
|
|
||||||
x, y+6, 0, 255, 0,
|
|
||||||
x+12, y+12, 0, 0, 255);
|
|
||||||
|
|
||||||
/* left side... */
|
|
||||||
draw_triangle(state->img,
|
|
||||||
x, y+6, 255, 0, 0,
|
|
||||||
x+12, y+12, 0, 255, 0,
|
|
||||||
x+12, y+24, 0, 0, 255);
|
|
||||||
draw_triangle(state->img,
|
|
||||||
x+12, y+24, 255, 0, 0,
|
|
||||||
x, y+6, 0, 255, 0,
|
|
||||||
x, y+18, 0, 0, 255);
|
|
||||||
|
|
||||||
/* right side... */
|
|
||||||
draw_triangle(state->img,
|
|
||||||
x+24, y+6, 255, 0, 0,
|
|
||||||
x+12, y+12, 0, 255, 0,
|
|
||||||
x+12, y+24, 0, 0, 255);
|
|
||||||
draw_triangle(state->img,
|
|
||||||
x+12, y+24, 255, 0, 0,
|
|
||||||
x+24, y+6, 0, 255, 0,
|
|
||||||
x+24, y+18, 0, 0, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderModeInterface rendermode_smooth_lighting = {
|
RenderModeInterface rendermode_smooth_lighting = {
|
||||||
|
|||||||
@@ -183,6 +183,14 @@ typedef struct {
|
|||||||
} RenderModeLighting;
|
} RenderModeLighting;
|
||||||
extern RenderModeInterface rendermode_lighting;
|
extern RenderModeInterface rendermode_lighting;
|
||||||
|
|
||||||
|
/* exposed so it can be used in other per-face occlusion checks */
|
||||||
|
int rendermode_lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z);
|
||||||
|
|
||||||
|
/* exposed so sub-modes can look at colors directly */
|
||||||
|
void get_lighting_color(RenderModeLighting *self, RenderState *state,
|
||||||
|
int x, int y, int z,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b);
|
||||||
|
|
||||||
/* NIGHT */
|
/* NIGHT */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* inherits from lighting */
|
/* inherits from lighting */
|
||||||
|
|||||||
Reference in New Issue
Block a user