ref: 4b9e518c1d6a3ae82a98f6368f6ff345b4ab8db7
parent: 15e248df75343f48d567f9a318d5635beb1139cb
author: rodri <rgl@antares-labs.eu>
date: Sat Mar 16 17:23:13 EDT 2024
implement actual gouraud (phong on the vertex shader).
--- a/main.c
+++ b/main.c
@@ -108,34 +108,74 @@
//}
Point3
-vertshader(VSparams *sp)
+gouraudvshader(VSparams *sp)
{
- Point3 lightdir;
- double intens;
+ static double Ka = 0.1; /* ambient factor */
+ static double Ks = 0.5; /* specular factor */
+ double Kd; /* diffuse factor */
+ double spec;
+ Point3 pos, lightdir, lookdir;
+ Material m;
+ Color a, d, s;
+ Color ambient, diffuse, specular;
- lightdir = normvec3(subpt3(light.p, center));
sp->v->n = qrotate(sp->v->n, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
- intens = fmax(0, dotvec3(sp->v->n, lightdir));
- addvattr(sp->v, "intensity", VANumber, &intens);
sp->v->p = qrotate(sp->v->p, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
- return world2clip(maincam, model2world(sp->su->entity, sp->v->p));
+ pos = model2world(sp->su->entity, sp->v->p);
+ if(sp->v->mtl != nil){
+ a.r = sp->v->mtl->Ka.r; a.g = sp->v->mtl->Ka.g; a.b = sp->v->mtl->Ka.b; a.a = 1;
+ d.r = sp->v->mtl->Kd.r; d.g = sp->v->mtl->Kd.g; d.b = sp->v->mtl->Kd.b; d.a = 1;
+ s.r = sp->v->mtl->Ks.r; s.g = sp->v->mtl->Ks.g; s.b = sp->v->mtl->Ks.b; s.a = 1;
+ m.ambient = a;
+ m.diffuse = d;
+ m.specular = s;
+ m.shininess = sp->v->mtl->Ns;
+
+ ambient = mulpt3(light.c, Ka);
+ ambient.r *= m.ambient.r;
+ ambient.g *= m.ambient.g;
+ ambient.b *= m.ambient.b;
+ ambient.a *= m.ambient.a;
+
+ lightdir = normvec3(subpt3(light.p, pos));
+ Kd = fmax(0, dotvec3(sp->v->n, lightdir));
+ diffuse = mulpt3(light.c, Kd);
+ diffuse.r *= m.diffuse.r;
+ diffuse.g *= m.diffuse.g;
+ diffuse.b *= m.diffuse.b;
+ diffuse.a *= m.diffuse.a;
+
+ lookdir = normvec3(subpt3(maincam->p, pos));
+ lightdir = qrotate(lightdir, sp->v->n, PI);
+ spec = pow(fmax(0, dotvec3(lookdir, lightdir)), m.shininess);
+ specular = mulpt3(light.c, spec*Ks);
+ specular.r *= m.specular.r;
+ specular.g *= m.specular.g;
+ specular.b *= m.specular.b;
+ specular.a *= m.specular.a;
+
+ sp->v->c = addpt3(ambient, addpt3(diffuse, specular));
+ }
+ return world2clip(maincam, pos);
}
Color
gouraudshader(FSparams *sp)
{
- Vertexattr *va;
- Color c;
+ Color tc, c;
- va = getvattr(&sp->v, "intensity");
if(sp->v.mtl != nil && sp->v.mtl->map_Kd != nil && sp->v.uv.w != 0)
- c = texture(sp->v.mtl->map_Kd, sp->v.uv, tsampler);
+ tc = texture(sp->v.mtl->map_Kd, sp->v.uv, tsampler);
else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
- c = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
+ tc = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
else
- c = Pt3(1,1,1,1);
+ tc = Pt3(1,1,1,1);
- c = mulpt3(c, va->n);
+ c.a = fclamp(sp->v.c.a*tc.a, 0, 1);
+ c.b = fclamp(sp->v.c.b*tc.b, 0, 1);
+ c.g = fclamp(sp->v.c.g*tc.g, 0, 1);
+ c.r = fclamp(sp->v.c.r*tc.r, 0, 1);
+
return c;
}
@@ -160,7 +200,7 @@
addvattr(sp->v, "specular", VAPoint, &s);
addvattr(sp->v, "shininess", VANumber, &ss);
}
- return world2clip(maincam, model2world(sp->su->entity, sp->v->p));
+ return world2clip(maincam, pos);
}
Color
@@ -226,6 +266,25 @@
return c;
}
+Point3
+identvshader(VSparams *sp)
+{
+ Point3 pos, lightdir;
+ double intens;
+
+ pos = model2world(sp->su->entity, sp->v->p);
+ lightdir = normvec3(subpt3(light.p, pos));
+ intens = fmax(0, dotvec3(sp->v->n, lightdir));
+ addvattr(sp->v, "intensity", VANumber, &intens);
+ if(sp->v->mtl != nil){
+ sp->v->c.r = sp->v->mtl->Kd.r;
+ sp->v->c.g = sp->v->mtl->Kd.g;
+ sp->v->c.b = sp->v->mtl->Kd.b;
+ sp->v->c.a = 1;
+ }
+ return world2clip(maincam, pos);
+}
+
Color
toonshader(FSparams *sp)
{
@@ -240,6 +299,32 @@
}
Color
+identshader(FSparams *sp)
+{
+ Color tc, c;
+
+ if(sp->v.mtl != nil && sp->v.mtl->map_Kd != nil && sp->v.uv.w != 0)
+ tc = texture(sp->v.mtl->map_Kd, sp->v.uv, tsampler);
+ else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
+ tc = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
+ else
+ tc = Pt3(1,1,1,1);
+
+ c.a = fclamp(sp->v.c.a*tc.a, 0, 1);
+ c.b = fclamp(sp->v.c.b*tc.b, 0, 1);
+ c.g = fclamp(sp->v.c.g*tc.g, 0, 1);
+ c.r = fclamp(sp->v.c.r*tc.r, 0, 1);
+
+ return c;
+}
+
+Point3
+ivshader(VSparams *sp)
+{
+ return world2clip(maincam, model2world(sp->su->entity, sp->v->p));
+}
+
+Color
triangleshader(FSparams *sp)
{
Triangle2 t;
@@ -327,35 +412,15 @@
return Pt3(uv.x, uv.y, smoothstep(0,1,uv.x+uv.y), 1);
}
-Point3
-ivshader(VSparams *sp)
-{
- return world2clip(maincam, model2world(sp->su->entity, sp->v->p));
-}
-
-Color
-identshader(FSparams *sp)
-{
- Color c;
-
- if(sp->v.mtl != nil && sp->v.mtl->map_Kd != nil && sp->v.uv.w != 0)
- c = texture(sp->v.mtl->map_Kd, sp->v.uv, tsampler);
- else if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0)
- c = texture(sp->su->entity->mdl->tex, sp->v.uv, tsampler);
- else
- c = Pt3(1,1,1,1);
- return c;
-}
-
Shader shadertab[] = {
{ "triangle", ivshader, triangleshader },
{ "circle", ivshader, circleshader },
{ "box", ivshader, boxshader },
{ "sf", ivshader, sfshader },
+ { "toon", identvshader, toonshader },
+ { "ident", identvshader, identshader },
+ { "gouraud", gouraudvshader, gouraudshader },
{ "phong", phongvshader, phongshader },
- { "gouraud", vertshader, gouraudshader },
- { "toon", vertshader, toonshader },
- { "ident", vertshader, identshader },
};
Shader *
getshader(char *name)