draw: draw_distance for 3d spaces, proper positioning of skybox according to it, scenery demo on circle rasters

This commit is contained in:
veclavtalica 2025-02-26 15:53:59 +03:00
parent 23fbd45564
commit 8c0f43ec34
9 changed files with 123 additions and 80 deletions

View File

@ -12,10 +12,13 @@
#define TERRAIN_FREQUENCY 0.15f #define TERRAIN_FREQUENCY 0.15f
#define TERRAIN_DISTANCE 128 #define TERRAIN_RADIUS 128
#define GRASS_RADIUS 16
#define TERRAIN_DISTANCE (TERRAIN_RADIUS * 2)
#define HALF_TERRAIN_DISTANCE ((float)TERRAIN_DISTANCE / 2) #define HALF_TERRAIN_DISTANCE ((float)TERRAIN_DISTANCE / 2)
#define PLAYER_HEIGHT 0.6f #define PLAYER_HEIGHT 0.6f
/* TODO: pregenerate grid of levels of detail */
static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE]; static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE];
@ -23,7 +26,7 @@ static void process_fly_mode(State *state) {
SceneIngame *scn = (SceneIngame *)state->scene; SceneIngame *scn = (SceneIngame *)state->scene;
DrawCameraFromPrincipalAxesResult dir_and_up = DrawCameraFromPrincipalAxesResult dir_and_up =
draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1); draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1, TERRAIN_RADIUS * M_SQRT2f);
const Vec3 right = m_vec_norm(m_vec_cross(dir_and_up.direction, dir_and_up.up)); const Vec3 right = m_vec_norm(m_vec_cross(dir_and_up.direction, dir_and_up.up));
const float speed = 0.04f; /* TODO: put this in a better place */ const float speed = 0.04f; /* TODO: put this in a better place */
@ -80,7 +83,7 @@ static void process_ground_mode(State *state) {
SceneIngame *scn = (SceneIngame *)state->scene; SceneIngame *scn = (SceneIngame *)state->scene;
DrawCameraFromPrincipalAxesResult dir_and_up = DrawCameraFromPrincipalAxesResult dir_and_up =
draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1); draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1, TERRAIN_RADIUS * M_SQRT2f);
dir_and_up.direction.y = 0; dir_and_up.direction.y = 0;
dir_and_up.direction = vec3_norm(dir_and_up.direction); dir_and_up.direction = vec3_norm(dir_and_up.direction);
@ -134,7 +137,7 @@ static void generate_terrain(SceneIngame *scn) {
float y = floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly); float y = floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly);
float height = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 1; float height = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 1;
height += stb_perlin_noise3((float)x * TERRAIN_FREQUENCY / 10, (float)y * TERRAIN_FREQUENCY / 10, 0, 0, 0, 0) * 10 - 1; height += stb_perlin_noise3((float)x * TERRAIN_FREQUENCY / 10, (float)y * TERRAIN_FREQUENCY / 10, 0, 0, 0, 0) * 20 - 1;
heightmap[lx][ly] = height; heightmap[lx][ly] = height;
} }
@ -142,9 +145,23 @@ static void generate_terrain(SceneIngame *scn) {
} }
static int32_t ceil_sqrt(int32_t const n) {
int32_t res = 1;
while(res * res < n)
res++;
return res;
}
static void draw_terrain(SceneIngame *scn) { static void draw_terrain(SceneIngame *scn) {
for (int ly = TERRAIN_DISTANCE - 1; ly > 0; ly--) { /* draw terrain in circle */
for (int lx = 0; lx < TERRAIN_DISTANCE - 1; lx++) { int32_t const rsi = (int32_t)TERRAIN_RADIUS * (int32_t)TERRAIN_RADIUS;
for (int32_t iy = -(int32_t)TERRAIN_RADIUS; iy <= (int32_t)TERRAIN_RADIUS - 1; ++iy) {
int32_t const dx = ceil_sqrt(rsi - (iy + (iy <= 0)) * (iy + (iy <= 0)));
for (int32_t ix = -dx; ix < dx; ++ix) {
int32_t lx = ix + TERRAIN_RADIUS;
int32_t ly = iy + TERRAIN_RADIUS;
int32_t x = (int32_t)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx)); int32_t x = (int32_t)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
int32_t y = (int32_t)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly)); int32_t y = (int32_t)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
@ -160,8 +177,21 @@ static void draw_terrain(SceneIngame *scn) {
(Vec3){ (float)x, d3, (float)y - 1 }, (Vec3){ (float)x, d3, (float)y - 1 },
(Rect){ .w = 128, .h = 128 }, (Rect){ .w = 128, .h = 128 },
(Color){255, 255, 255, 255}); (Color){255, 255, 255, 255});
}
}
int32_t const rsi_g = (int32_t)GRASS_RADIUS * (int32_t)GRASS_RADIUS;
for (int32_t iy = -(int32_t)GRASS_RADIUS; iy <= (int32_t)GRASS_RADIUS - 1; ++iy) {
int32_t const dx = ceil_sqrt(rsi_g - (iy + (iy <= 0)) * (iy + (iy <= 0)));
for (int32_t ix = -dx; ix < dx; ++ix) {
int32_t lx = ix + TERRAIN_RADIUS;
int32_t ly = iy + TERRAIN_RADIUS;
int32_t x = (int32_t)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
int32_t y = (int32_t)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
float d0 = heightmap[lx][ly];
/* TODO: only draw upclose */
draw_billboard("/assets/grasses/10.png", draw_billboard("/assets/grasses/10.png",
(Vec3){ (float)x, d0 + 0.15f, (float)y }, (Vec3){ (float)x, d0 + 0.15f, (float)y },
(Vec2){0.3f, 0.3f}, (Vec2){0.3f, 0.3f},
@ -216,7 +246,7 @@ static void ingame_tick(State *state) {
draw_skybox("/assets/miramar/miramar_*.tga"); draw_skybox("/assets/miramar/miramar_*.tga");
ctx.fog_color = (Color){ 140, 147, 160, 255 }; ctx.fog_color = (Color){ 140, 147, 160, 255 };
ctx.fog_density = 0.03f; ctx.fog_density = 0.02f;
} }

View File

@ -86,11 +86,12 @@ TWN_API void draw_camera_2d(Vec2 position, /* optional, default: (0, 0) */
/* sets a perspective 3d camera to be used for all 3d commands */ /* sets a perspective 3d camera to be used for all 3d commands */
/* fov = 0 corresponds to orthographic projection */ /* fov = 0 corresponds to orthographic projection */
TWN_API void draw_camera(Vec3 position, TWN_API void draw_camera(Vec3 position, /* optional, default: (0, 0, 0) */
Vec3 direction, /* optional, default: (0, 0, -1) */ Vec3 direction, /* optional, default: (0, 0, -1) */
Vec3 up, /* optional, default: (0, 1, 0) */ Vec3 up, /* optional, default: (0, 1, 0) */
float fov, /* optional, default: PI / 6 * 3 (90 degrees) */ float fov, /* optional, default: PI / 6 * 3 (90 degrees) */
float zoom); /* optional, default: 1 */ float zoom, /* optional, default: 1 */
float draw_distance); /* optional, default: 100 */
/* same as draw_camera(), but with first person controller in mind */ /* same as draw_camera(), but with first person controller in mind */
/* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */ /* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */
@ -100,12 +101,13 @@ typedef struct DrawCameraFromPrincipalAxesResult {
Vec3 up; Vec3 up;
} DrawCameraFromPrincipalAxesResult; } DrawCameraFromPrincipalAxesResult;
TWN_API DrawCameraFromPrincipalAxesResult TWN_API DrawCameraFromPrincipalAxesResult
draw_camera_from_principal_axes(Vec3 position, draw_camera_from_principal_axes(Vec3 position, /* optional, default: (0, 0, 0) */
float roll, /* optional, default: 0 */ float roll, /* optional, default: 0 */
float pitch, /* optional, default: 0 */ float pitch, /* optional, default: 0 */
float yaw, /* optional, default: 0 */ float yaw, /* optional, default: 0 */
float fov, /* optional, default: PI / 6 * 3 (90 degrees) */ float fov, /* optional, default: PI / 6 * 3 (90 degrees) */
float zoom); /* optional, default: 1 */ float zoom, /* optional, default: 1 */
float draw_distance); /* optional, default: 100 */
/* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */ /* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */
TWN_API void draw_skybox(const char *textures); TWN_API void draw_skybox(const char *textures);

View File

@ -207,11 +207,12 @@
"symbol": "camera", "symbol": "camera",
"header": "twn_draw.h", "header": "twn_draw.h",
"params": [ "params": [
{ "name": "position", "type": "Vec3" }, { "name": "position", "type": "Vec3", "default": { "x": 0, "y": 0, "z": 0 } },
{ "name": "direction", "type": "Vec3", "default": { "x": 0, "y": 0, "z": -1 } }, { "name": "direction", "type": "Vec3", "default": { "x": 0, "y": 0, "z": -1 } },
{ "name": "up", "type": "Vec3", "default": { "x": 0, "y": 1, "z": 0 } }, { "name": "up", "type": "Vec3", "default": { "x": 0, "y": 1, "z": 0 } },
{ "name": "fov", "type": "float", "default": 1.57079632679 }, { "name": "fov", "type": "float", "default": 1.57079632679 },
{ "name": "zoom", "type": "float", "default": 1 } { "name": "zoom", "type": "float", "default": 1 },
{ "name": "draw_distance", "type": "float", "default": 100 }
] ]
}, },
@ -220,12 +221,13 @@
"symbol": "camera_from_principal_axes", "symbol": "camera_from_principal_axes",
"header": "twn_draw.h", "header": "twn_draw.h",
"params": [ "params": [
{ "name": "position", "type": "Vec3" }, { "name": "position", "type": "Vec3", "default": { "x": 0, "y": 0, "z": 0 } },
{ "name": "roll", "type": "float", "default": 0 }, { "name": "roll", "type": "float", "default": 0 },
{ "name": "pitch", "type": "float", "default": 0 }, { "name": "pitch", "type": "float", "default": 0 },
{ "name": "yaw", "type": "float", "default": 0 }, { "name": "yaw", "type": "float", "default": 0 },
{ "name": "fov", "type": "float", "default": 1.57079632679 }, { "name": "fov", "type": "float", "default": 1.57079632679 },
{ "name": "zoom", "type": "float", "default": 1 } { "name": "zoom", "type": "float", "default": 1 },
{ "name": "draw_distance", "type": "float", "default": 100 }
], ],
"return": { "return": {
"fields": [ "fields": [

View File

@ -20,6 +20,7 @@ DeferredCommand *deferred_commands;
/* TODO: with buffered render, don't we use camera of wrong frame right now ? */ /* TODO: with buffered render, don't we use camera of wrong frame right now ? */
Matrix4 camera_projection_matrix; Matrix4 camera_projection_matrix;
Matrix4 camera_look_at_matrix; Matrix4 camera_look_at_matrix;
float camera_far_z;
float camera_2d_rotation; float camera_2d_rotation;
Vec2 camera_2d_position; Vec2 camera_2d_position;
@ -36,7 +37,7 @@ static void reset_camera_2d(void) {
void render_clear(void) { void render_clear(void) {
draw_camera((Vec3){0, 0, 0}, (Vec3){0, 0, 1}, (Vec3){0, 1, 0}, 1.57079632679f, 1); draw_camera((Vec3){0, 0, 0}, (Vec3){0, 0, 1}, (Vec3){0, 1, 0}, 1.57079632679f, 1, 100);
reset_camera_2d(); reset_camera_2d();
text_cache_reset_arena(&ctx.text_cache); text_cache_reset_arena(&ctx.text_cache);
@ -423,7 +424,7 @@ TWN_API void draw_camera_2d(Vec2 position,
} }
/* TODO: check for NaNs and alike */ /* TODO: check for NaNs and alike */
void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom) { void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom, float draw_distance) {
bool const orthographic = fabsf(0.0f - fov) < 0.00001f; bool const orthographic = fabsf(0.0f - fov) < 0.00001f;
if (!orthographic && fov >= (float)(M_PI)) if (!orthographic && fov >= (float)(M_PI))
log_warn("Invalid fov given (%f)", (double)fov); log_warn("Invalid fov given (%f)", (double)fov);
@ -437,6 +438,7 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom)
(Vec2){ 1/-zoom, 1/zoom }, (Vec2){ 1/-zoom, 1/zoom },
(Vec2){ 1/zoom, 1/-zoom } (Vec2){ 1/zoom, 1/-zoom }
}, },
.far_z = draw_distance
}; };
if (!orthographic) if (!orthographic)
@ -444,6 +446,8 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom)
else else
camera_projection_matrix = camera_orthographic(&camera); camera_projection_matrix = camera_orthographic(&camera);
camera_far_z = draw_distance;
camera_look_at_matrix = camera_look_at(&camera); camera_look_at_matrix = camera_look_at(&camera);
} }
@ -455,7 +459,8 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
float pitch, float pitch,
float yaw, float yaw,
float fov, float fov,
float zoom) float zoom,
float draw_distance)
{ {
bool const orthographic = fabsf(0.0f - fov) < 0.00001f; bool const orthographic = fabsf(0.0f - fov) < 0.00001f;
if (!orthographic && fov >= (float)(M_PI)) if (!orthographic && fov >= (float)(M_PI))
@ -476,7 +481,7 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
Vec3 const up = (Vec3){0, 1, 0}; Vec3 const up = (Vec3){0, 1, 0};
draw_camera(position, direction, up, fov, zoom); draw_camera(position, direction, up, fov, zoom, draw_distance);
return (DrawCameraFromPrincipalAxesResult) { return (DrawCameraFromPrincipalAxesResult) {
.direction = direction, .direction = direction,

View File

@ -16,6 +16,7 @@
extern Matrix4 camera_projection_matrix; extern Matrix4 camera_projection_matrix;
extern Matrix4 camera_look_at_matrix; extern Matrix4 camera_look_at_matrix;
extern float camera_far_z;
extern float camera_2d_rotation; extern float camera_2d_rotation;
extern Vec2 camera_2d_position; extern Vec2 camera_2d_position;

View File

@ -441,66 +441,68 @@ void finally_render_skybox(DeferredCommandDrawSkybox command) {
glEnable(GL_DEPTH_CLAMP); glEnable(GL_DEPTH_CLAMP);
#endif #endif
float const d = camera_far_z / sqrtf(3);
glBegin(GL_QUADS); { glBegin(GL_QUADS); {
/* up */ /* up */
glTexCoord3f(50.f, 50.f, 50.f); glTexCoord3f(d, d, d);
glVertex3f(50.f, 50.f, 50.f); glVertex3f(d, d, d);
glTexCoord3f(-50.f, 50.f, 50.f); glTexCoord3f(-d, d, d);
glVertex3f(-50.f, 50.f, 50.f); glVertex3f(-d, d, d);
glTexCoord3f(-50.f, 50.f, -50.f); glTexCoord3f(-d, d, -d);
glVertex3f(-50.f, 50.f, -50.f); glVertex3f(-d, d, -d);
glTexCoord3f(50.f, 50.f, -50.f); glTexCoord3f(d, d, -d);
glVertex3f(50.f, 50.f, -50.f); glVertex3f(d, d, -d);
/* down */ /* down */
glTexCoord3f(50.f, -50.f, 50.f); glTexCoord3f(d, -d, d);
glVertex3f(50.f, -50.f, 50.f); glVertex3f(d, -d, d);
glTexCoord3f(50.f, -50.f, -50.f); glTexCoord3f(d, -d, -d);
glVertex3f(50.f, -50.f, -50.f); glVertex3f(d, -d, -d);
glTexCoord3f(-50.f, -50.f, -50.f); glTexCoord3f(-d, -d, -d);
glVertex3f(-50.f, -50.f, -50.f); glVertex3f(-d, -d, -d);
glTexCoord3f(-50.f, -50.f, 50.f); glTexCoord3f(-d, -d, d);
glVertex3f(-50.f, -50.f, 50.f); glVertex3f(-d, -d, d);
/* east */ /* east */
glTexCoord3f(50.f, -50.f, 50.f); glTexCoord3f(d, -d, d);
glVertex3f(50.f, -50.f, 50.f); glVertex3f(d, -d, d);
glTexCoord3f(50.f, 50.f, 50.f); glTexCoord3f(d, d, d);
glVertex3f(50.f, 50.f, 50.f); glVertex3f(d, d, d);
glTexCoord3f(50.f, 50.f, -50.f); glTexCoord3f(d, d, -d);
glVertex3f(50.f, 50.f, -50.f); glVertex3f(d, d, -d);
glTexCoord3f(50.f, -50.f, -50.f); glTexCoord3f(d, -d, -d);
glVertex3f(50.f, -50.f, -50.f); glVertex3f(d, -d, -d);
/* west */ /* west */
glTexCoord3f(-50.f, -50.f, 50.f); glTexCoord3f(-d, -d, d);
glVertex3f(-50.f, -50.f, 50.f); glVertex3f(-d, -d, d);
glTexCoord3f(-50.f, -50.f, -50.f); glTexCoord3f(-d, -d, -d);
glVertex3f(-50.f, -50.f, -50.f); glVertex3f(-d, -d, -d);
glTexCoord3f(-50.f, 50.f, -50.f); glTexCoord3f(-d, d, -d);
glVertex3f(-50.f, 50.f, -50.f); glVertex3f(-d, d, -d);
glTexCoord3f(-50.f, 50.f, 50.f); glTexCoord3f(-d, d, d);
glVertex3f(-50.f, 50.f, 50.f); glVertex3f(-d, d, d);
/* north */ /* north */
glTexCoord3f(-50.f, -50.f, 50.f); glTexCoord3f(-d, -d, d);
glVertex3f(-50.f, -50.f, 50.f); glVertex3f(-d, -d, d);
glTexCoord3f(-50.f, 50.f, 50.f); glTexCoord3f(-d, d, d);
glVertex3f(-50.f, 50.f, 50.f); glVertex3f(-d, d, d);
glTexCoord3f(50.f, 50.f, 50.f); glTexCoord3f(d, d, d);
glVertex3f(50.f, 50.f, 50.f); glVertex3f(d, d, d);
glTexCoord3f(50.f, -50.f, 50.f); glTexCoord3f(d, -d, d);
glVertex3f(50.f, -50.f, 50.f); glVertex3f(d, -d, d);
/* south */ /* south */
glTexCoord3f(-50.f, -50.f, -50.f); glTexCoord3f(-d, -d, -d);
glVertex3f(-50.f, -50.f, -50.f); glVertex3f(-d, -d, -d);
glTexCoord3f(50.f, -50.f, -50.f); glTexCoord3f(d, -d, -d);
glVertex3f(50.f, -50.f, -50.f); glVertex3f(d, -d, -d);
glTexCoord3f(50.f, 50.f, -50.f); glTexCoord3f(d, d, -d);
glVertex3f(50.f, 50.f, -50.f); glVertex3f(d, d, -d);
glTexCoord3f(-50.f, 50.f, -50.f); glTexCoord3f(-d, d, -d);
glVertex3f(-50.f, 50.f, -50.f); glVertex3f(-d, d, -d);
} glEnd(); } glEnd();
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__

View File

@ -6,7 +6,7 @@
#define CAMERA_NEAR_Z 0.1f #define CAMERA_NEAR_Z 0.1f
#define CAMERA_FAR_Z 1000.0f // #define CAMERA_FAR_Z 400.0f
Matrix4 camera_look_at(const Camera *const camera) { Matrix4 camera_look_at(const Camera *const camera) {
@ -42,13 +42,13 @@ Matrix4 camera_perspective(const Camera *const camera) {
const float aspect = ((float)ctx.base_render_width / (float)ctx.base_render_height); const float aspect = ((float)ctx.base_render_width / (float)ctx.base_render_height);
const float f = 1.0f / tanf(camera->fov * 0.5f); const float f = 1.0f / tanf(camera->fov * 0.5f);
const float fn = 1.0f / (CAMERA_NEAR_Z - CAMERA_FAR_Z); const float fn = 1.0f / (CAMERA_NEAR_Z - camera->far_z);
result.row[0].x = f / aspect; result.row[0].x = f / aspect;
result.row[1].y = f; result.row[1].y = f;
result.row[2].z = (CAMERA_NEAR_Z + CAMERA_FAR_Z) * fn; result.row[2].z = (CAMERA_NEAR_Z + camera->far_z) * fn;
result.row[2].w = -1.0f; result.row[2].w = -1.0f;
result.row[3].z = 2.0f * CAMERA_NEAR_Z * CAMERA_FAR_Z * fn; result.row[3].z = 2.0f * CAMERA_NEAR_Z * camera->far_z * fn;
return result; return result;
} }
@ -61,14 +61,14 @@ Matrix4 camera_orthographic(const Camera *const camera) {
const float rl = 1.0f / (camera->viewbox[0].y - camera->viewbox[0].x); const float rl = 1.0f / (camera->viewbox[0].y - camera->viewbox[0].x);
const float tb = 1.0f / (camera->viewbox[1].x - camera->viewbox[1].y); const float tb = 1.0f / (camera->viewbox[1].x - camera->viewbox[1].y);
const float fn = -1.0f / (CAMERA_FAR_Z - -CAMERA_FAR_Z); const float fn = -1.0f / (camera->far_z - -camera->far_z);
result.row[0].x = 2.0f * rl; result.row[0].x = 2.0f * rl;
result.row[1].y = 2.0f * tb; result.row[1].y = 2.0f * tb;
result.row[2].z = 2.0f * fn; result.row[2].z = 2.0f * fn;
result.row[3].x = -(camera->viewbox[0].y + camera->viewbox[0].x) * rl; result.row[3].x = -(camera->viewbox[0].y + camera->viewbox[0].x) * rl;
result.row[3].y = -(camera->viewbox[1].x + camera->viewbox[1].y) * tb; result.row[3].y = -(camera->viewbox[1].x + camera->viewbox[1].y) * tb;
result.row[3].z = (CAMERA_FAR_Z + -CAMERA_FAR_Z) * fn; result.row[3].z = (camera->far_z + -camera->far_z) * fn;
result.row[3].w = 1.0f; result.row[3].w = 1.0f;
return result; return result;

View File

@ -12,8 +12,9 @@ typedef struct Camera {
Vec3 pos; /* eye position */ Vec3 pos; /* eye position */
Vec3 target; /* normalized target vector */ Vec3 target; /* normalized target vector */
Vec3 up; /* normalized up vector */ Vec3 up; /* normalized up vector */
float fov; /* field of view, in radians */
Vec2 viewbox[2]; /* othrographic aabb, ((left, right), (top, bottom)) */ Vec2 viewbox[2]; /* othrographic aabb, ((left, right), (top, bottom)) */
float fov; /* field of view, in radians */
float far_z;
} Camera; } Camera;
Matrix4 camera_look_at(const Camera *camera); Matrix4 camera_look_at(const Camera *camera);

View File

@ -631,7 +631,7 @@ static bool initialize(void) {
input_state_init(&ctx.input); input_state_init(&ctx.input);
ctx.render_double_buffered = true; ctx.render_double_buffered = false;
ctx.window_mouse_resident = true; ctx.window_mouse_resident = true;
ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */ ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */