diff options
author | rodri <rgl@antares-labs.eu> | 2024-07-13 10:23:52 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2024-07-13 10:23:52 +0000 |
commit | 04d50b8bbe324fdb7a8a1e724fbc59c4050862f0 (patch) | |
tree | 285be4b648747346d96e5e0c87d0abec9f80d6a5 /camera.c | |
parent | 45c21bb2483adf0ad1dd2f9950681f6a07a14b24 (diff) | |
download | libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.tar.gz libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.tar.bz2 libgraphics-04d50b8bbe324fdb7a8a1e724fbc59c4050862f0.zip |
fix the geometry glitches when moving things around.
it's possible for interactive programs to keep updating
the geometry of the scene during rendering, which caused
primitives to look deformed or shattered in the final
image.
to avoid this we take a snapshot of the current state of
things (scene and camera), and render based on that copy.
Diffstat (limited to 'camera.c')
-rw-r--r-- | camera.c | 67 |
1 files changed, 39 insertions, 28 deletions
@@ -106,6 +106,36 @@ verifycfg(Camera *c) assert(c->clip.n > 0 && c->clip.n < c->clip.f); } +/* TODO the current camera abstraction is quite dirty, not pleasant to work with. make it better. */ +//Camera * +//Cam(Camcfg cfg) +//{ +// +//} + +void +reloadcamera(Camera *c) +{ + double a; + double l, r, b, t; + + verifycfg(c); + switch(c->projtype){ + case ORTHOGRAPHIC: + r = Dx(c->vp->fbctl->fb[0]->r)/2; + t = Dy(c->vp->fbctl->fb[0]->r)/2; + l = -r; + b = -t; + orthographic(c->proj, l, r, b, t, c->clip.n, c->clip.f); + break; + case PERSPECTIVE: + a = (double)Dx(c->vp->fbctl->fb[0]->r)/Dy(c->vp->fbctl->fb[0]->r); + perspective(c->proj, c->fov, a, c->clip.n, c->clip.f); + break; + default: sysfatal("unknown projection type"); + } +} + void configcamera(Camera *c, Viewport *v, double fov, double n, double f, Projection p) { @@ -133,29 +163,6 @@ aimcamera(Camera *c, Point3 focus) } void -reloadcamera(Camera *c) -{ - double a; - double l, r, b, t; - - verifycfg(c); - switch(c->projtype){ - case ORTHOGRAPHIC: - r = Dx(c->vp->fbctl->fb[0]->r)/2; - t = Dy(c->vp->fbctl->fb[0]->r)/2; - l = -r; - b = -t; - orthographic(c->proj, l, r, b, t, c->clip.n, c->clip.f); - break; - case PERSPECTIVE: - a = (double)Dx(c->vp->fbctl->fb[0]->r)/Dy(c->vp->fbctl->fb[0]->r); - perspective(c->proj, c->fov, a, c->clip.n, c->clip.f); - break; - default: sysfatal("unknown projection type"); - } -} - -void shootcamera(Camera *c, Shadertab *s) { static Scene *skyboxscene; @@ -167,8 +174,9 @@ shootcamera(Camera *c, Shadertab *s) job = emalloc(sizeof *job); memset(job, 0, sizeof *job); job->fb = c->vp->fbctl->getbb(c->vp->fbctl); - job->camera = c; - job->scene = c->scene; + job->camera = emalloc(sizeof *c); + *job->camera = *c; + job->scene = dupscene(c->scene); /* take a snapshot */ job->shaders = s; job->donec = chancreate(sizeof(void*), 0); @@ -176,21 +184,23 @@ shootcamera(Camera *c, Shadertab *s) t0 = nanosec(); sendp(c->rctl->c, job); recvp(job->donec); + delscene(job->scene); /* destroy the snapshot */ /* * if the scene has a skybox, do another render pass, - * filling in the fragments left untouched by the z-buffer. + * filling in the pixels left untouched. */ if(c->scene->skybox != nil){ if(skyboxscene == nil){ skyboxscene = newscene("skybox"); mdl = mkskyboxmodel(); - skyboxscene->addent(skyboxscene, newentity(mdl)); + skyboxscene->addent(skyboxscene, newentity("skybox", mdl)); } skyboxscene->skybox = c->scene->skybox; - job->scene = skyboxscene; + job->scene = dupscene(skyboxscene); job->shaders = &skyboxshader; sendp(c->rctl->c, job); recvp(job->donec); + delscene(job->scene); } t1 = nanosec(); c->vp->fbctl->swap(c->vp->fbctl); @@ -199,5 +209,6 @@ shootcamera(Camera *c, Shadertab *s) updatetimes(c, job); chanfree(job->donec); + free(job->camera); free(job); } |