draw: draw_distance for 3d spaces, proper positioning of skybox according to it, scenery demo on circle rasters
This commit is contained in:
parent
23fbd45564
commit
8c0f43ec34
@ -12,10 +12,13 @@
|
||||
|
||||
|
||||
#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 PLAYER_HEIGHT 0.6f
|
||||
|
||||
/* TODO: pregenerate grid of levels of detail */
|
||||
static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE];
|
||||
|
||||
|
||||
@ -23,7 +26,7 @@ static void process_fly_mode(State *state) {
|
||||
SceneIngame *scn = (SceneIngame *)state->scene;
|
||||
|
||||
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 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;
|
||||
|
||||
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 = 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 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;
|
||||
}
|
||||
@ -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) {
|
||||
for (int ly = TERRAIN_DISTANCE - 1; ly > 0; ly--) {
|
||||
for (int lx = 0; lx < TERRAIN_DISTANCE - 1; lx++) {
|
||||
/* draw terrain in circle */
|
||||
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 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 },
|
||||
(Rect){ .w = 128, .h = 128 },
|
||||
(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",
|
||||
(Vec3){ (float)x, d0 + 0.15f, (float)y },
|
||||
(Vec2){0.3f, 0.3f},
|
||||
@ -216,7 +246,7 @@ static void ingame_tick(State *state) {
|
||||
draw_skybox("/assets/miramar/miramar_*.tga");
|
||||
|
||||
ctx.fog_color = (Color){ 140, 147, 160, 255 };
|
||||
ctx.fog_density = 0.03f;
|
||||
ctx.fog_density = 0.02f;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
/* 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 up, /* optional, default: (0, 1, 0) */
|
||||
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 */
|
||||
/* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */
|
||||
@ -100,12 +101,13 @@ typedef struct DrawCameraFromPrincipalAxesResult {
|
||||
Vec3 up;
|
||||
} 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 pitch, /* optional, default: 0 */
|
||||
float yaw, /* optional, default: 0 */
|
||||
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' */
|
||||
TWN_API void draw_skybox(const char *textures);
|
||||
|
@ -207,11 +207,12 @@
|
||||
"symbol": "camera",
|
||||
"header": "twn_draw.h",
|
||||
"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": "up", "type": "Vec3", "default": { "x": 0, "y": 1, "z": 0 } },
|
||||
{ "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",
|
||||
"header": "twn_draw.h",
|
||||
"params": [
|
||||
{ "name": "position", "type": "Vec3" },
|
||||
{ "name": "position", "type": "Vec3", "default": { "x": 0, "y": 0, "z": 0 } },
|
||||
{ "name": "roll", "type": "float", "default": 0 },
|
||||
{ "name": "pitch", "type": "float", "default": 0 },
|
||||
{ "name": "yaw", "type": "float", "default": 0 },
|
||||
{ "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": {
|
||||
"fields": [
|
||||
|
@ -20,6 +20,7 @@ DeferredCommand *deferred_commands;
|
||||
/* TODO: with buffered render, don't we use camera of wrong frame right now ? */
|
||||
Matrix4 camera_projection_matrix;
|
||||
Matrix4 camera_look_at_matrix;
|
||||
float camera_far_z;
|
||||
|
||||
float camera_2d_rotation;
|
||||
Vec2 camera_2d_position;
|
||||
@ -36,7 +37,7 @@ static void reset_camera_2d(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();
|
||||
|
||||
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 */
|
||||
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;
|
||||
if (!orthographic && fov >= (float)(M_PI))
|
||||
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 }
|
||||
},
|
||||
.far_z = draw_distance
|
||||
};
|
||||
|
||||
if (!orthographic)
|
||||
@ -444,6 +446,8 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom)
|
||||
else
|
||||
camera_projection_matrix = camera_orthographic(&camera);
|
||||
|
||||
camera_far_z = draw_distance;
|
||||
|
||||
camera_look_at_matrix = camera_look_at(&camera);
|
||||
}
|
||||
|
||||
@ -455,7 +459,8 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
|
||||
float pitch,
|
||||
float yaw,
|
||||
float fov,
|
||||
float zoom)
|
||||
float zoom,
|
||||
float draw_distance)
|
||||
{
|
||||
bool const orthographic = fabsf(0.0f - fov) < 0.00001f;
|
||||
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};
|
||||
|
||||
draw_camera(position, direction, up, fov, zoom);
|
||||
draw_camera(position, direction, up, fov, zoom, draw_distance);
|
||||
|
||||
return (DrawCameraFromPrincipalAxesResult) {
|
||||
.direction = direction,
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
extern Matrix4 camera_projection_matrix;
|
||||
extern Matrix4 camera_look_at_matrix;
|
||||
extern float camera_far_z;
|
||||
|
||||
extern float camera_2d_rotation;
|
||||
extern Vec2 camera_2d_position;
|
||||
|
@ -441,66 +441,68 @@ void finally_render_skybox(DeferredCommandDrawSkybox command) {
|
||||
glEnable(GL_DEPTH_CLAMP);
|
||||
#endif
|
||||
|
||||
float const d = camera_far_z / sqrtf(3);
|
||||
|
||||
glBegin(GL_QUADS); {
|
||||
/* up */
|
||||
glTexCoord3f(50.f, 50.f, 50.f);
|
||||
glVertex3f(50.f, 50.f, 50.f);
|
||||
glTexCoord3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glTexCoord3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glTexCoord3f(50.f, 50.f, -50.f);
|
||||
glVertex3f(50.f, 50.f, -50.f);
|
||||
glTexCoord3f(d, d, d);
|
||||
glVertex3f(d, d, d);
|
||||
glTexCoord3f(-d, d, d);
|
||||
glVertex3f(-d, d, d);
|
||||
glTexCoord3f(-d, d, -d);
|
||||
glVertex3f(-d, d, -d);
|
||||
glTexCoord3f(d, d, -d);
|
||||
glVertex3f(d, d, -d);
|
||||
|
||||
/* down */
|
||||
glTexCoord3f(50.f, -50.f, 50.f);
|
||||
glVertex3f(50.f, -50.f, 50.f);
|
||||
glTexCoord3f(50.f, -50.f, -50.f);
|
||||
glVertex3f(50.f, -50.f, -50.f);
|
||||
glTexCoord3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glTexCoord3f(-50.f, -50.f, 50.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
glTexCoord3f(d, -d, d);
|
||||
glVertex3f(d, -d, d);
|
||||
glTexCoord3f(d, -d, -d);
|
||||
glVertex3f(d, -d, -d);
|
||||
glTexCoord3f(-d, -d, -d);
|
||||
glVertex3f(-d, -d, -d);
|
||||
glTexCoord3f(-d, -d, d);
|
||||
glVertex3f(-d, -d, d);
|
||||
|
||||
/* east */
|
||||
glTexCoord3f(50.f, -50.f, 50.f);
|
||||
glVertex3f(50.f, -50.f, 50.f);
|
||||
glTexCoord3f(50.f, 50.f, 50.f);
|
||||
glVertex3f(50.f, 50.f, 50.f);
|
||||
glTexCoord3f(50.f, 50.f, -50.f);
|
||||
glVertex3f(50.f, 50.f, -50.f);
|
||||
glTexCoord3f(50.f, -50.f, -50.f);
|
||||
glVertex3f(50.f, -50.f, -50.f);
|
||||
glTexCoord3f(d, -d, d);
|
||||
glVertex3f(d, -d, d);
|
||||
glTexCoord3f(d, d, d);
|
||||
glVertex3f(d, d, d);
|
||||
glTexCoord3f(d, d, -d);
|
||||
glVertex3f(d, d, -d);
|
||||
glTexCoord3f(d, -d, -d);
|
||||
glVertex3f(d, -d, -d);
|
||||
|
||||
/* west */
|
||||
glTexCoord3f(-50.f, -50.f, 50.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
glTexCoord3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glTexCoord3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glTexCoord3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glTexCoord3f(-d, -d, d);
|
||||
glVertex3f(-d, -d, d);
|
||||
glTexCoord3f(-d, -d, -d);
|
||||
glVertex3f(-d, -d, -d);
|
||||
glTexCoord3f(-d, d, -d);
|
||||
glVertex3f(-d, d, -d);
|
||||
glTexCoord3f(-d, d, d);
|
||||
glVertex3f(-d, d, d);
|
||||
|
||||
/* north */
|
||||
glTexCoord3f(-50.f, -50.f, 50.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
glTexCoord3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glTexCoord3f(50.f, 50.f, 50.f);
|
||||
glVertex3f(50.f, 50.f, 50.f);
|
||||
glTexCoord3f(50.f, -50.f, 50.f);
|
||||
glVertex3f(50.f, -50.f, 50.f);
|
||||
glTexCoord3f(-d, -d, d);
|
||||
glVertex3f(-d, -d, d);
|
||||
glTexCoord3f(-d, d, d);
|
||||
glVertex3f(-d, d, d);
|
||||
glTexCoord3f(d, d, d);
|
||||
glVertex3f(d, d, d);
|
||||
glTexCoord3f(d, -d, d);
|
||||
glVertex3f(d, -d, d);
|
||||
|
||||
/* south */
|
||||
glTexCoord3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glTexCoord3f(50.f, -50.f, -50.f);
|
||||
glVertex3f(50.f, -50.f, -50.f);
|
||||
glTexCoord3f(50.f, 50.f, -50.f);
|
||||
glVertex3f(50.f, 50.f, -50.f);
|
||||
glTexCoord3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glTexCoord3f(-d, -d, -d);
|
||||
glVertex3f(-d, -d, -d);
|
||||
glTexCoord3f(d, -d, -d);
|
||||
glVertex3f(d, -d, -d);
|
||||
glTexCoord3f(d, d, -d);
|
||||
glVertex3f(d, d, -d);
|
||||
glTexCoord3f(-d, d, -d);
|
||||
glVertex3f(-d, d, -d);
|
||||
} glEnd();
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
#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) {
|
||||
@ -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 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[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[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;
|
||||
}
|
||||
@ -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 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[1].y = 2.0f * tb;
|
||||
result.row[2].z = 2.0f * fn;
|
||||
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].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;
|
||||
|
||||
return result;
|
||||
|
@ -12,8 +12,9 @@ typedef struct Camera {
|
||||
Vec3 pos; /* eye position */
|
||||
Vec3 target; /* normalized target vector */
|
||||
Vec3 up; /* normalized up vector */
|
||||
float fov; /* field of view, in radians */
|
||||
Vec2 viewbox[2]; /* othrographic aabb, ((left, right), (top, bottom)) */
|
||||
float fov; /* field of view, in radians */
|
||||
float far_z;
|
||||
} Camera;
|
||||
|
||||
Matrix4 camera_look_at(const Camera *camera);
|
||||
|
@ -631,7 +631,7 @@ static bool initialize(void) {
|
||||
|
||||
input_state_init(&ctx.input);
|
||||
|
||||
ctx.render_double_buffered = true;
|
||||
ctx.render_double_buffered = false;
|
||||
ctx.window_mouse_resident = true;
|
||||
|
||||
ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */
|
||||
|
Loading…
Reference in New Issue
Block a user