shithub: 3dee

Download patch

ref: aa16a1b67c240833e1ef29a10ddedd28882bc6c1
parent: e76a8e48037367ac29369d3220cef357383866ed
author: rodri <[email protected]>
date: Wed Mar 6 07:45:48 EST 2024

use the new texture sampler and vertex material definitions.

add an mmb menu for texture sampling selection and point
light position randomization.

--- a/main.c
+++ b/main.c
@@ -77,6 +77,7 @@
 static int doprof;
 static int inception;
 static int showhud;
+Color (*tsampler)(Memimage*,Point2);
 
 static int
 min(int a, int b)
@@ -124,11 +125,19 @@
 gouraudshader(FSparams *sp)
 {
 	Vertexattr *va;
+	Color c;
 
 	va = getvattr(&sp->v, "intensity");
-	sp->cbuf[1] *= va->n;
-	sp->cbuf[2] *= va->n;
-	sp->cbuf[3] *= va->n;
+	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);
+
+	c = mulpt3(c, va->n);
+	sp->cbuf[0] *= c.a;
+	sp->cbuf[1] *= c.b;
+	sp->cbuf[2] *= c.g;
+	sp->cbuf[3] *= c.r;
 	memfillcolor(sp->frag, *(ulong*)sp->cbuf);
 
 	return sp->frag;
@@ -138,11 +147,23 @@
 phongvshader(VSparams *sp)
 {
 	Point3 pos;
+	Color a, d, s;
+	double ss;
 
 	sp->v->n = qrotate(sp->v->n, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
 	sp->v->p = qrotate(sp->v->p, Vec3(0,1,0), θ+fmod(ω*sp->su->uni_time/1e9, 2*PI));
 	pos = model2world(sp->su->entity, sp->v->p);
 	addvattr(sp->v, "pos", VAPoint, &pos);
+	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;
+		ss = sp->v->mtl->Ns;
+		addvattr(sp->v, "ambient", VAPoint, &a);
+		addvattr(sp->v, "diffuse", VAPoint, &d);
+		addvattr(sp->v, "specular", VAPoint, &s);
+		addvattr(sp->v, "shininess", VANumber, &ss);
+	}
 	return world2clip(maincam, model2world(sp->su->entity, sp->v->p));
 }
 
@@ -153,27 +174,47 @@
 	static double Ks = 0.5;	/* specular factor */
 	double Kd;		/* diffuse factor */
 	double spec;
-	Color ambient, diffuse, specular;
+	Color ambient, diffuse, specular, tc, c;
 	Point3 pos, lookdir, lightdir;
+	Material m;
 	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: Pt3(1,1,1,1);
+	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;
 
 	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)), 64);
+	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->cbuf[1] *= fclamp(ambient.b + diffuse.b + specular.b, 0, 1);
-	sp->cbuf[2] *= fclamp(ambient.g + diffuse.g + specular.g, 0, 1);
-	sp->cbuf[3] *= fclamp(ambient.r + diffuse.r + specular.r, 0, 1);
+	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 = addpt3(ambient, addpt3(diffuse, specular));
+	sp->cbuf[0] *= fclamp(c.a*tc.a, 0, 1);
+	sp->cbuf[1] *= fclamp(c.b*tc.b, 0, 1);
+	sp->cbuf[2] *= fclamp(c.g*tc.g, 0, 1);
+	sp->cbuf[3] *= fclamp(c.r*tc.r, 0, 1);
 	memfillcolor(sp->frag, *(ulong*)sp->cbuf);
 
 	return sp->frag;
@@ -320,6 +361,17 @@
 Memimage *
 identshader(FSparams *sp)
 {
+	Color c;
+
+	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);
+
+	sp->cbuf[0] *= c.a;
+	sp->cbuf[1] *= c.b;
+	sp->cbuf[2] *= c.g;
+	sp->cbuf[3] *= c.r;
 	memfillcolor(sp->frag, *(ulong*)sp->cbuf);
 	return sp->frag;
 }
@@ -416,6 +468,37 @@
 	}
 }
 
+void
+mmb(void)
+{
+	enum {
+		MOVELIGHT,
+		TSNEAREST,
+		TSBILINEAR,
+	};
+	static char *items[] = {
+	 [MOVELIGHT]	"move light",
+	 [TSNEAREST]	"use nearest sampler",
+	 [TSBILINEAR]	"use bilinear sampler",
+		nil,
+	};
+	static Menu menu = { .item = items };
+
+	switch(menuhit(2, mctl, &menu, _screen)){
+	case MOVELIGHT:
+		srand(time(0));
+		light.p = Pt3((frand()-0.5)*2000,(frand()-0.5)*2000,(frand()-0.5)*2000,1);
+		break;
+	case TSNEAREST:
+		tsampler = neartexsampler;
+		break;
+	case TSBILINEAR:
+		tsampler = bilitexsampler;
+		break;
+	}
+	nbsend(drawc, nil);
+}
+
 static char *
 genrmbmenuitem(int idx)
 {
@@ -434,12 +517,14 @@
 	if(idx < 0)
 		return;
 	shader = &shadertab[idx];
-	nbsendp(drawc, nil);
+	nbsend(drawc, nil);
 }
 
 void
 mouse(void)
 {
+	if((mctl->buttons & 2) != 0)
+		mmb();
 	if((mctl->buttons & 4) != 0)
 		rmb();
 	if((mctl->buttons & 8) != 0){
@@ -665,6 +750,7 @@
 	light.p = Pt3(0,100,100,1);
 	light.c = Pt3(1,1,1,1);
 	light.type = LIGHT_POINT;
+	tsampler = neartexsampler;
 
 	keyc = chancreate(sizeof(void*), 1);
 	drawc = chancreate(sizeof(void*), 1);