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:
Lephenixnoir 2022-08-20 19:46:41 +02:00
parent b9e01bc1ef
commit 37d068e628
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 112 additions and 30 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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,