ref: 8674cb151144982ca5146268bad8a6b226fd8b62
parent: 1d61030857e868dee98386e5b07ec98416322d7f
author: rodri <rgl@antares-labs.eu>
date: Fri Aug 23 11:04:21 EDT 2024
correct the gouraud and phong shaders. add a blinn shader.
--- a/med.c
+++ b/med.c
@@ -136,8 +136,7 @@
l.v[0].p = world2model(subject, viewport2world(cam, p[i]));
l.v[1].p = world2model(subject, viewport2world(cam, p[(i+1)%nelem(p)]));
qlock(&scenelk);
- model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims));
- model->prims[model->nprims-1] = l;
+ model->addprim(model, l);
qunlock(&scenelk);
/* middle frame */
@@ -144,8 +143,7 @@
l.v[0].p = world2model(subject, viewport2world(cam, subpt3(p[i], Vec3(0,0,0.5))));
l.v[1].p = world2model(subject, viewport2world(cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,0.5))));
qlock(&scenelk);
- model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims));
- model->prims[model->nprims-1] = l;
+ model->addprim(model, l);
qunlock(&scenelk);
/* back frame */
@@ -152,15 +150,13 @@
l.v[0].p = world2model(subject, viewport2world(cam, subpt3(p[i], Vec3(0,0,1))));
l.v[1].p = world2model(subject, viewport2world(cam, subpt3(p[(i+1)%nelem(p)], Vec3(0,0,1))));
qlock(&scenelk);
- model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims));
- model->prims[model->nprims-1] = l;
+ model->addprim(model, l);
qunlock(&scenelk);
/* struts */
l.v[1].p = world2model(subject, viewport2world(cam, p[i]));
qlock(&scenelk);
- model->prims = erealloc(model->prims, ++model->nprims*sizeof(*model->prims));
- model->prims[model->nprims-1] = l;
+ model->addprim(model, l);
qunlock(&scenelk);
}
}
@@ -186,10 +182,12 @@
t[0].v[1].n = addpt3(p, v1);
t[0].v[2].p = addpt3(center, addpt3(p, addpt3(v1, v2)));
t[0].v[2].n = addpt3(p, addpt3(v1, v2));
+ t[0].v[0].c = t[0].v[1].c = t[0].v[2].c = Pt3(1,1,1,1);
t[1].v[0] = t[0].v[0];
t[1].v[1] = t[0].v[2];
t[1].v[2].p = addpt3(center, addpt3(p, v2));
t[1].v[2].n = addpt3(p, v2);
+ t[1].v[2].c = Pt3(1,1,1,1);
/* make a cube by rotating the reference face */
for(i = 0; i < 6; i++){
@@ -201,9 +199,8 @@
}
qlock(&scenelk);
- model->prims = erealloc(model->prims, (model->nprims += 2)*sizeof(*model->prims));
- model->prims[model->nprims-2] = t[0];
- model->prims[model->nprims-1] = t[1];
+ model->addprim(model, t[0]);
+ model->addprim(model, t[1]);
qunlock(&scenelk);
}
}
@@ -230,8 +227,9 @@
prims[2].v[1].p = addpt3(center, e->bz);
prims[2].v[1].c = Pt3(0,0,1,1);
- m->prims = erealloc(m->prims, (m->nprims += 3)*sizeof(*m->prims));
- memmove(m->prims, prims, sizeof prims);
+ m->addprim(m, prims[0]);
+ m->addprim(m, prims[1]);
+ m->addprim(m, prims[2]);
scene->addent(scene, e);
}
@@ -244,34 +242,40 @@
double Kd; /* diffuse factor */
double spec;
Point3 pos, lightdir, lookdir;
- Material *m;
+ Material m;
Color ambient, diffuse, specular, lightc;
sp->v->n = model2world(sp->su->entity, sp->v->n);
sp->v->p = model2world(sp->su->entity, sp->v->p);
pos = sp->v->p;
- m = sp->v->mtl;
+ if(sp->v->mtl != nil)
+ m = *sp->v->mtl;
+ else{
+ memset(&m, 0, sizeof m);
+ m.diffuse = sp->v->c;
+ m.specular = Pt3(1,1,1,1);
+ m.shininess = 1;
+ }
+
lightdir = normvec3(subpt3(light.p, pos));
lightc = getlightcolor(&light, lightdir);
ambient = mulpt3(lightc, Ka);
- if(m != nil)
- ambient = modulapt3(ambient, m->ambient);
+ ambient = modulapt3(ambient, m.diffuse);
Kd = fmax(0, dotvec3(sp->v->n, lightdir));
diffuse = mulpt3(lightc, Kd);
- if(m != nil)
- diffuse = modulapt3(diffuse, m->diffuse);
+ diffuse = modulapt3(diffuse, m.diffuse);
lookdir = normvec3(subpt3(sp->su->camera->p, pos));
lightdir = qrotate(lightdir, sp->v->n, PI);
- spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m? m->shininess: 1);
+ spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess);
specular = mulpt3(lightc, spec*Ks);
- if(m != nil)
- specular = modulapt3(specular, m->specular);
+ specular = modulapt3(specular, m.specular);
sp->v->c = addpt3(ambient, addpt3(diffuse, specular));
+ sp->v->c.a = m.diffuse.a;
return world2clip(sp->su->camera, pos);
}
@@ -278,7 +282,7 @@
Color
gouraudshader(FSparams *sp)
{
- Color tc, c;
+ Color tc;
if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
tc = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
@@ -287,10 +291,7 @@
else
tc = Pt3(1,1,1,1);
- c = modulapt3(sp->v.c, tc);
- c.a = 1;
-
- return c;
+ return modulapt3(sp->v.c, tc);
}
Point3
@@ -304,6 +305,10 @@
sp->v->p = model2world(sp->su->entity, sp->v->p);
pos = sp->v->p;
addvattr(sp->v, "pos", VAPoint, &pos);
+ if(sp->v->mtl != nil && sp->v->mtl->normalmap != nil && sp->v->uv.w != 0){
+ sp->v->tangent = model2world(sp->su->entity, sp->v->tangent);
+ addvattr(sp->v, "tangent", VAPoint, &sp->v->tangent);
+ }
if(sp->v->mtl != nil){
a = sp->v->mtl->ambient;
d = sp->v->mtl->diffuse;
@@ -324,7 +329,7 @@
static double Ks = 0.5; /* specular factor */
double Kd; /* diffuse factor */
double spec;
- Color ambient, diffuse, specular, tc, c, lightc;
+ Color ambient, diffuse, specular, lightc, c;
Point3 pos, n, lightdir, lookdir;
Material m;
RFrame3 TBN;
@@ -336,7 +341,7 @@
va = getvattr(&sp->v, "ambient");
m.ambient = va != nil? va->p: Pt3(1,1,1,1);
va = getvattr(&sp->v, "diffuse");
- m.diffuse = va != nil? va->p: Pt3(1,1,1,1);
+ m.diffuse = va != nil? va->p: sp->v.c;
va = getvattr(&sp->v, "specular");
m.specular = va != nil? va->p: Pt3(1,1,1,1);
va = getvattr(&sp->v, "shininess");
@@ -345,9 +350,6 @@
lightdir = normvec3(subpt3(light.p, pos));
lightc = getlightcolor(&light, lightdir);
- ambient = mulpt3(lightc, Ka);
- ambient = modulapt3(ambient, m.ambient);
-
/* normal mapping */
va = getvattr(&sp->v, "tangent");
if(va == nil)
@@ -366,10 +368,21 @@
sp->v.n = n;
}
+ if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
+ m.diffuse = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
+ else if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0)
+ m.diffuse = sampletexture(sp->v.mtl->diffusemap, sp->v.uv, tsampler);
+
+ ambient = mulpt3(lightc, Ka);
+ ambient = modulapt3(ambient, m.diffuse);
+
Kd = fmax(0, dotvec3(n, lightdir));
diffuse = mulpt3(lightc, Kd);
diffuse = modulapt3(diffuse, m.diffuse);
+ if(sp->v.mtl != nil && sp->v.mtl->specularmap != nil && sp->v.uv.w != 0)
+ m.specular = sampletexture(sp->v.mtl->specularmap, sp->v.uv, tsampler);
+
lookdir = normvec3(subpt3(sp->su->camera->p, pos));
lightdir = qrotate(lightdir, n, PI);
spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess);
@@ -376,17 +389,8 @@
specular = mulpt3(lightc, spec*Ks);
specular = modulapt3(specular, m.specular);
- if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
- tc = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
- else if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0)
- tc = sampletexture(sp->v.mtl->diffusemap, sp->v.uv, tsampler);
- else
- tc = Pt3(1,1,1,1);
-
c = addpt3(ambient, addpt3(diffuse, specular));
- c = modulapt3(c, tc);
- c.a = 1;
-
+ c.a = m.diffuse.a;
return c;
}
--- a/readme
+++ b/readme
@@ -21,8 +21,7 @@
The s option will switch the skybox on (performance will drop
considerably).
- The t flag takes as input an image(6) file used to texture the first model
- (if it happens to have no materials).
+ The t flag takes as input an image(6) file used to texture the first model.
The g flag takes as input the dimensions of the camera viewport. If it's
smaller than screen the image will be upscaled to fit it as much as
possible, otherwise it will default to the screen dimensions.
--- a/vis.c
+++ b/vis.c
@@ -129,34 +129,40 @@
double Kd; /* diffuse factor */
double spec;
Point3 pos, lightdir, lookdir;
- Material *m;
+ Material m;
Color ambient, diffuse, specular, lightc;
sp->v->n = model2world(sp->su->entity, sp->v->n);
sp->v->p = model2world(sp->su->entity, sp->v->p);
pos = sp->v->p;
- m = sp->v->mtl;
+ if(sp->v->mtl != nil)
+ m = *sp->v->mtl;
+ else{
+ memset(&m, 0, sizeof m);
+ m.diffuse = sp->v->c;
+ m.specular = Pt3(1,1,1,1);
+ m.shininess = 1;
+ }
+
lightdir = normvec3(subpt3(light.p, pos));
lightc = getlightcolor(&light, lightdir);
ambient = mulpt3(lightc, Ka);
- if(m != nil)
- ambient = modulapt3(ambient, m->ambient);
+ ambient = modulapt3(ambient, m.diffuse);
Kd = fmax(0, dotvec3(sp->v->n, lightdir));
diffuse = mulpt3(lightc, Kd);
- if(m != nil)
- diffuse = modulapt3(diffuse, m->diffuse);
+ diffuse = modulapt3(diffuse, m.diffuse);
lookdir = normvec3(subpt3(sp->su->camera->p, pos));
lightdir = qrotate(lightdir, sp->v->n, PI);
- spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m? m->shininess: 1);
+ spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess);
specular = mulpt3(lightc, spec*Ks);
- if(m != nil)
- specular = modulapt3(specular, m->specular);
+ specular = modulapt3(specular, m.specular);
sp->v->c = addpt3(ambient, addpt3(diffuse, specular));
+ sp->v->c.a = m.diffuse.a;
return world2clip(sp->su->camera, pos);
}
@@ -210,7 +216,7 @@
static double Ks = 0.5; /* specular factor */
double Kd; /* diffuse factor */
double spec;
- Color ambient, diffuse, specular, tc, c, lightc;
+ Color ambient, diffuse, specular, lightc, c;
Point3 pos, n, lightdir, lookdir;
Material m;
RFrame3 TBN;
@@ -222,7 +228,7 @@
va = getvattr(&sp->v, "ambient");
m.ambient = va != nil? va->p: Pt3(1,1,1,1);
va = getvattr(&sp->v, "diffuse");
- m.diffuse = va != nil? va->p: Pt3(1,1,1,1);
+ m.diffuse = va != nil? va->p: sp->v.c;
va = getvattr(&sp->v, "specular");
m.specular = va != nil? va->p: Pt3(1,1,1,1);
va = getvattr(&sp->v, "shininess");
@@ -231,9 +237,6 @@
lightdir = normvec3(subpt3(light.p, pos));
lightc = getlightcolor(&light, lightdir);
- ambient = mulpt3(lightc, Ka);
- ambient = modulapt3(ambient, m.ambient);
-
/* normal mapping */
va = getvattr(&sp->v, "tangent");
if(va == nil)
@@ -252,10 +255,21 @@
sp->v.n = n;
}
+ if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
+ m.diffuse = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
+ else if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0)
+ m.diffuse = sampletexture(sp->v.mtl->diffusemap, sp->v.uv, tsampler);
+
+ ambient = mulpt3(lightc, Ka);
+ ambient = modulapt3(ambient, m.diffuse);
+
Kd = fmax(0, dotvec3(n, lightdir));
diffuse = mulpt3(lightc, Kd);
diffuse = modulapt3(diffuse, m.diffuse);
+ if(sp->v.mtl != nil && sp->v.mtl->specularmap != nil && sp->v.uv.w != 0)
+ m.specular = sampletexture(sp->v.mtl->specularmap, sp->v.uv, tsampler);
+
lookdir = normvec3(subpt3(sp->su->camera->p, pos));
lightdir = qrotate(lightdir, n, PI);
spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess);
@@ -262,16 +276,80 @@
specular = mulpt3(lightc, spec*Ks);
specular = modulapt3(specular, m.specular);
+ c = addpt3(ambient, addpt3(diffuse, specular));
+ c.a = m.diffuse.a;
+ return c;
+}
+
+Color
+blinnshader(FSparams *sp)
+{
+ static double Ka = 0.1; /* ambient factor */
+ static double Ks = 0.5; /* specular factor */
+ double Kd; /* diffuse factor */
+ double spec;
+ Color ambient, diffuse, specular, lightc, c;
+ Point3 pos, n, lightdir, lookdir;
+ Material m;
+ RFrame3 TBN;
+ Vertexattr *va;
+
+ va = getvattr(&sp->v, "pos");
+ pos = va->p;
+
+ va = getvattr(&sp->v, "ambient");
+ m.ambient = va != nil? va->p: Pt3(1,1,1,1);
+ va = getvattr(&sp->v, "diffuse");
+ m.diffuse = va != nil? va->p: sp->v.c;
+ va = getvattr(&sp->v, "specular");
+ m.specular = va != nil? va->p: Pt3(1,1,1,1);
+ va = getvattr(&sp->v, "shininess");
+ m.shininess = va != nil? va->n: 1;
+
+ lightdir = normvec3(subpt3(light.p, pos));
+ lightc = getlightcolor(&light, lightdir);
+
+ /* normal mapping */
+ va = getvattr(&sp->v, "tangent");
+ if(va == nil)
+ n = sp->v.n;
+ else{
+ /* TODO implement this on the VS instead and apply Gram-Schmidt here */
+ n = sampletexture(sp->v.mtl->normalmap, sp->v.uv, neartexsampler);
+ n = normvec3(subpt3(mulpt3(n, 2), Vec3(1,1,1)));
+
+ TBN.p = Pt3(0,0,0,1);
+ TBN.bx = va->p; /* T */
+ TBN.bz = sp->v.n; /* N */
+ TBN.by = crossvec3(TBN.bz, TBN.bx); /* B */
+
+ n = normvec3(invrframexform3(n, TBN));
+ sp->v.n = n;
+ }
+
if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
- tc = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
+ m.diffuse = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
else if(sp->v.mtl != nil && sp->v.mtl->diffusemap != nil && sp->v.uv.w != 0)
- tc = sampletexture(sp->v.mtl->diffusemap, sp->v.uv, tsampler);
- else
- tc = Pt3(1,1,1,1);
+ m.diffuse = sampletexture(sp->v.mtl->diffusemap, sp->v.uv, tsampler);
- c = addpt3(ambient, addpt3(diffuse, specular));
- c = modulapt3(c, tc);
+ ambient = mulpt3(lightc, Ka);
+ ambient = modulapt3(ambient, m.diffuse);
+ Kd = fmax(0, dotvec3(n, lightdir));
+ diffuse = mulpt3(lightc, Kd);
+ diffuse = modulapt3(diffuse, m.diffuse);
+
+ if(sp->v.mtl != nil && sp->v.mtl->specularmap != nil && sp->v.uv.w != 0)
+ m.specular = sampletexture(sp->v.mtl->specularmap, sp->v.uv, tsampler);
+
+ lookdir = normvec3(subpt3(sp->su->camera->p, pos));
+ lightdir = normvec3(addpt3(lookdir, lightdir)); /* half vector */
+ spec = pow(fmax(0, dotvec3(n, lightdir)), m.shininess);
+ specular = mulpt3(lightc, spec*Ks);
+ specular = modulapt3(specular, m.specular);
+
+ c = addpt3(ambient, addpt3(diffuse, specular));
+ c.a = m.diffuse.a;
return c;
}
@@ -436,6 +514,7 @@
{ "ident", identvshader, identshader },
{ "gouraud", gouraudvshader, gouraudshader },
{ "phong", phongvshader, phongshader },
+ { "blinn", phongvshader, blinnshader },
};
Shadertab *
getshader(char *name)
@@ -596,6 +675,9 @@
Point p;
Color c, n;
double z;
+// Abuf *abuf;
+// Astk *astk;
+// int i;
p = subpt(mctl->xy, screen->r.min);
p₂ = Pt2(p.x, p.y, 1);
@@ -608,6 +690,15 @@
c = ul2col(fb->cb[p.y*Dx(fb->r) + p.x]);
n = ul2col(fb->nb[p.y*Dx(fb->r) + p.x]);
z = fb->zb[p.y*Dx(fb->r) + p.x];
+// abuf = &fb->abuf;
+// if(abuf->stk != nil){
+// astk = &abuf->stk[p.y*Dx(fb->r) + p.x];
+// if(astk->active){
+// fprint(2, "p %P nfrags %lud\n", p, astk->size);
+// for(i = 0; i < astk->size; i++)
+// fprint(2, "\t%d: %V %g\n", i, astk->items[i].c, astk->items[i].z);
+// }
+// }
qunlock(maincam->view->fbctl);
snprint(stats[Spixcol], sizeof(stats[Spixcol]), "c %V z %g", c, z);
snprint(stats[Snorcol], sizeof(stats[Snorcol]), "n %V", n);
@@ -903,9 +994,8 @@
}
mdl = newmodel();
- mdl->prims = erealloc(mdl->prims, (mdl->nprims += 2)*sizeof(*mdl->prims));
- mdl->prims[mdl->nprims-2] = t[0];
- mdl->prims[mdl->nprims-1] = t[1];
+ mdl->addprim(mdl, t[0]);
+ mdl->addprim(mdl, t[1]);
ent = newentity(nil, mdl);
scene->addent(scene, ent);
}
@@ -996,7 +1086,7 @@
mdlpath = argv[argc];
model = readobjmodel(mdlpath);
subject = newentity(mdlpath, model);
-// subject->p.x = argc*4;
+// subject->p.z = -argc*4;
scene->addent(scene, subject);
if(argc == 0 && texpath != nil){