summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-11 21:57:22 +0800
committerKonAki <konaki@anokonaki.org>2026-10-11 21:57:22 +0800
commit95bd48a7b0556adab5250cae766ee9dd9c6b2cde (patch)
treea29b83a4f436d6c58321a44977e4eb6d30f7c8d8
parent42630ebee76996a37f5104e6e11b860f31634dab (diff)
konsofren: 3D is opt-in with KONSOFREN_3D, build.sh sets it for 3d, model and sector
-rw-r--r--README.md4
-rwxr-xr-xbuild.sh5
-rw-r--r--examples/handmade.c1
-rw-r--r--kon/kon3d.h4
-rw-r--r--kon/konmodel.h4
-rw-r--r--kon/konsector.h11
-rw-r--r--kon/konsofren.h18
-rw-r--r--src/engine.c55
8 files changed, 78 insertions, 24 deletions
diff --git a/README.md b/README.md
index 7aaed7d..40d7a1a 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Everything is written in [c99](https://en.wikipedia.org/wiki/C99) and drawn by a
The reusable stuff is single-header and lives in [kon](kon). Those are the ones you can drag into any project:
- konwinlib: windows and input events
-- konsofren: the software renderer, 2D and 3D
+- konsofren: the software renderer, 2D always, 3D when you define `KONSOFREN_3D` (the 3d, model and sector modules do it for you)
- konmath: vectors, matrices
- konfont: text, built-in bitmap font or a ttf
- kontime: timing and sleeping
@@ -43,6 +43,8 @@ The engine modules are a `.h` and a `.c` pair, they depend on each other a bit,
| ui | immediate mode ui |
| debug | developer console and asset view |
+The 3D part of konsofren (cameras, triangles, meshes, billboards, fog) is only compiled when a module that draws in 3D is picked, so a 2D game does not carry it. Using konsofren.h on its own, define `KONSOFREN_3D` before including it.
+
### Supported Platforms:
- linux
diff --git a/build.sh b/build.sh
index 2785369..c532155 100755
--- a/build.sh
+++ b/build.sh
@@ -110,10 +110,9 @@ case " $modules " in *" 3d "*) need tile ;; esac
case " $modules " in *" model "*) need assets ;; esac
case " $DEFS " in *" -DKON_MODULE_ASSETS "*) need pack ;; esac
-# 2D games do not get the 3D renderer, the 3d, model and sector modules turn it on
+# the 3D renderer is only compiled when a module that draws in 3D is picked
case " $DEFS " in
-*" -DKON_MODULE_3D "*|*" -DKON_MODULE_MODEL "*|*" -DKON_MODULE_SECTOR "*) ;;
-*) DEFS="$DEFS -DKONSOFREN_NO_3D" ;;
+*" -DKON_MODULE_3D "*|*" -DKON_MODULE_MODEL "*|*" -DKON_MODULE_SECTOR "*) DEFS="$DEFS -DKONSOFREN_3D" ;;
esac
case " $modules " in
diff --git a/examples/handmade.c b/examples/handmade.c
index f2f6847..61b983e 100644
--- a/examples/handmade.c
+++ b/examples/handmade.c
@@ -10,6 +10,7 @@
* w and s walk, a and d strafe, left and right turn, escape quits. which picture goes on which texture name is the table in textures[]
*/
+#define KONSOFREN_3D
#define KONWINLIB_IMPLEMENTATION
#define KONSOFREN_IMPLEMENTATION
#define KONTIME_IMPLEMENTATION
diff --git a/kon/kon3d.h b/kon/kon3d.h
index 726df26..f45f985 100644
--- a/kon/kon3d.h
+++ b/kon/kon3d.h
@@ -29,6 +29,10 @@
#include "konprogram.h"
#include "kontile.h"
+#ifndef KONSOFREN_HAS_3D
+#error "this needs the 3D part of konsofren, define KONSOFREN_3D before the first include of konsofren.h (build.sh does it for -m 3d, model and sector)"
+#endif
+
/*** definition ***/
/* a first person body on a tilemap. the world is one unit per tile, y is up, yaw 0 looks up the map (towards row 0) */
diff --git a/kon/konmodel.h b/kon/konmodel.h
index 8ce36c8..9120194 100644
--- a/kon/konmodel.h
+++ b/kon/konmodel.h
@@ -33,6 +33,10 @@
#include "konsofren.h"
#include "konassets.h"
+#ifndef KONSOFREN_HAS_3D
+#error "this needs the 3D part of konsofren, define KONSOFREN_3D before the first include of konsofren.h (build.sh does it for -m 3d, model and sector)"
+#endif
+
/*** definition ***/
#define KON_MODEL_MAX_BONES 128
diff --git a/kon/konsector.h b/kon/konsector.h
index c7a71e3..fa65a0e 100644
--- a/kon/konsector.h
+++ b/kon/konsector.h
@@ -24,7 +24,8 @@
*/
/* a map made of rooms: loading, saving, looking things up, building a mesh and drawing it. it needs konsofren.h and konmath.h next to it
- * and nothing else, so it is copy and paste like the other single header libs. in exactly one .c file:
+ * and nothing else, so it is copy and paste like the other single header libs. it turns on the 3D part of konsofren, so include it
+ * before konsofren.h or define KONSOFREN_3D yourself. in exactly one .c file:
*
* #define KONSOFREN_IMPLEMENTATION (once, wherever konsofren is)
* #define KONSECTOR_IMPLEMENTATION
@@ -37,9 +38,17 @@
#include <stddef.h>
+#ifndef KONSOFREN_3D
+#define KONSOFREN_3D
+#endif
+
#include "konmath.h"
#include "konsofren.h"
+#ifndef KONSOFREN_HAS_3D
+#error "this needs the 3D part of konsofren, define KONSOFREN_3D before the first include of konsofren.h (build.sh does it for -m 3d, model and sector)"
+#endif
+
/*** definition ***/
/* a map is rooms seen from above. every room (sector) is a polygon of vertices with a floor and a ceiling height, and every
diff --git a/kon/konsofren.h b/kon/konsofren.h
index d7f3570..4e29e56 100644
--- a/kon/konsofren.h
+++ b/kon/konsofren.h
@@ -26,8 +26,8 @@
#ifndef KONSOFREN_H
#define KONSOFREN_H
-/* define KONSOFREN_NO_3D (in every file that includes this, and where the implementation is) for a 2D game, the cameras,
- triangles, meshes and billboards are left out. 3D is on by default */
+/* the 3D part (cameras, triangles, meshes, billboards, mipmaps, fog) is only there if you ask for it. define KONSOFREN_3D
+ before this header in every file that includes it, and in the one with the implementation. a 2D game compiles without it */
#include <stdint.h>
#include <stdlib.h>
@@ -77,7 +77,9 @@ typedef struct kon_display {
kon_filter_t filter;
} kon_display_t;
-#ifndef KONSOFREN_NO_3D
+#ifdef KONSOFREN_3D
+
+#define KONSOFREN_HAS_3D
typedef enum kon_projection {
KON_PROJECTION_PERSPECTIVE = 0,
@@ -152,7 +154,7 @@ typedef struct kon_mesh {
int triangleCount;
} kon_mesh_t;
-#endif /* KONSOFREN_NO_3D */
+#endif /* KONSOFREN_3D */
/*** 2D declarations ***/
@@ -208,7 +210,7 @@ void kon_presentDisplay(kon_display_t *display);
/* returns 0 if the window position is on a bar, outside the game image */
int kon_windowToGame(const kon_display_t *display, int windowX, int windowY, int *gameX, int *gameY);
-#ifndef KONSOFREN_NO_3D
+#ifdef KONSOFREN_3D
/*** 3D declarations ***/
@@ -250,7 +252,7 @@ int kon_drawBillboard(kon_framebuffer_t *fb, kon_mat4_t viewProjection, kon_vec3
/* cube from -1 to 1 with every face mapped to the whole texture */
extern const kon_mesh_t kon_cubeMesh;
-#endif /* KONSOFREN_NO_3D */
+#endif /* KONSOFREN_3D */
/*** implementation ***/
@@ -996,7 +998,7 @@ int kon_windowToGame(const kon_display_t *display, int windowX, int windowY, int
return 1;
}
-#ifndef KONSOFREN_NO_3D
+#ifdef KONSOFREN_3D
/*** 3D implementation ***/
@@ -1650,7 +1652,7 @@ int kon_drawBillboard(kon_framebuffer_t *fb, kon_mat4_t viewProjection, kon_vec3
return 1;
}
-#endif /* KONSOFREN_NO_3D */
+#endif /* KONSOFREN_3D */
#endif /* end of KONSOFREN_IMPLEMENTATION */
#endif
diff --git a/src/engine.c b/src/engine.c
index 1594032..362e522 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1,11 +1,17 @@
#include "konprogram.h"
+/* the starting point for a game. with the 3d module (./build.sh -m 3d) it is a spinning cube, without it a square that bounces around */
+
typedef struct demo {
+#ifdef KONSOFREN_3D
kon_camera_t camera;
kon_material_t material;
kon_light_t light;
- float angle;
int ortho;
+#else
+ float x, y, vx, vy;
+#endif
+ float angle;
} demo_t;
static int init(kon_program_t *program, void *user)
@@ -13,23 +19,36 @@ static int init(kon_program_t *program, void *user)
demo_t *demo = user;
(void)program;
+#ifdef KONSOFREN_3D
demo->camera = kon_cameraDefault();
demo->camera.position = KON_VEC3(3, 3, 6);
demo->material = kon_materialColor(0xFFC8C8FF);
demo->light = kon_lightDefault();
+#else
+ demo->x = 40.0f;
+ demo->y = 30.0f;
+ demo->vx = 70.0f;
+ demo->vy = 50.0f;
+#endif
return 1;
}
static int event(kon_program_t *program, const kon_event_t *ev, void *user)
{
- demo_t *demo = user;
-
(void)program;
- if (ev->type == KON_EVENT_KEY_DOWN && ev->key == KON_KEY_O) {
- demo->ortho = !demo->ortho;
- demo->camera.projection = demo->ortho ? KON_PROJECTION_ORTHOGRAPHIC : KON_PROJECTION_PERSPECTIVE;
- return 1;
+#ifdef KONSOFREN_3D
+ {
+ demo_t *demo = user;
+
+ if (ev->type == KON_EVENT_KEY_DOWN && ev->key == KON_KEY_O) {
+ demo->ortho = !demo->ortho;
+ demo->camera.projection = demo->ortho ? KON_PROJECTION_ORTHOGRAPHIC : KON_PROJECTION_PERSPECTIVE;
+ return 1;
+ }
}
+#else
+ (void)ev; (void)user;
+#endif
return 0;
}
@@ -37,18 +56,32 @@ static void update(kon_program_t *program, double dt, void *user)
{
demo_t *demo = user;
- (void)program;
demo->angle += (float)dt;
+#ifndef KONSOFREN_3D
+ demo->x += demo->vx * (float)dt;
+ demo->y += demo->vy * (float)dt;
+ if (demo->x < 0.0f || demo->x > (float)program->display->game->width - 24.0f) demo->vx = -demo->vx;
+ if (demo->y < 0.0f || demo->y > (float)program->display->game->height - 24.0f) demo->vy = -demo->vy;
+#else
+ (void)program;
+#endif
}
static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user)
{
demo_t *demo = user;
- kon_mat4_t model = kon_mat4Rotate(kon_mat4Identity(), KON_VEC3(demo->angle * 0.5f, demo->angle, 0));
- kon_mat4_t viewProjection = kon_cameraViewProjection(&demo->camera, game->width, game->height);
(void)program;
- kon_drawMesh(game, viewProjection, model, &kon_cubeMesh, &demo->material, &demo->light, KON_RENDER_DEFAULT);
+#ifdef KONSOFREN_3D
+ {
+ kon_mat4_t model = kon_mat4Rotate(kon_mat4Identity(), KON_VEC3(demo->angle * 0.5f, demo->angle, 0));
+ kon_mat4_t viewProjection = kon_cameraViewProjection(&demo->camera, game->width, game->height);
+
+ kon_drawMesh(game, viewProjection, model, &kon_cubeMesh, &demo->material, &demo->light, KON_RENDER_DEFAULT);
+ }
+#else
+ kon_fillRectangle(game, (int)demo->x, (int)demo->y, 24, 24, 0xFFF2A7C3);
+#endif
}
int main(void)