render: render distance 8, actually 28 FPS
The previous 30 FPS was a lie; it forgot blatant problems with the computation. This is now fixed with 28 FPS on a full 10-side cylinder of render distance 8... which is definitely impressive at full resolution. Actual performance in game will be better due to way fewer platforms.
This commit is contained in:
parent
b9e01bc1ef
commit
37d068e628
34
src/main.cpp
34
src/main.cpp
|
@ -4,10 +4,18 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/timer.h>
|
||||
#include <gint/cpu.h>
|
||||
#include <azur/gint/render.h>
|
||||
#include <gint/drivers/r61524.h>
|
||||
#include <fxlibc/printf.h>
|
||||
|
||||
#define RGB24(hex) \
|
||||
(((hex & 0xf80000) >> 8) | \
|
||||
((hex & 0x00fc00) >> 5) | \
|
||||
((hex & 0x0000f8) >> 3))
|
||||
|
||||
constexpr int bg = RGB24(0x49759f);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
__printf_enable_fp();
|
||||
|
@ -19,9 +27,12 @@ int main(void)
|
|||
// azrp_shader_image_p4_configure();
|
||||
azrp_shader_triangle_configure();
|
||||
|
||||
render_init();
|
||||
|
||||
level_t level = level_create(1);
|
||||
|
||||
int volatile need_frame = 1;
|
||||
int last_frame_us = 0;
|
||||
int timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
|
||||
timer_start(timer);
|
||||
|
||||
|
@ -33,8 +44,12 @@ int main(void)
|
|||
|
||||
bool game_run = true;
|
||||
while(game_run) {
|
||||
while(!need_frame) sleep();
|
||||
|
||||
num dt = 1.0 / 30;
|
||||
t += dt;
|
||||
prof_t perf_frame = prof_make();
|
||||
prof_enter_norec(perf_frame);
|
||||
|
||||
level_update(&level);
|
||||
|
||||
|
@ -43,12 +58,15 @@ int main(void)
|
|||
//---
|
||||
|
||||
azrp_perf_clear();
|
||||
azrp_clear(C_WHITE);
|
||||
azrp_clear(bg);
|
||||
|
||||
struct camera camera;
|
||||
camera.pos = vec3(0, RENDER_CAMERA_DEPTH, 0);
|
||||
vec2 screen_size(DWIDTH, DHEIGHT);
|
||||
|
||||
prof_t perf_comp = prof_make();
|
||||
prof_enter_norec(perf_comp);
|
||||
|
||||
for(int depth = RENDER_SECTION_DISTANCE - 1; depth >= 0; depth--) {
|
||||
num z = depth * RENDER_SECTION_LENGTH - level_z;
|
||||
|
||||
|
@ -59,21 +77,24 @@ int main(void)
|
|||
|
||||
struct prect p = render_platform_position(i, z);
|
||||
/* Near plane clipping */
|
||||
if(p.fl.z <= num(0.1) || p.fr.z <= num(0.1)) continue;
|
||||
if(p.fl.z <= num(0.1)) continue;
|
||||
if(p.nl.z <= num(0.1)) p.nl.z = num(0.1);
|
||||
if(p.nr.z <= num(0.1)) p.nr.z = num(0.1);
|
||||
|
||||
camera_project_prect(&camera, &p, screen_size);
|
||||
|
||||
render_triangle(&p.nl, &p.fr, &p.fl, color);
|
||||
render_triangle(&p.fr, &p.nl, &p.nr, color);
|
||||
}
|
||||
}
|
||||
prof_leave_norec(perf_comp);
|
||||
azrp_update();
|
||||
|
||||
drect(0, DHEIGHT-20, DWIDTH-1, DHEIGHT-1, C_WHITE);
|
||||
dprint(1, 210, C_BLACK, "render:%4d+%4dus level_z=%f",
|
||||
dprint(4, 209, C_BLACK, "render:%4d+%4dus comp:%4dus(%02d FPS)",
|
||||
prof_time(azrp_perf_render) - prof_time(azrp_perf_r61524),
|
||||
prof_time(azrp_perf_r61524),
|
||||
prof_time(perf_comp),
|
||||
last_frame_us ? 1000000 / last_frame_us : 0,
|
||||
(float)level_z);
|
||||
r61524_display(gint_vram, DHEIGHT-20, 20, R61524_DMA_WAIT);
|
||||
|
||||
|
@ -109,6 +130,11 @@ int main(void)
|
|||
level_z -= RENDER_SECTION_LENGTH;
|
||||
sections_passed++;
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
prof_leave_norec(perf_frame);
|
||||
last_frame_us = prof_time(perf_frame);
|
||||
}
|
||||
|
||||
timer_stop(timer);
|
||||
|
|
100
src/render.cpp
100
src/render.cpp
|
@ -10,6 +10,28 @@ static float get_alpha(void)
|
|||
return 2 * 3.14159 / PLATFORM_COUNT;
|
||||
}
|
||||
|
||||
num num_cos_dl(num a)
|
||||
{
|
||||
num u = 1.0;
|
||||
int p = 7;
|
||||
for(p = 2 * p - 1; p >= 1; p -= 2)
|
||||
u = num(1) - a * a / (p * p + p) * u;
|
||||
return u;
|
||||
}
|
||||
|
||||
num num_cos(num a)
|
||||
{
|
||||
if(a < 0) a = -a;
|
||||
a = a % num(6.28319);
|
||||
if(a > num(3.14159)) a -= num(6.28319);
|
||||
return num_cos_dl(a);
|
||||
}
|
||||
|
||||
num num_sin(num a)
|
||||
{
|
||||
return num_cos(a - num(1.57080));
|
||||
}
|
||||
|
||||
/* Get enlargement factor from FOV */
|
||||
float get_near_plane(void)
|
||||
{
|
||||
|
@ -17,31 +39,41 @@ float get_near_plane(void)
|
|||
return 2 * atanf(1 / fov_radians);
|
||||
}
|
||||
|
||||
vec3 vec_rotate_around_z(vec3 v, float angle)
|
||||
{
|
||||
float sin_f, cos_f;
|
||||
sincosf(angle, &sin_f, &cos_f);
|
||||
num s=sin_f, c=cos_f;
|
||||
static vec2 alpha_rotations[PLATFORM_COUNT];
|
||||
|
||||
vec3 u;
|
||||
u.x = c * v.x - s * v.y;
|
||||
u.y = c * v.y + s * v.x;
|
||||
u.z = v.z;
|
||||
return u;
|
||||
/* We can't use a constructor function because g++ already generates one which
|
||||
uses the default 0-constructor and it would run after us, overriding the
|
||||
computed values. */
|
||||
void render_init(void)
|
||||
{
|
||||
float alpha = get_alpha();
|
||||
|
||||
for(int i = 0; i < PLATFORM_COUNT; i++) {
|
||||
num angle = num(-alpha * i + (alpha / 2));
|
||||
alpha_rotations[i] = vec2(num_cos(angle), num_sin(angle));
|
||||
}
|
||||
}
|
||||
|
||||
vec3 vec_rotate_around_z(vec3 v, vec2 rotator)
|
||||
{
|
||||
num c = rotator.x;
|
||||
num s = rotator.y;
|
||||
return vec3(
|
||||
c * v.x - s * v.y,
|
||||
c * v.y + s * v.x,
|
||||
v.z);
|
||||
}
|
||||
|
||||
struct prect render_platform_position(int platform_id, num z)
|
||||
{
|
||||
struct prect r;
|
||||
float alpha = get_alpha();
|
||||
vec3 radius(0, RENDER_RADIUS, 0);
|
||||
|
||||
/* +/- rather than -/+ because right-handed system */
|
||||
float angle_l = alpha * platform_id + (alpha / 2);
|
||||
float angle_r = alpha * platform_id - (alpha / 2);
|
||||
int angle_l = platform_id;
|
||||
int angle_r = (platform_id + 1) % PLATFORM_COUNT;
|
||||
|
||||
r.nl = r.fl = vec_rotate_around_z(radius, angle_l);
|
||||
r.nr = r.fr = vec_rotate_around_z(radius, angle_r);
|
||||
r.nl = r.fl = vec_rotate_around_z(radius, alpha_rotations[angle_l]);
|
||||
r.nr = r.fr = vec_rotate_around_z(radius, alpha_rotations[angle_r]);
|
||||
|
||||
r.nl.z += z;
|
||||
r.nr.z += z;
|
||||
|
@ -56,24 +88,46 @@ vec3 camera_project(struct camera *camera, vec3 u, vec2 screen_size)
|
|||
if(u.z <= 0)
|
||||
return u;
|
||||
|
||||
static float near_plane = get_near_plane();
|
||||
static num near_plane = get_near_plane();
|
||||
|
||||
int screen = screen_size.x < screen_size.y
|
||||
? (int)screen_size.x / 2
|
||||
: (int)screen_size.y / 2;
|
||||
|
||||
u.x = u.x * num(near_plane) * screen / u.z + screen_size.x / 2;
|
||||
u.y = u.y * num(near_plane) * screen / u.z + screen_size.y / 2;
|
||||
num f = near_plane * screen / u.z;
|
||||
u.x = u.x * f + screen_size.x / 2;
|
||||
u.y = u.y * f + screen_size.y / 2;
|
||||
return u;
|
||||
}
|
||||
|
||||
void camera_project_prect(struct camera *camera, struct prect *p,
|
||||
vec2 screen_size)
|
||||
{
|
||||
p->nl = camera_project(camera, p->nl, screen_size);
|
||||
p->nr = camera_project(camera, p->nr, screen_size);
|
||||
p->fl = camera_project(camera, p->fl, screen_size);
|
||||
p->fr = camera_project(camera, p->fr, screen_size);
|
||||
/* Require the rectangle to be already clipped */
|
||||
if(p->nl.z <= camera->pos.z)
|
||||
return;
|
||||
|
||||
static num near_plane = get_near_plane();
|
||||
|
||||
vec3 half_screen(screen_size.x / 2, screen_size.y / 2, 0);
|
||||
int screen = half_screen.x < half_screen.y
|
||||
? (int)half_screen.x
|
||||
: (int)half_screen.y;
|
||||
|
||||
p->nl -= camera->pos;
|
||||
p->nr -= camera->pos;
|
||||
p->fl -= camera->pos;
|
||||
p->fr -= camera->pos;
|
||||
|
||||
/* We assume nl/nr have the same z, and so do fl/fr */
|
||||
num f = near_plane * screen;
|
||||
num near_f = f / p->nl.z;
|
||||
num far_f = f / p->fl.z;
|
||||
|
||||
p->nl = p->nl * near_f + half_screen;
|
||||
p->nr = p->nr * near_f + half_screen;
|
||||
p->fl = p->fl * far_f + half_screen;
|
||||
p->fr = p->fr * far_f + half_screen;
|
||||
}
|
||||
|
||||
void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color)
|
||||
|
|
|
@ -14,20 +14,22 @@ using namespace libnum;
|
|||
/* Section lengths, in world units */
|
||||
#define RENDER_SECTION_LENGTH num(4.0)
|
||||
/* Number of sections visible in advance */
|
||||
#define RENDER_SECTION_DISTANCE 5
|
||||
#define RENDER_SECTION_DISTANCE 8
|
||||
|
||||
struct prect {
|
||||
vec3 nl, nr; /* Near left and near right points */
|
||||
vec3 fl, fr; /* Far left and far right points */
|
||||
};
|
||||
|
||||
struct prect render_platform_position(int platform_id, num z);
|
||||
|
||||
/* We assume the camera is looking towards (0,0,z) */
|
||||
struct camera {
|
||||
vec3 pos;
|
||||
};
|
||||
|
||||
void render_init(void);
|
||||
|
||||
struct prect render_platform_position(int platform_id, num z);
|
||||
|
||||
vec3 camera_project(struct camera *camera, vec3 u, vec2 screen_size);
|
||||
|
||||
void camera_project_prect(struct camera *camera, struct prect *p,
|
||||
|
|
Loading…
Reference in New Issue