shithub: libgraphics

Download patch

ref: 213c3a4e99c3085ee89fda550897213abbc888ad
parent: 239a319b41474a35e4c9c4b7c6ae3c6e0b0b7185
author: rodri <rgl@antares-labs.eu>
date: Mon Jun 10 11:59:57 EDT 2024

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.

--- a/graphics.h
+++ b/graphics.h
@@ -104,8 +104,12 @@
 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,6 +334,8 @@
 /* util */
 double fmin(double, double);
 double fmax(double, double);
+Point2 modulapt2(Point2, Point2);
+Point3 modulapt3(Point3, Point3);
 Memimage *rgb(ulong);
 
 /* shadeop */
@@ -336,5 +342,6 @@
 double sign(double);
 double step(double, double);
 double smoothstep(double, double, double);
+Color getlightcolor(LightSource*, Point3);
 
 extern Rectangle UR;	/* unit rectangle */
--- a/render.c
+++ b/render.c
@@ -15,10 +15,10 @@
 {
 	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];
 }
 
--- a/scene.c
+++ b/scene.c
@@ -159,18 +159,9 @@
 				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 @@
 clearscene(Scene *s)
 {
 	Entity *e, *ne;
-	int i;
 
 	for(e = s->ents.next; e != &s->ents; e = ne){
 		ne = e->next;
--- a/shadeop.c
+++ b/shadeop.c
@@ -30,3 +30,21 @@
 	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;
+}
--- a/util.c
+++ b/util.c
@@ -52,6 +52,18 @@
 	*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)
 {
--- a/vertex.c
+++ b/vertex.c
@@ -43,6 +43,9 @@
 	return nv;
 }
 
+/*
+ * linear attribute interpolation
+ */
 void
 lerpvertex(Vertex *v, Vertex *v0, Vertex *v1, double t)
 {
@@ -68,7 +71,7 @@
 }
 
 /*
- * perspective-correct barycentric attribute interpolation
+ * barycentric attribute interpolation
  */
 void
 berpvertex(Vertex *v, Vertex *v0, Vertex *v1, Vertex *v2, Point3 bc)