From 213c3a4e99c3085ee89fda550897213abbc888ad Mon Sep 17 00:00:00 2001 From: rodri Date: Mon, 10 Jun 2024 15:59:57 +0000 Subject: add spotlight params and a light color shading routine. other things. among these other things are clamping the color channels to [0,1] internally, and adding a modulation function for mixing colors/points. --- graphics.h | 7 +++++++ render.c | 8 ++++---- scene.c | 16 +++------------- shadeop.c | 18 ++++++++++++++++++ util.c | 12 ++++++++++++ vertex.c | 5 ++++- 6 files changed, 48 insertions(+), 18 deletions(-) diff --git a/graphics.h b/graphics.h index b7cfdce..b30dd9f 100644 --- a/graphics.h +++ b/graphics.h @@ -104,8 +104,12 @@ struct Vertex struct LightSource { Point3 p; + Point3 dir; Color c; int type; + /* spotlights */ + double θu; /* umbra angle. anything beyond is unlit */ + double θp; /* penumbra angle. anything within is fully lit */ }; struct Material @@ -330,11 +334,14 @@ Color cubemaptexture(Cubemap*, Point3, Color(*)(Memimage*, Point2)); /* util */ double fmin(double, double); double fmax(double, double); +Point2 modulapt2(Point2, Point2); +Point3 modulapt3(Point3, Point3); Memimage *rgb(ulong); /* shadeop */ double sign(double); double step(double, double); double smoothstep(double, double, double); +Color getlightcolor(LightSource*, Point3); extern Rectangle UR; /* unit rectangle */ diff --git a/render.c b/render.c index 91cf039..469605e 100644 --- a/render.c +++ b/render.c @@ -15,10 +15,10 @@ col2ul(Color c) { uchar cbuf[4]; - cbuf[0] = c.a*0xFF; - cbuf[1] = c.b*0xFF; - cbuf[2] = c.g*0xFF; - cbuf[3] = c.r*0xFF; + cbuf[0] = fclamp(c.a, 0, 1)*0xFF; + cbuf[1] = fclamp(c.b, 0, 1)*0xFF; + cbuf[2] = fclamp(c.g, 0, 1)*0xFF; + cbuf[3] = fclamp(c.r, 0, 1)*0xFF; return cbuf[3]<<24 | cbuf[2]<<16 | cbuf[1]<<8 | cbuf[0]; } diff --git a/scene.c b/scene.c index 5cd547e..f003e83 100644 --- a/scene.c +++ b/scene.c @@ -159,18 +159,9 @@ loadobjmodel(Model *m, OBJ *obj) if(mtl->name == nil) sysfatal("strdup: %r"); } - mtl->ambient.r = objmtl->Ka.r; - mtl->ambient.g = objmtl->Ka.g; - mtl->ambient.b = objmtl->Ka.b; - mtl->ambient.a = 1; - mtl->diffuse.r = objmtl->Kd.r; - mtl->diffuse.g = objmtl->Kd.g; - mtl->diffuse.b = objmtl->Kd.b; - mtl->diffuse.a = 1; - mtl->specular.r = objmtl->Ks.r; - mtl->specular.g = objmtl->Ks.g; - mtl->specular.b = objmtl->Ks.b; - mtl->specular.a = 1; + mtl->ambient = Pt3(objmtl->Ka.r, objmtl->Ka.g, objmtl->Ka.b, 1); + mtl->diffuse = Pt3(objmtl->Kd.r, objmtl->Kd.g, objmtl->Kd.b, 1); + mtl->specular = Pt3(objmtl->Ks.r, objmtl->Ks.g, objmtl->Ks.b, 1); mtl->shininess = objmtl->Ns; if(objmtl->map_Kd != nil){ @@ -419,7 +410,6 @@ void clearscene(Scene *s) { Entity *e, *ne; - int i; for(e = s->ents.next; e != &s->ents; e = ne){ ne = e->next; diff --git a/shadeop.c b/shadeop.c index c6080e3..4b74256 100644 --- a/shadeop.c +++ b/shadeop.c @@ -30,3 +30,21 @@ smoothstep(double edge0, double edge1, double n) t = fclamp((n-edge0)/(edge1-edge0), 0, 1); return t*t * (3 - 2*t); } + +/* TODO apply attenuation for punctual lights */ +Color +getlightcolor(LightSource *l, Point3 dir) +{ + double cθs, cθu, cθp, t; + + /* see “Spotlights”, Real-Time Rendering 4th ed. § 5.2.2 */ + if(l->type == LIGHT_SPOT){ + cθs = dotvec3(mulpt3(dir, -1), l->dir); + cθu = cos(l->θu); + cθp = cos(l->θp); +// return mulpt3(l->c, smoothstep(cθu, cθp, cθs)); + t = fclamp((cθs - cθu)/(cθp - cθu), 0, 1); + return mulpt3(l->c, t*t); + } + return l->c; +} diff --git a/util.c b/util.c index e114da5..db538a3 100644 --- a/util.c +++ b/util.c @@ -52,6 +52,18 @@ swappt(Point *a, Point *b) *b = t; } +Point2 +modulapt2(Point2 a, Point2 b) +{ + return (Point2){a.x*b.x, a.y*b.y, a.w*b.w}; +} + +Point3 +modulapt3(Point3 a, Point3 b) +{ + return (Point3){a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; +} + void memsetd(double *p, double v, usize len) { diff --git a/vertex.c b/vertex.c index bc7759f..204c6fc 100644 --- a/vertex.c +++ b/vertex.c @@ -43,6 +43,9 @@ dupvertex(Vertex *v) return nv; } +/* + * linear attribute interpolation + */ void lerpvertex(Vertex *v, Vertex *v0, Vertex *v1, double t) { @@ -68,7 +71,7 @@ lerpvertex(Vertex *v, Vertex *v0, Vertex *v1, double t) } /* - * perspective-correct barycentric attribute interpolation + * barycentric attribute interpolation */ void berpvertex(Vertex *v, Vertex *v0, Vertex *v1, Vertex *v2, Point3 bc) -- cgit v1.2.3