summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/hills.c10
-rw-r--r--kon/kon3d.c30
-rw-r--r--kon/kon3d.h1
3 files changed, 38 insertions, 3 deletions
diff --git a/examples/hills.c b/examples/hills.c
index c56ab70..a6f36c5 100644
--- a/examples/hills.c
+++ b/examples/hills.c
@@ -22,6 +22,7 @@
#define SIZE 128
#define MARKERS 24
#define BRUSH 3.0f
+#define FOG_END 80.0f
#define COL_SKY 0xFF1B1826u
#define COL_DIM 0xFF9A93B3u
@@ -35,6 +36,7 @@ typedef struct state {
kon_terrain_t *terrain;
kon_material_t grass;
kon_image *ground, *marker;
+ kon_mipmaps_t *mips;
kon_fp_t fp;
int raise, lower;
double time;
@@ -82,6 +84,9 @@ static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user)
kon_clearFramebuffer(game, COL_SKY);
light.direction = KON_VEC3(-0.4f, -1.0f, -0.3f);
light.ambient = 0.45f;
+ light.fogColor = COL_SKY;
+ light.fogStart = 25.0f;
+ light.fogEnd = FOG_END;
kon_drawTerrain(game, &camera, state->terrain, &light);
for (i = 0; i < MARKERS; i++) {
@@ -151,6 +156,8 @@ static int init(kon_program_t *program, void *user)
}
}
state->grass = kon_materialTexture(state->ground);
+ state->mips = kon_createMipmaps(state->ground);
+ state->grass.mips = state->mips;
state->terrain->material = &state->grass;
state->map.columns = SIZE;
@@ -172,7 +179,7 @@ static int init(kon_program_t *program, void *user)
}
kon_fpInit(&state->fp, &state->map, SIZE / 2, SIZE / 2);
- state->fp.farZ = 90.0f;
+ state->fp.farZ = FOG_END;
kon_fpPlace(&state->fp, &state->map, state->terrain);
kon_fpDebug(&state->fp, program->debug);
kon_terrainDebug(state->terrain, program->debug);
@@ -185,6 +192,7 @@ static void shutdown(kon_program_t *program, void *user)
(void)program;
kon_terrainFree(state->terrain);
+ kon_freeMipmaps(state->mips);
kon_freeFramebuffer(state->ground);
kon_freeFramebuffer(state->marker);
}
diff --git a/kon/kon3d.c b/kon/kon3d.c
index 6d6cee7..8e5c106 100644
--- a/kon/kon3d.c
+++ b/kon/kon3d.c
@@ -271,6 +271,17 @@ static float *kon_corner_(const kon_terrain_t *terrain, int column, int row)
return &terrain->heights[(size_t)row * (size_t)(terrain->columns + 1) + (size_t)column];
}
+/* the slope at a corner from the corners around it, so the light does not jump between triangles */
+static kon_vec3_t kon_cornerNormal_(const kon_terrain_t *terrain, int column, int row)
+{
+ int x0 = column > 0 ? column - 1 : column, x1 = column < terrain->columns ? column + 1 : column;
+ int z0 = row > 0 ? row - 1 : row, z1 = row < terrain->rows ? row + 1 : row;
+ float dx = *kon_corner_(terrain, x0, row) - *kon_corner_(terrain, x1, row);
+ float dz = *kon_corner_(terrain, column, z0) - *kon_corner_(terrain, column, z1);
+
+ return kon_vec3Normalize(KON_VEC3(dx / (float)(x1 - x0), 1.0f, dz / (float)(z1 - z0)));
+}
+
static void kon_chunkBounds_(kon_terrain_t *terrain, int cx, int cz)
{
int x0 = cx * terrain->chunk, z0 = cz * terrain->chunk;
@@ -578,8 +589,23 @@ void kon_drawTerrain(kon_framebuffer_t *fb, const kon_camera_t *camera, const ko
kon_vec3_t a = KON_VEC3((float)x, ha, (float)z), b = KON_VEC3((float)x + 1, hb, (float)z);
kon_vec3_t c = KON_VEC3((float)x + 1, hc, (float)z + 1), d = KON_VEC3((float)x, hd, (float)z + 1);
kon_vec3_t upper = kon_vec3Normalize(KON_VEC3(hd - hc, 1.0f, ha - hd)), lower = kon_vec3Normalize(KON_VEC3(ha - hb, 1.0f, hb - hc));
- kon_vertex_t va = { a, upper, KON_VEC2((float)x, (float)z) }, vd = { d, upper, KON_VEC2((float)x, (float)z + 1) }, vc = { c, upper, KON_VEC2((float)x + 1, (float)z + 1) };
- kon_vertex_t wa = { a, lower, va.uv }, wc = { c, lower, vc.uv }, wb = { b, lower, KON_VEC2((float)x + 1, (float)z) };
+ kon_vec3_t na = upper, nb = lower, nc = upper, nd = upper;
+ kon_vertex_t va, vd, vc, wa, wc, wb;
+
+ if (!terrain->faceted) {
+ na = kon_cornerNormal_(terrain, x, z);
+ nb = kon_cornerNormal_(terrain, x + 1, z);
+ nc = kon_cornerNormal_(terrain, x + 1, z + 1);
+ nd = kon_cornerNormal_(terrain, x, z + 1);
+ }
+ va.position = a; va.normal = na; va.uv = KON_VEC2((float)x, (float)z);
+ vd.position = d; vd.normal = nd; vd.uv = KON_VEC2((float)x, (float)z + 1);
+ vc.position = c; vc.normal = nc; vc.uv = KON_VEC2((float)x + 1, (float)z + 1);
+ wa = va; wc = vc; wb.position = b; wb.normal = nb; wb.uv = KON_VEC2((float)x + 1, (float)z);
+ if (terrain->faceted) {
+ wa.normal = lower;
+ wc.normal = lower;
+ }
kon_drawTriangle3D(fb, vp, va, vd, vc, terrain->material, light, KON_RENDER_DEFAULT);
kon_drawTriangle3D(fb, vp, wa, wc, wb, terrain->material, light, KON_RENDER_DEFAULT);
diff --git a/kon/kon3d.h b/kon/kon3d.h
index 510fb86..726df26 100644
--- a/kon/kon3d.h
+++ b/kon/kon3d.h
@@ -57,6 +57,7 @@ typedef struct kon_terrain {
int chunkColumns, chunkRows;
float *chunkMin, *chunkMax;
const kon_material_t *material; /* the texture repeats once per cell */
+ int faceted; /* 1 shades every triangle flat, 0 smooths the light over the corners */
} kon_terrain_t;
/* what to draw for a map. solid is indexed by tile id like in kon_tilemapMove, solid tiles become walls.