ref: 596647fb035740e178293a37faef8b6af5f6e428
parent: df239037125072efca28411d29f94ed46b31c470
author: rodri <rgl@antares-labs.eu>
date: Sun Apr 6 20:07:25 EDT 2025
small optimizations
--- a/camera.c
+++ b/camera.c
@@ -99,7 +99,7 @@
{
Camera *c;
- if(v == nil || r == nil)
+ if(v == nil)
return nil;
c = newcamera();
--- a/clip.c
+++ b/clip.c
@@ -191,11 +191,11 @@
dp = subpt3(v1->p, v0->p);
len = hypot(dp.x, dp.y);
- Δp = subpt(Pt(v0->p.x, v0->p.y), *p0);
+ Δp = subpt((Point){v0->p.x, v0->p.y}, *p0);
perc = len == 0? 0: hypot(Δp.x, Δp.y)/len;
_lerpvertex(&v[0], v0, v1, perc);
- Δp = subpt(Pt(v0->p.x, v0->p.y), *p1);
+ Δp = subpt((Point){v0->p.x, v0->p.y}, *p1);
perc = len == 0? 0: hypot(Δp.x, Δp.y)/len;
_lerpvertex(&v[1], v0, v1, perc);
--- a/render.c
+++ b/render.c
@@ -165,14 +165,58 @@
}
static void
-rasterize(Rastertask *task)
+rasterizept(Rastertask *task)
{
SUparams *params;
Raster *cr, *zr;
Primitive *prim;
- Triangle2 t;
+ Point p;
+ Color c;
+ float z;
+ uint ropts;
+
+ params = task->params;
+ prim = &task->p;
+
+ cr = params->fb->rasters;
+ zr = cr->next;
+
+ ropts = params->camera->rendopts;
+
+ p = (Point){prim->v[0].p.x, prim->v[0].p.y};
+
+ z = fclamp(prim->v[0].p.z, 0, 1);
+ if((ropts & RODepth) && z <= getdepth(zr, p))
+ return;
+
+ *task->fsp->v = prim->v[0];
+ task->fsp->p = p;
+ c = params->stab->fs(task->fsp);
+ if(c.a == 0) /* discard non-colors */
+ return;
+ if(ropts & RODepth)
+ putdepth(zr, p, z);
+ if(ropts & ROAbuff)
+ pushtoAbuf(params->fb, p, c, z);
+ else
+ pixel(cr, p, c, ropts & ROBlend);
+
+ if(task->clipr->min.x < 0){
+ task->clipr->min = p;
+ task->clipr->max = addpt(p, (Point){1,1});
+ }else{
+ task->clipr->min = minpt(task->clipr->min, p);
+ task->clipr->max = maxpt(task->clipr->max, addpt(p, (Point){1,1}));
+ }
+}
+
+static void
+rasterizeline(Rastertask *task)
+{
+ SUparams *params;
+ Raster *cr, *zr;
+ Primitive *prim;
Point p, dp, Δp, p0, p1;
- Point3 bc;
Color c;
double dplen, perc;
float z, pcz;
@@ -187,19 +231,56 @@
ropts = params->camera->rendopts;
- switch(prim->type){
- case PPoint:
- p = Pt(prim->v[0].p.x, prim->v[0].p.y);
+ p0 = (Point){prim->v[0].p.x, prim->v[0].p.y};
+ p1 = (Point){prim->v[1].p.x, prim->v[1].p.y};
+ /* clip it against our wr */
+ if(_rectclipline(task->wr, &p0, &p1, prim->v+0, prim->v+1) < 0)
+ return;
- z = fclamp(prim->v[0].p.z, 0, 1);
- if((ropts & RODepth) && z <= getdepth(zr, p))
- break;
+ steep = 0;
+ /* transpose the points */
+ if(abs(p0.x-p1.x) < abs(p0.y-p1.y)){
+ steep = 1;
+ SWAP(int, &p0.x, &p0.y);
+ SWAP(int, &p1.x, &p1.y);
+ }
- *task->fsp->v = prim->v[0];
+ /* make them left-to-right */
+ if(p0.x > p1.x){
+ SWAP(Point, &p0, &p1);
+ SWAP(Vertex, prim->v+0, prim->v+1);
+ }
+
+ dp = subpt(p1, p0);
+ Δe = 2*abs(dp.y);
+ e = 0;
+ Δy = p1.y > p0.y? 1: -1;
+
+ for(p = p0; p.x <= p1.x; p.x++){
+ Δp = subpt(p, p0);
+ dplen = hypot(dp.x, dp.y);
+ perc = dplen == 0? 0: hypot(Δp.x, Δp.y)/dplen;
+
+ if(steep) SWAP(int, &p.x, &p.y);
+
+ z = flerp(prim->v[0].p.z, prim->v[1].p.z, perc);
+ /* TODO get rid of the bounds check and make sure the clipping doesn't overflow */
+ if(!ptinrect(p, params->fb->r) ||
+ ((ropts & RODepth) && z <= getdepth(zr, p)))
+ goto discard;
+
+ /* interpolate z⁻¹ and get actual z */
+ pcz = flerp(prim->v[0].p.w, prim->v[1].p.w, perc);
+ pcz = 1.0/(pcz < ε1? ε1: pcz);
+
+ /* perspective-correct attribute interpolation */
+ perc *= prim->v[0].p.w * pcz;
+ _lerpvertex(task->fsp->v, prim->v+0, prim->v+1, perc);
+
task->fsp->p = p;
c = params->stab->fs(task->fsp);
if(c.a == 0) /* discard non-colors */
- break;
+ goto discard;
if(ropts & RODepth)
putdepth(zr, p, z);
if(ropts & ROAbuff)
@@ -209,135 +290,87 @@
if(task->clipr->min.x < 0){
task->clipr->min = p;
- task->clipr->max = addpt(p, Pt(1,1));
+ task->clipr->max = addpt(p, (Point){1,1});
}else{
task->clipr->min = minpt(task->clipr->min, p);
- task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1)));
+ task->clipr->max = maxpt(task->clipr->max, addpt(p, (Point){1,1}));
}
- break;
- case PLine:
- p0 = Pt(prim->v[0].p.x, prim->v[0].p.y);
- p1 = Pt(prim->v[1].p.x, prim->v[1].p.y);
- /* clip it against our wr */
- if(_rectclipline(task->wr, &p0, &p1, prim->v+0, prim->v+1) < 0)
- break;
+discard:
+ if(steep) SWAP(int, &p.x, &p.y);
- steep = 0;
- /* transpose the points */
- if(abs(p0.x-p1.x) < abs(p0.y-p1.y)){
- steep = 1;
- SWAP(int, &p0.x, &p0.y);
- SWAP(int, &p1.x, &p1.y);
+ e += Δe;
+ if(e > dp.x){
+ p.y += Δy;
+ e -= 2*dp.x;
}
+ }
+}
- /* make them left-to-right */
- if(p0.x > p1.x){
- SWAP(Point, &p0, &p1);
- SWAP(Vertex, prim->v+0, prim->v+1);
- }
+static void
+rasterizetri(Rastertask *task)
+{
+ SUparams *params;
+ Raster *cr, *zr;
+ Primitive *prim;
+ Triangle2 t;
+ Point p;
+ Point3 bc;
+ Color c;
+ float z, pcz;
+ uint ropts;
- dp = subpt(p1, p0);
- Δe = 2*abs(dp.y);
- e = 0;
- Δy = p1.y > p0.y? 1: -1;
+ params = task->params;
+ prim = &task->p;
- for(p = p0; p.x <= p1.x; p.x++){
- Δp = subpt(p, p0);
- dplen = hypot(dp.x, dp.y);
- perc = dplen == 0? 0: hypot(Δp.x, Δp.y)/dplen;
+ cr = params->fb->rasters;
+ zr = cr->next;
- if(steep) SWAP(int, &p.x, &p.y);
+ ropts = params->camera->rendopts;
- z = flerp(prim->v[0].p.z, prim->v[1].p.z, perc);
- /* TODO get rid of the bounds check and make sure the clipping doesn't overflow */
- if(!ptinrect(p, params->fb->r) ||
- ((ropts & RODepth) && z <= getdepth(zr, p)))
- goto discard;
+ t.p0 = (Point2){prim->v[0].p.x, prim->v[0].p.y, 1};
+ t.p1 = (Point2){prim->v[1].p.x, prim->v[1].p.y, 1};
+ t.p2 = (Point2){prim->v[2].p.x, prim->v[2].p.y, 1};
- /* interpolate z⁻¹ and get actual z */
- pcz = flerp(prim->v[0].p.w, prim->v[1].p.w, perc);
- pcz = 1.0/(pcz < ε1? ε1: pcz);
+ _perspdiv(prim->v+0, prim->v[0].p.w);
+ _perspdiv(prim->v+1, prim->v[1].p.w);
+ _perspdiv(prim->v+2, prim->v[2].p.w);
- /* perspective-correct attribute interpolation */
- perc *= prim->v[0].p.w * pcz;
- _lerpvertex(task->fsp->v, prim->v+0, prim->v+1, perc);
+ for(p.y = task->wr.min.y; p.y < task->wr.max.y; p.y++)
+ for(p.x = task->wr.min.x; p.x < task->wr.max.x; p.x++){
+ bc = _barycoords(t, (Point2){p.x+0.5,p.y+0.5,1});
+ if(bc.x < 0 || bc.y < 0 || bc.z < 0)
+ continue;
- task->fsp->p = p;
- c = params->stab->fs(task->fsp);
- if(c.a == 0) /* discard non-colors */
- goto discard;
- if(ropts & RODepth)
- putdepth(zr, p, z);
- if(ropts & ROAbuff)
- pushtoAbuf(params->fb, p, c, z);
- else
- pixel(cr, p, c, ropts & ROBlend);
+ z = fberp(prim->v[0].p.z, prim->v[1].p.z, prim->v[2].p.z, bc);
+ if((ropts & RODepth) && z <= getdepth(zr, p))
+ continue;
- if(task->clipr->min.x < 0){
- task->clipr->min = p;
- task->clipr->max = addpt(p, Pt(1,1));
- }else{
- task->clipr->min = minpt(task->clipr->min, p);
- task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1)));
- }
-discard:
- if(steep) SWAP(int, &p.x, &p.y);
+ /* interpolate z⁻¹ and get actual z */
+ pcz = fberp(prim->v[0].p.w, prim->v[1].p.w, prim->v[2].p.w, bc);
+ pcz = 1.0/(pcz < ε1? ε1: pcz);
- e += Δe;
- if(e > dp.x){
- p.y += Δy;
- e -= 2*dp.x;
- }
- }
- break;
- case PTriangle:
- t.p0 = Pt2(prim->v[0].p.x, prim->v[0].p.y, 1);
- t.p1 = Pt2(prim->v[1].p.x, prim->v[1].p.y, 1);
- t.p2 = Pt2(prim->v[2].p.x, prim->v[2].p.y, 1);
+ /* perspective-correct attribute interpolation */
+ bc = mulpt3(bc, pcz);
+ _berpvertex(task->fsp->v, prim->v+0, prim->v+1, prim->v+2, bc);
- _perspdiv(prim->v+0, prim->v[0].p.w);
- _perspdiv(prim->v+1, prim->v[1].p.w);
- _perspdiv(prim->v+2, prim->v[2].p.w);
+ task->fsp->p = p;
+ c = params->stab->fs(task->fsp);
+ if(c.a == 0) /* discard non-colors */
+ continue;
+ if(ropts & RODepth)
+ putdepth(zr, p, z);
+ if(ropts & ROAbuff)
+ pushtoAbuf(params->fb, p, c, z);
+ else
+ pixel(cr, p, c, ropts & ROBlend);
- for(p.y = task->wr.min.y; p.y < task->wr.max.y; p.y++)
- for(p.x = task->wr.min.x; p.x < task->wr.max.x; p.x++){
- bc = _barycoords(t, Pt2(p.x+0.5,p.y+0.5,1));
- if(bc.x < 0 || bc.y < 0 || bc.z < 0)
- continue;
-
- z = fberp(prim->v[0].p.z, prim->v[1].p.z, prim->v[2].p.z, bc);
- if((ropts & RODepth) && z <= getdepth(zr, p))
- continue;
-
- /* interpolate z⁻¹ and get actual z */
- pcz = fberp(prim->v[0].p.w, prim->v[1].p.w, prim->v[2].p.w, bc);
- pcz = 1.0/(pcz < ε1? ε1: pcz);
-
- /* perspective-correct attribute interpolation */
- bc = mulpt3(bc, pcz);
- _berpvertex(task->fsp->v, prim->v+0, prim->v+1, prim->v+2, bc);
-
- task->fsp->p = p;
- c = params->stab->fs(task->fsp);
- if(c.a == 0) /* discard non-colors */
- continue;
- if(ropts & RODepth)
- putdepth(zr, p, z);
- if(ropts & ROAbuff)
- pushtoAbuf(params->fb, p, c, z);
- else
- pixel(cr, p, c, ropts & ROBlend);
-
- if(task->clipr->min.x < 0){
- task->clipr->min = p;
- task->clipr->max = addpt(p, Pt(1,1));
- }else{
- task->clipr->min = minpt(task->clipr->min, p);
- task->clipr->max = maxpt(task->clipr->max, addpt(p, Pt(1,1)));
- }
+ if(task->clipr->min.x < 0){
+ task->clipr->min = p;
+ task->clipr->max = addpt(p, (Point){1,1});
+ }else{
+ task->clipr->min = minpt(task->clipr->min, p);
+ task->clipr->max = maxpt(task->clipr->max, addpt(p, (Point){1,1}));
}
- break;
- default: sysfatal("alien primitive detected");
}
}
@@ -404,7 +437,12 @@
fsp.su = params;
task->fsp = &fsp;
- rasterize(task);
+ switch(task->p.type){
+ case PPoint: rasterizept(task); break;
+ case PLine: rasterizeline(task); break;
+ case PTriangle: rasterizetri(task); break;
+ default: sysfatal("alien primitive detected");
+ }
_delvattrs(&v);
for(i = 0; i < task->p.type+1; i++)