summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-06-10 15:59:57 +0000
committerrodri <rgl@antares-labs.eu>2024-06-10 15:59:57 +0000
commit213c3a4e99c3085ee89fda550897213abbc888ad (patch)
tree6dead68a5f64ca4d23285ab3dd13a7a36e4fea92
parent239a319b41474a35e4c9c4b7c6ae3c6e0b0b7185 (diff)
downloadlibgraphics-213c3a4e99c3085ee89fda550897213abbc888ad.tar.gz
libgraphics-213c3a4e99c3085ee89fda550897213abbc888ad.tar.bz2
libgraphics-213c3a4e99c3085ee89fda550897213abbc888ad.zip
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.
-rw-r--r--graphics.h7
-rw-r--r--render.c8
-rw-r--r--scene.c16
-rw-r--r--shadeop.c18
-rw-r--r--util.c12
-rw-r--r--vertex.c5
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)