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)