shithub: qk1

Download patch

ref: 05455d82d6bd6d707c8fac3bff07a29d8a2b0ecf
parent: 4a017f063a2a88849ef19e705689f0c7e40e4b6c
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Dec 11 18:39:39 EST 2023

add basics of colored lighting

--- a/d_iface.h
+++ b/d_iface.h
@@ -4,9 +4,7 @@
 
 typedef struct
 {
-	float	u, v;
-	float	s, t;
-	float	zi;
+	float u, v, s, t, zi;
 } emitpoint_t;
 
 typedef enum {
@@ -30,15 +28,16 @@
 
 #define PARTICLE_Z_CLIP	8.0
 
-typedef struct polyvert_s {
-	float	u, v, zi, s, t;
-} polyvert_t;
-
 // !!! if this is changed, it must be changed in d_ifacea.h too !!!
 typedef struct finalvert_s {
-	int		v[6];		// u, v, s, t, l, 1/z
-	int		flags;
-	float	reserved;
+	union {
+		struct {
+			int u, v, s, t, zi;
+			int l[3];
+		};
+		int x[5+3];
+	};
+	int flags;
 } finalvert_t;
 
 // !!! if this is changed, it must be changed in d_ifacea.h too !!!
--- a/d_polyse.c
+++ b/d_polyse.c
@@ -2,23 +2,21 @@
 
 // !!! if this is changed, it must be changed in asm_draw.h too !!!
 typedef struct {
-	pixel_t			*pdest;
-	uzint			*pz;
-	int				count;
-	pixel_t			*ptex;
-	int				sfrac, tfrac, light, zi;
+	pixel_t *pdest, *ptex;
+	uzint *pz;
+	int count, sfrac, tfrac, zi, light[3];
 } spanpackage_t;
 
 typedef struct {
-	int		isflattop;
-	int		numleftedges;
-	int		*pleftedgevert0;
-	int		*pleftedgevert1;
-	int		*pleftedgevert2;
-	int		numrightedges;
-	int		*prightedgevert0;
-	int		*prightedgevert1;
-	int		*prightedgevert2;
+	finalvert_t *pleftedgevert0;
+	finalvert_t *pleftedgevert1;
+	finalvert_t *pleftedgevert2;
+	finalvert_t *prightedgevert0;
+	finalvert_t *prightedgevert1;
+	finalvert_t *prightedgevert2;
+	int isflattop;
+	int numleftedges;
+	int numrightedges;
 } edgetable;
 
 // TODO: put in span spilling to shrink list size
@@ -26,29 +24,29 @@
 static spanpackage_t a_spans[MAXHEIGHT+1];
 									// 1 extra for spanpackage that marks end
 
-static int r_p0[6], r_p1[6], r_p2[6];
+static finalvert_t r_p0, r_p1, r_p2;
 static pixel_t *d_pcolormap;
 static int d_xdenom;
 static edgetable *pedgetable;
 
 static edgetable edgetables[12] = {
-	{0, 1, r_p0, r_p2, nil, 2, r_p0, r_p1, r_p2 },
-	{0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, nil},
-	{1, 1, r_p0, r_p2, nil, 1, r_p1, r_p2, nil},
-	{0, 1, r_p1, r_p0, nil, 2, r_p1, r_p2, r_p0 },
-	{0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, nil},
-	{0, 1, r_p2, r_p1, nil, 1, r_p2, r_p0, nil},
-	{0, 1, r_p2, r_p1, nil, 2, r_p2, r_p0, r_p1 },
-	{0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, nil},
-	{0, 1, r_p1, r_p0, nil, 1, r_p1, r_p2, nil},
-	{1, 1, r_p2, r_p1, nil, 1, r_p0, r_p1, nil},
-	{1, 1, r_p1, r_p0, nil, 1, r_p2, r_p0, nil},
-	{0, 1, r_p0, r_p2, nil, 1, r_p0, r_p1, nil},
+	{&r_p0, &r_p2, nil,   &r_p0, &r_p1, &r_p2, 0, 1, 2},
+	{&r_p1, &r_p0, &r_p2, &r_p1, &r_p2, nil,   0, 2, 1},
+	{&r_p0, &r_p2, nil,   &r_p1, &r_p2, nil,   1, 1, 1},
+	{&r_p1, &r_p0, nil,   &r_p1, &r_p2, &r_p0, 0, 1, 2},
+	{&r_p0, &r_p2, &r_p1, &r_p0, &r_p1, nil,   0, 2, 1},
+	{&r_p2, &r_p1, nil,   &r_p2, &r_p0, nil,   0, 1, 1},
+	{&r_p2, &r_p1, nil,   &r_p2, &r_p0, &r_p1, 0, 1, 2},
+	{&r_p2, &r_p1, &r_p0, &r_p2, &r_p0, nil,   0, 2, 1},
+	{&r_p1, &r_p0, nil,   &r_p1, &r_p2, nil,   0, 1, 1},
+	{&r_p2, &r_p1, nil,   &r_p0, &r_p1, nil,   1, 1, 1},
+	{&r_p1, &r_p0, nil,   &r_p2, &r_p0, nil,   1, 1, 1},
+	{&r_p0, &r_p2, nil,   &r_p0, &r_p1, nil,   0, 1, 1},
 };
 
 // FIXME: some of these can become statics
-static int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
-static int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
+static int a_sstepxfrac, a_tstepxfrac, r_lstepx[3], a_ststepxwhole;
+static int r_sstepx, r_tstepx, r_lstepy[3], r_sstepy, r_tstepy;
 static int r_zistepx, r_zistepy;
 static int d_aspancount, d_countextrastep;
 
@@ -56,10 +54,10 @@
 static int ystart;
 static pixel_t *d_pdest, *d_ptex;
 static uzint *d_pz;
-static int d_sfrac, d_tfrac, d_light, d_zi;
+static int d_sfrac, d_tfrac, d_light[3], d_zi;
 static int d_ptexextrastep, d_sfracextrastep;
-static int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
-static int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
+static int d_lightextrastep[3], d_pdestextrastep, d_tfracextrastep;
+static int d_lightbasestep[3], d_pdestbasestep, d_ptexbasestep;
 static int d_sfracbasestep, d_tfracbasestep;
 static int d_ziextrastep, d_zibasestep;
 static int d_pzextrastep, d_pzbasestep;
@@ -82,7 +80,7 @@
 void D_PolysetCalcGradients (int skinwidth);
 void D_DrawSubdiv (pixel_t *colormap);
 void D_DrawNonSubdiv (void);
-void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3, byte alpha);
+void D_PolysetRecursiveTriangle (finalvert_t *p1, finalvert_t *p2, finalvert_t *p3, byte alpha, int l[3]);
 void D_PolysetSetEdgeTable (void);
 void D_RasterizeAliasPolySmooth (void);
 void D_PolysetScanLeftEdge (int height);
@@ -115,18 +113,15 @@
 	int		i, z;
 	uzint	*zbuf;
 
-	for (i=0 ; i<numverts ; i++, fv++)
-	{
+	for(i = 0 ; i < numverts; i++, fv++){
 		// valid triangle coordinates for filling can include the bottom and
 		// right clip edges, due to the fill rule; these shouldn't be drawn
-		if ((fv->v[0] < r_refdef.vrectright) &&
-			(fv->v[1] < r_refdef.vrectbottom))
-		{
-			z = fv->v[5]>>16;
-			zbuf = zspantable[fv->v[1]] + fv->v[0];
-			if (z >= *zbuf){
-				pixel_t p = skintable[fv->v[3]>>16][fv->v[2]>>16];
-				int n = d_scantable[fv->v[1]] + fv->v[0];
+		if (fv->u < r_refdef.vrectright && fv->v < r_refdef.vrectbottom){
+			z = fv->zi >> 16;
+			zbuf = zspantable[fv->v] + fv->u;
+			if(z >= *zbuf){
+				pixel_t p = addlight(skintable[fv->t >> 16][fv->s >> 16], fv->l[0], fv->l[1], fv->l[2]);
+				int n = d_scantable[fv->v] + fv->u;
 				if(r_drawflags & DRAW_BLEND){
 					d_viewbuffer[n] = blendalpha(p, d_viewbuffer[n], alpha);
 				}else{
@@ -161,40 +156,40 @@
 		index1 = pfv + ptri[i].vertindex[1];
 		index2 = pfv + ptri[i].vertindex[2];
 
-		if (((index0->v[1]-index1->v[1]) *
-			 (index0->v[0]-index2->v[0]) -
-			 (index0->v[0]-index1->v[0]) *
-			 (index0->v[1]-index2->v[1])) >= 0)
+		if (((index0->v - index1->v) *
+			 (index0->u - index2->u) -
+			 (index0->u - index1->u) *
+			 (index0->v - index2->v)) >= 0)
 		{
 			continue;
 		}
 
-		d_pcolormap = colormap + (index0->v[4] & 0xFF00);
+		d_pcolormap = colormap + (index0->l[0] & 0xFF00);
 
 		if (ptri[i].facesfront)
 		{
-			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v, currententity->alpha);
+			D_PolysetRecursiveTriangle(index0, index1, index2, currententity->alpha, index0->l);
 		}
 		else
 		{
 			int		s0, s1, s2;
 
-			s0 = index0->v[2];
-			s1 = index1->v[2];
-			s2 = index2->v[2];
+			s0 = index0->s;
+			s1 = index1->s;
+			s2 = index2->s;
 
 			if (index0->flags & ALIAS_ONSEAM)
-				index0->v[2] += r_affinetridesc.seamfixupX16;
+				index0->s += r_affinetridesc.seamfixupX16;
 			if (index1->flags & ALIAS_ONSEAM)
-				index1->v[2] += r_affinetridesc.seamfixupX16;
+				index1->s += r_affinetridesc.seamfixupX16;
 			if (index2->flags & ALIAS_ONSEAM)
-				index2->v[2] += r_affinetridesc.seamfixupX16;
+				index2->s += r_affinetridesc.seamfixupX16;
 
-			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v, currententity->alpha);
+			D_PolysetRecursiveTriangle(index0, index1, index2, currententity->alpha, index0->l);
 
-			index0->v[2] = s0;
-			index1->v[2] = s1;
-			index2->v[2] = s2;
+			index0->s = s0;
+			index1->s = s1;
+			index2->s = s2;
 		}
 	}
 }
@@ -222,48 +217,28 @@
 		index1 = pfv + ptri->vertindex[1];
 		index2 = pfv + ptri->vertindex[2];
 
-		d_xdenom = (index0->v[1]-index1->v[1]) *
-				(index0->v[0]-index2->v[0]) -
-				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
+		d_xdenom = (index0->v - index1->v) * (index0->u - index2->u) -
+				(index0->u - index1->u) * (index0->v - index2->v);
 
-		if (d_xdenom >= 0)
-		{
+		if(d_xdenom >= 0)
 			continue;
-		}
 
-		r_p0[0] = index0->v[0];		// u
-		r_p0[1] = index0->v[1];		// v
-		r_p0[2] = index0->v[2];		// s
-		r_p0[3] = index0->v[3];		// t
-		r_p0[4] = index0->v[4];		// light
-		r_p0[5] = index0->v[5];		// iz
+		memmove(r_p0.x, index0->x, sizeof(r_p0.x));
+		memmove(r_p1.x, index1->x, sizeof(r_p1.x));
+		memmove(r_p2.x, index2->x, sizeof(r_p2.x));
 
-		r_p1[0] = index1->v[0];
-		r_p1[1] = index1->v[1];
-		r_p1[2] = index1->v[2];
-		r_p1[3] = index1->v[3];
-		r_p1[4] = index1->v[4];
-		r_p1[5] = index1->v[5];
-
-		r_p2[0] = index2->v[0];
-		r_p2[1] = index2->v[1];
-		r_p2[2] = index2->v[2];
-		r_p2[3] = index2->v[3];
-		r_p2[4] = index2->v[4];
-		r_p2[5] = index2->v[5];
-
 		if (!ptri->facesfront)
 		{
 			if (index0->flags & ALIAS_ONSEAM)
-				r_p0[2] += r_affinetridesc.seamfixupX16;
+				r_p0.s += r_affinetridesc.seamfixupX16;
 			if (index1->flags & ALIAS_ONSEAM)
-				r_p1[2] += r_affinetridesc.seamfixupX16;
+				r_p1.s += r_affinetridesc.seamfixupX16;
 			if (index2->flags & ALIAS_ONSEAM)
-				r_p2[2] += r_affinetridesc.seamfixupX16;
+				r_p2.s += r_affinetridesc.seamfixupX16;
 		}
 
-		D_PolysetSetEdgeTable ();
-		D_RasterizeAliasPolySmooth ();
+		D_PolysetSetEdgeTable();
+		D_RasterizeAliasPolySmooth();
 	}
 }
 
@@ -273,32 +248,30 @@
 D_PolysetRecursiveTriangle
 ================
 */
-void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3, byte alpha)
+void D_PolysetRecursiveTriangle (finalvert_t *lp1, finalvert_t *lp2, finalvert_t *lp3, byte alpha, int l[3])
 {
-	int		*temp;
-	int		d;
-	int		new[6];
-	int		z;
-	uzint	*zbuf;
+	finalvert_t new, *temp;
+	uzint *zbuf;
+	int d, z;
 
-	d = lp2[0] - lp1[0];
+	d = lp2->u - lp1->u;
 	if (d < -1 || d > 1)
 		goto split;
-	d = lp2[1] - lp1[1];
+	d = lp2->v - lp1->v;
 	if (d < -1 || d > 1)
 		goto split;
 
-	d = lp3[0] - lp2[0];
+	d = lp3->u - lp2->u;
 	if (d < -1 || d > 1)
 		goto split2;
-	d = lp3[1] - lp2[1];
+	d = lp3->v - lp2->v;
 	if (d < -1 || d > 1)
 		goto split2;
 
-	d = lp1[0] - lp3[0];
+	d = lp1->u - lp3->u;
 	if (d < -1 || d > 1)
 		goto split3;
-	d = lp1[1] - lp3[1];
+	d = lp1->v - lp3->v;
 	if (d < -1 || d > 1)
 	{
 split3:
@@ -320,24 +293,23 @@
 
 split:
 	// split this edge
-	new[0] = (lp1[0] + lp2[0]) >> 1;
-	new[1] = (lp1[1] + lp2[1]) >> 1;
-	new[2] = (lp1[2] + lp2[2]) >> 1;
-	new[3] = (lp1[3] + lp2[3]) >> 1;
-	new[5] = (lp1[5] + lp2[5]) >> 1;
+	new.u = (lp1->u + lp2->u) >> 1;
+	new.v = (lp1->v + lp2->v) >> 1;
+	new.s = (lp1->s + lp2->s) >> 1;
+	new.t = (lp1->t + lp2->t) >> 1;
+	new.zi = (lp1->zi + lp2->zi) >> 1;
 
 	// draw the point if splitting a leading edge
-	if (lp2[1] > lp1[1])
+	if (lp2->v > lp1->v)
 		goto nodraw;
-	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+	if ((lp2->v == lp1->v) && (lp2->u < lp1->u))
 		goto nodraw;
 
-
-	z = new[5]>>16;
-	zbuf = zspantable[new[1]] + new[0];
+	z = new.zi >> 16;
+	zbuf = zspantable[new.v] + new.u;
 	if (z >= *zbuf){
-		pixel_t p = skintable[new[3]>>16][new[2]>>16];
-		int n = d_scantable[new[1]] + new[0];
+		pixel_t p = addlight(skintable[new.t >> 16][new.s >> 16], l[0], l[1], l[2]);
+		int n = d_scantable[new.v] + new.u;
 		if(r_drawflags & DRAW_BLEND){
 			d_viewbuffer[n] = blendalpha(p, d_viewbuffer[n], alpha);
 		}else{
@@ -348,8 +320,8 @@
 
 nodraw:
 	// recursively continue
-	D_PolysetRecursiveTriangle (lp3, lp1, new, alpha);
-	D_PolysetRecursiveTriangle (lp3, new, lp2, alpha);
+	D_PolysetRecursiveTriangle(lp3, lp1, &new, alpha, l);
+	D_PolysetRecursiveTriangle(lp3, &new, lp2, alpha, l);
 }
 
 
@@ -381,7 +353,6 @@
 */
 void D_PolysetScanLeftEdge (int height)
 {
-
 	do
 	{
 		d_pedgespanpackage->pdest = d_pdest;
@@ -393,7 +364,9 @@
 		d_pedgespanpackage->tfrac = d_tfrac;
 
 		// FIXME: need to clamp l, s, t, at both ends?
-		d_pedgespanpackage->light = d_light;
+		d_pedgespanpackage->light[0] = d_light[0];
+		d_pedgespanpackage->light[1] = d_light[1];
+		d_pedgespanpackage->light[2] = d_light[2];
 		d_pedgespanpackage->zi = d_zi;
 
 		d_pedgespanpackage++;
@@ -415,7 +388,9 @@
 				d_ptex += r_affinetridesc.skinwidth;
 				d_tfrac &= 0xFFFF;
 			}
-			d_light += d_lightextrastep;
+			d_light[0] += d_lightextrastep[0];
+			d_light[1] += d_lightextrastep[1];
+			d_light[2] += d_lightextrastep[2];
 			d_zi += d_ziextrastep;
 			errorterm -= erroradjustdown;
 		}
@@ -434,7 +409,9 @@
 				d_ptex += r_affinetridesc.skinwidth;
 				d_tfrac &= 0xFFFF;
 			}
-			d_light += d_lightbasestep;
+			d_light[0] += d_lightbasestep[0];
+			d_light[1] += d_lightbasestep[1];
+			d_light[2] += d_lightbasestep[2];
 			d_zi += d_zibasestep;
 		}
 	} while (--height);
@@ -487,12 +464,13 @@
 void D_PolysetCalcGradients (int skinwidth)
 {
 	float	xstepdenominv, ystepdenominv, t0, t1;
-	float	p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
+	float	p0v_minus_p2v, p1v_minus_p2v, p0u_minus_p2u, p1u_minus_p2u;
+	int i;
 
-	p00_minus_p20 = r_p0[0] - r_p2[0];
-	p01_minus_p21 = r_p0[1] - r_p2[1];
-	p10_minus_p20 = r_p1[0] - r_p2[0];
-	p11_minus_p21 = r_p1[1] - r_p2[1];
+	p0u_minus_p2u = r_p0.u - r_p2.u;
+	p0v_minus_p2v = r_p0.v - r_p2.v;
+	p1u_minus_p2u = r_p1.u - r_p2.u;
+	p1v_minus_p2v = r_p1.v - r_p2.v;
 
 	xstepdenominv = 1.0 / (float)d_xdenom;
 
@@ -501,33 +479,27 @@
 	// ceil () for light so positive steps are exaggerated, negative steps
 	// diminished,  pushing us away from underflow toward overflow. Underflow is
 	// very visible, overflow is very unlikely, because of ambient lighting
-	t0 = r_p0[4] - r_p2[4];
-	t1 = r_p1[4] - r_p2[4];
-	r_lstepx = (int)
-			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
-	r_lstepy = (int)
-			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
+	for(i = 0; i < 3; i++){
+		t0 = r_p0.l[i] - r_p2.l[i];
+		t1 = r_p1.l[i] - r_p2.l[i];
+		r_lstepx[i] = (int)ceil((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
+		r_lstepy[i] = (int)ceil((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
+	}
 
-	t0 = r_p0[2] - r_p2[2];
-	t1 = r_p1[2] - r_p2[2];
-	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
-			xstepdenominv);
-	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
-			ystepdenominv);
+	t0 = r_p0.s - r_p2.s;
+	t1 = r_p1.s - r_p2.s;
+	r_sstepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
+	r_sstepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
 
-	t0 = r_p0[3] - r_p2[3];
-	t1 = r_p1[3] - r_p2[3];
-	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
-			xstepdenominv);
-	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
-			ystepdenominv);
+	t0 = r_p0.t - r_p2.t;
+	t1 = r_p1.t - r_p2.t;
+	r_tstepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
+	r_tstepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
 
-	t0 = r_p0[5] - r_p2[5];
-	t1 = r_p1[5] - r_p2[5];
-	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
-			xstepdenominv);
-	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
-			ystepdenominv);
+	t0 = r_p0.zi - r_p2.zi;
+	t1 = r_p1.zi - r_p2.zi;
+	r_zistepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
+	r_zistepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
 
 	a_sstepxfrac = r_sstepx & 0xFFFF;
 	a_tstepxfrac = r_tstepx & 0xFFFF;
@@ -544,7 +516,7 @@
 	int		lcount;
 	pixel_t	*lpdest, *lptex;
 	int		lsfrac, ltfrac;
-	int		llight;
+	int		llight[3];
 	int		lzi;
 	uzint	*lpz;
 
@@ -570,14 +542,15 @@
 			lpz = pspanpackage->pz;
 			lsfrac = pspanpackage->sfrac;
 			ltfrac = pspanpackage->tfrac;
-			llight = pspanpackage->light;
+			llight[0] = pspanpackage->light[0];
+			llight[1] = pspanpackage->light[1];
+			llight[2] = pspanpackage->light[2];
 			lzi = pspanpackage->zi;
 
 			do
 			{
-pixel_t addlight(pixel_t x, int light);
 				if ((lzi >> 16) >= *lpz){
-					pixel_t p = addlight(*lptex, llight);
+					pixel_t p = addlight(*lptex, llight[0], llight[1], llight[2]);
 					if(r_drawflags & DRAW_BLEND){
 						*lpdest = blendalpha(
 							p,
@@ -593,7 +566,9 @@
 				lpdest++;
 				lzi += r_zistepx;
 				lpz++;
-				llight += r_lstepx;
+				llight[0] += r_lstepx[0];
+				llight[1] += r_lstepx[1];
+				llight[2] += r_lstepx[2];
 				lptex += a_ststepxwhole;
 				lsfrac += a_sstepxfrac;
 				lptex += lsfrac >> 16;
@@ -618,9 +593,9 @@
 */
 void D_RasterizeAliasPolySmooth (void)
 {
-	int				initialleftheight, initialrightheight;
-	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
-	int				working_lstepx, originalcount;
+	int initialleftheight, initialrightheight;
+	finalvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom;
+	int working_lstepx[3], originalcount;
 
 	plefttop = pedgetable->pleftedgevert0;
 	prighttop = pedgetable->prightedgevert0;
@@ -628,8 +603,9 @@
 	pleftbottom = pedgetable->pleftedgevert1;
 	prightbottom = pedgetable->prightedgevert1;
 
-	initialleftheight = pleftbottom[1] - plefttop[1];
-	initialrightheight = prightbottom[1] - prighttop[1];
+	initialleftheight = pleftbottom->v - plefttop->v;
+	initialrightheight = prightbottom->v - prighttop->v;
+	assert(initialleftheight <= MAXHEIGHT);
 
 	// set the s, t, and light gradients, which are consistent across the triangle
 	// because being a triangle, things are affine
@@ -639,18 +615,20 @@
 	// scan out the top (and possibly only) part of the left edge
 	d_pedgespanpackage = a_spans;
 
-	ystart = plefttop[1];
-	d_aspancount = plefttop[0] - prighttop[0];
+	ystart = plefttop->v;
+	d_aspancount = plefttop->u - prighttop->u;
 
-	d_ptex = r_affinetridesc.pskin + (plefttop[2] >> 16) +
-			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
-	d_sfrac = plefttop[2] & 0xFFFF;
-	d_tfrac = plefttop[3] & 0xFFFF;
-	d_light = plefttop[4];
-	d_zi = plefttop[5];
+	d_ptex = r_affinetridesc.pskin + (plefttop->s >> 16) +
+			(plefttop->t >> 16) * r_affinetridesc.skinwidth;
+	d_sfrac = plefttop->s & 0xFFFF;
+	d_tfrac = plefttop->t & 0xFFFF;
+	d_zi = plefttop->zi;
+	d_light[0] = plefttop->l[0];
+	d_light[1] = plefttop->l[1];
+	d_light[2] = plefttop->l[2];
 
-	d_pdest = d_viewbuffer + ystart * screenwidth + plefttop[0];
-	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+	d_pdest = d_viewbuffer + ystart * screenwidth + plefttop->u;
+	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop->u;
 
 	if (initialleftheight == 1)
 	{
@@ -663,7 +641,9 @@
 		d_pedgespanpackage->tfrac = d_tfrac;
 
 		// FIXME: need to clamp l, s, t, at both ends?
-		d_pedgespanpackage->light = d_light;
+		d_pedgespanpackage->light[0] = d_light[0];
+		d_pedgespanpackage->light[1] = d_light[1];
+		d_pedgespanpackage->light[2] = d_light[2];
 		d_pedgespanpackage->zi = d_zi;
 
 		d_pedgespanpackage++;
@@ -670,8 +650,8 @@
 	}
 	else
 	{
-		D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
-							  pleftbottom[0], pleftbottom[1]);
+		D_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
+							  pleftbottom->u, pleftbottom->v);
 
 		d_pzbasestep = d_zwidth + ubasestep;
 		d_pzextrastep = d_pzbasestep + 1;
@@ -683,10 +663,14 @@
 		// for negative steps in x along left edge, bias toward overflow rather than
 		// underflow (sort of turning the floor () we did in the gradient calcs into
 		// ceil (), but plus a little bit)
-		if (ubasestep < 0)
-			working_lstepx = r_lstepx - 1;
-		else
-			working_lstepx = r_lstepx;
+		working_lstepx[0] = r_lstepx[0];
+		working_lstepx[1] = r_lstepx[1];
+		working_lstepx[2] = r_lstepx[2];
+		if(ubasestep < 0){
+			working_lstepx[0] -= 1;
+			working_lstepx[1] -= 1;
+			working_lstepx[2] -= 1;
+		}
 
 		d_countextrastep = ubasestep + 1;
 		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
@@ -694,7 +678,9 @@
 				r_affinetridesc.skinwidth;
 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
-		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+		d_lightbasestep[0] = r_lstepy[0] + working_lstepx[0] * ubasestep;
+		d_lightbasestep[1] = r_lstepy[1] + working_lstepx[1] * ubasestep;
+		d_lightbasestep[2] = r_lstepy[2] + working_lstepx[2] * ubasestep;
 		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
 
 		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
@@ -702,7 +688,9 @@
 				r_affinetridesc.skinwidth;
 		d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
 		d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
-		d_lightextrastep = d_lightbasestep + working_lstepx;
+		d_lightextrastep[0] = d_lightbasestep[0] + working_lstepx[0];
+		d_lightextrastep[1] = d_lightbasestep[1] + working_lstepx[1];
+		d_lightextrastep[2] = d_lightbasestep[2] + working_lstepx[2];
 		d_ziextrastep = d_zibasestep + r_zistepx;
 
 		D_PolysetScanLeftEdge (initialleftheight);
@@ -716,21 +704,23 @@
 		plefttop = pleftbottom;
 		pleftbottom = pedgetable->pleftedgevert2;
 
-		height = pleftbottom[1] - plefttop[1];
+		height = pleftbottom->v - plefttop->v;
 
 		// TODO: make this a function; modularize this function in general
 
-		ystart = plefttop[1];
-		d_aspancount = plefttop[0] - prighttop[0];
-		d_ptex = r_affinetridesc.pskin + (plefttop[2] >> 16) +
-				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
+		ystart = plefttop->v;
+		d_aspancount = plefttop->u - prighttop->u;
+		d_ptex = r_affinetridesc.pskin + (plefttop->s >> 16) +
+				(plefttop->t >> 16) * r_affinetridesc.skinwidth;
 		d_sfrac = 0;
 		d_tfrac = 0;
-		d_light = plefttop[4];
-		d_zi = plefttop[5];
+		d_zi = plefttop->zi;
+		d_light[0] = plefttop->l[0];
+		d_light[1] = plefttop->l[1];
+		d_light[2] = plefttop->l[2];
 
-		d_pdest = d_viewbuffer + ystart * screenwidth + plefttop[0];
-		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
+		d_pdest = d_viewbuffer + ystart * screenwidth + plefttop->u;
+		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop->u;
 
 		if (height == 1)
 		{
@@ -743,13 +733,15 @@
 			d_pedgespanpackage->tfrac = d_tfrac;
 
 			// FIXME: need to clamp l, s, t, at both ends?
-			d_pedgespanpackage->light = d_light;
+			d_pedgespanpackage->light[0] = d_light[0];
+			d_pedgespanpackage->light[1] = d_light[1];
+			d_pedgespanpackage->light[2] = d_light[2];
 			d_pedgespanpackage->zi = d_zi;
 		}
 		else
 		{
-			D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
-								  pleftbottom[0], pleftbottom[1]);
+			D_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
+								  pleftbottom->u, pleftbottom->v);
 
 			d_pdestbasestep = screenwidth + ubasestep;
 			d_pdestextrastep = d_pdestbasestep + 1;
@@ -756,10 +748,15 @@
 			d_pzbasestep = d_zwidth + ubasestep;
 			d_pzextrastep = d_pzbasestep + 1;
 
-			if (ubasestep < 0)
-				working_lstepx = r_lstepx - 1;
-			else
-				working_lstepx = r_lstepx;
+			if (ubasestep < 0){
+				working_lstepx[0] = r_lstepx[0] - 1;
+				working_lstepx[1] = r_lstepx[1] - 1;
+				working_lstepx[2] = r_lstepx[2] - 1;
+			}else{
+				working_lstepx[0] = r_lstepx[0];
+				working_lstepx[1] = r_lstepx[1];
+				working_lstepx[2] = r_lstepx[2];
+			}
 
 			d_countextrastep = ubasestep + 1;
 			d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
@@ -767,7 +764,9 @@
 					r_affinetridesc.skinwidth;
 			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
 			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
-			d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
+			d_lightbasestep[0] = r_lstepy[0] + working_lstepx[0] * ubasestep;
+			d_lightbasestep[1] = r_lstepy[1] + working_lstepx[1] * ubasestep;
+			d_lightbasestep[2] = r_lstepy[2] + working_lstepx[2] * ubasestep;
 			d_zibasestep = r_zistepy + r_zistepx * ubasestep;
 
 			d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
@@ -775,7 +774,9 @@
 					r_affinetridesc.skinwidth;
 			d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
 			d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
-			d_lightextrastep = d_lightbasestep + working_lstepx;
+			d_lightextrastep[0] = d_lightbasestep[0] + working_lstepx[0];
+			d_lightextrastep[1] = d_lightbasestep[1] + working_lstepx[1];
+			d_lightextrastep[2] = d_lightbasestep[2] + working_lstepx[2];
 			d_ziextrastep = d_zibasestep + r_zistepx;
 
 			D_PolysetScanLeftEdge (height);
@@ -786,8 +787,8 @@
 	// count field
 	d_pedgespanpackage = a_spans;
 
-	D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
-						  prightbottom[0], prightbottom[1]);
+	D_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
+						  prightbottom->u, prightbottom->v);
 	d_aspancount = 0;
 	d_countextrastep = ubasestep + 1;
 	originalcount = a_spans[initialrightheight].count;
@@ -803,15 +804,15 @@
 		pstart = a_spans + initialrightheight;
 		pstart->count = originalcount;
 
-		d_aspancount = prightbottom[0] - prighttop[0];
+		d_aspancount = prightbottom->u - prighttop->u;
 
 		prighttop = prightbottom;
 		prightbottom = pedgetable->prightedgevert2;
 
-		height = prightbottom[1] - prighttop[1];
+		height = prightbottom->v - prighttop->v;
 
-		D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
-							  prightbottom[0], prightbottom[1]);
+		D_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
+							  prightbottom->u, prightbottom->v);
 
 		d_countextrastep = ubasestep + 1;
 		a_spans[initialrightheight + height].count = Q_MININT;
@@ -828,7 +829,7 @@
 */
 void D_PolysetSetEdgeTable (void)
 {
-	int			edgetableindex;
+	int edgetableindex;
 
 	edgetableindex = 0;	// assume the vertices are already in
 						//  top to bottom order
@@ -835,46 +836,26 @@
 
 	// determine which edges are right & left, and the order in which
 	// to rasterize them
-	if (r_p0[1] >= r_p1[1])
-	{
-		if (r_p0[1] == r_p1[1])
-		{
-			if (r_p0[1] < r_p2[1])
-				pedgetable = &edgetables[2];
-			else
-				pedgetable = &edgetables[5];
-
+	if(r_p0.v >= r_p1.v){
+		if(r_p0.v == r_p1.v){
+			pedgetable = &edgetables[r_p0.v < r_p2.v ? 2 : 5];
 			return;
 		}
-		else
-		{
-			edgetableindex = 1;
-		}
+		edgetableindex = 1;
 	}
 
-	if (r_p0[1] == r_p2[1])
-	{
-		if (edgetableindex)
-			pedgetable = &edgetables[8];
-		else
-			pedgetable = &edgetables[9];
-
+	if(r_p0.v == r_p2.v){
+		pedgetable = &edgetables[edgetableindex ? 8 : 9];
 		return;
 	}
-	else if (r_p1[1] == r_p2[1])
-	{
-		if (edgetableindex)
-			pedgetable = &edgetables[10];
-		else
-			pedgetable = &edgetables[11];
-
+	if(r_p1.v == r_p2.v){
+		pedgetable = &edgetables[edgetableindex ? 10 : 11];
 		return;
 	}
 
-	if (r_p0[1] > r_p2[1])
+	if(r_p0.v > r_p2.v)
 		edgetableindex += 2;
-
-	if (r_p1[1] > r_p2[1])
+	if(r_p1.v > r_p2.v)
 		edgetableindex += 4;
 
 	pedgetable = &edgetables[edgetableindex];
--- a/model_bsp.c
+++ b/model_bsp.c
@@ -212,10 +212,37 @@
 int
 BSP_LoadLighting(model_t *mod, byte *in, int sz)
 {
-	if(sz == 0)
+	int i, litsz;
+	byte *lit;
+	char s[64], *t;
+
+	if(sz == 0){
 		mod->lightdata = nil;
-	else
-		memcpy(mod->lightdata = Hunk_Alloc(sz), in, sz);
+		return 0;
+	}
+
+	strcpy(s, mod->name);
+	lit = nil;
+	if((t = strrchr(s, '.')) != nil){
+		strcpy(t, ".lit");
+		if((lit = loadhunklmp(s, &litsz)) != nil && litsz >= 4+4+sz*3){
+			if(memcmp(lit, "QLIT", 4) == 0 && lit[4] == 1 && lit[5] == 0 && lit[6] == 0 && lit[7] == 0){
+				mod->lightdata = lit + 8;
+				return 0;
+			}else{
+				Con_Printf("%s: invalid/unsupported LIT file\n", s);
+			}
+		}else{
+			lit = nil;
+		}
+	}
+
+	mod->lightdata = lit ? lit : Hunk_Alloc(sz*3);
+	for(i = 0; i < sz; i++){
+		mod->lightdata[i*3+0] = in[i];
+		mod->lightdata[i*3+1] = in[i];
+		mod->lightdata[i*3+2] = in[i];
+	}
 	return 0;
 }
 
@@ -390,7 +417,7 @@
 		memmove(out->styles, in, MAXLIGHTMAPS);
 		in += MAXLIGHTMAPS;
 		i = le32(in);
-		out->samples = i < 0 ? nil : mod->lightdata + i;
+		out->samples = i < 0 ? nil : mod->lightdata + i*3;
 
 		// set the drawing flags flag
 
--- a/model_bsp2.c
+++ b/model_bsp2.c
@@ -86,7 +86,7 @@
 
 		memmove(out->styles, in, MAXLIGHTMAPS);
 		in += MAXLIGHTMAPS;
-		out->samples = (i = le32(in)) < 0 ? nil : mod->lightdata + i;
+		out->samples = (i = le32(in)) < 0 ? nil : mod->lightdata + i*3;
 
 		// set the drawing flags flag
 
--- a/model_bsp30.c
+++ b/model_bsp30.c
@@ -43,18 +43,12 @@
 int
 BSP30_LoadLighting(model_t *mod, byte *in, int sz)
 {
-	int i;
-
 	if(sz == 0){
 		mod->lightdata = nil;
 		return 0;
 	}
 
-	// FIXME(sigrid): change when colored lighting support is in
-	sz /= 3;
-	mod->lightdata = Hunk_Alloc(sz);
-	for(i = 0; i < sz; i++, in += 3)
-		mod->lightdata[i] = (in[0] + in[1] + in[2])/3;
+	memcpy(mod->lightdata = Hunk_Alloc(sz), in, sz);
 	return 0;
 }
 
@@ -90,8 +84,7 @@
 			if(i % 3)
 				Con_Printf("misaligned light samples: %d\n", i);
 			else{
-				// FIXME(sigrid): change when colored lighting support is in
-				out->samples = mod->lightdata + i/3;
+				out->samples = mod->lightdata + i;
 			}
 		}
 
--- a/r_aclip.c
+++ b/r_aclip.c
@@ -25,46 +25,47 @@
 {
 	float		scale;
 	auxvert_t	*pav0, *pav1, avout;
+	int i;
 
 	pav0 = &av[pfv0 - &fv[0][0]];
 	pav1 = &av[pfv1 - &fv[0][0]];
 
-	if (pfv0->v[1] >= pfv1->v[1])
+	if (pfv0->v >= pfv1->v)
 	{
-		scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) /
-				(pav1->fv[2] - pav0->fv[2]);
+		scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / (pav1->fv[2] - pav0->fv[2]);
 
 		avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale;
 		avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale;
 		avout.fv[2] = ALIAS_Z_CLIP_PLANE;
 
-		out->v[2] =	pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale;
-		out->v[3] =	pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale;
-		out->v[4] =	pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale;
+		out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
+		out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
+		for(i = 0; i < 3; i++)
+			out->l[i] = pfv0->l[i] + (pfv1->l[i] - pfv0->l[i]) * scale;
 	}
 	else
 	{
-		scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) /
-				(pav0->fv[2] - pav1->fv[2]);
+		scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / (pav0->fv[2] - pav1->fv[2]);
 
 		avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale;
 		avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale;
 		avout.fv[2] = ALIAS_Z_CLIP_PLANE;
 
-		out->v[2] =	pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale;
-		out->v[3] =	pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale;
-		out->v[4] =	pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale;
+		out->s = pfv1->s + (pfv0->s - pfv1->s) * scale;
+		out->t = pfv1->t + (pfv0->t - pfv1->t) * scale;
+		for(i = 0; i < 3; i++)
+			out->l[i] = pfv1->l[i] + (pfv0->l[i] - pfv1->l[i]) * scale;
 	}
 
 	R_AliasProjectFinalVert (out, &avout);
 
-	if (out->v[0] < r_refdef.aliasvrect.x)
+	if (out->u < r_refdef.aliasvrect.x)
 		out->flags |= ALIAS_LEFT_CLIP;
-	if (out->v[1] < r_refdef.aliasvrect.y)
+	if (out->v < r_refdef.aliasvrect.y)
 		out->flags |= ALIAS_TOP_CLIP;
-	if (out->v[0] > r_refdef.aliasvrectright)
+	if (out->u > r_refdef.aliasvrectright)
 		out->flags |= ALIAS_RIGHT_CLIP;
-	if (out->v[1] > r_refdef.aliasvrectbottom)
+	if (out->v > r_refdef.aliasvrectbottom)
 		out->flags |= ALIAS_BOTTOM_CLIP;
 }
 
@@ -74,43 +75,32 @@
 	float		scale;
 	int			i;
 
-	if (pfv0->v[1] >= pfv1->v[1])
-	{
-		scale = (float)(r_refdef.aliasvrect.x - pfv0->v[0]) /
-				(pfv1->v[0] - pfv0->v[0]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	if(pfv0->v >= pfv1->v){
+		scale = (float)(r_refdef.aliasvrect.x - pfv0->u) / (pfv1->u - pfv0->u);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv0->x[i] + (pfv1->x[i] - pfv0->x[i])*scale + 0.5;
+	}else{
+		scale = (float)(r_refdef.aliasvrect.x - pfv1->u) / (pfv0->u - pfv1->u);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv1->x[i] + (pfv0->x[i] - pfv1->x[i])*scale + 0.5;
 	}
-	else
-	{
-		scale = (float)(r_refdef.aliasvrect.x - pfv1->v[0]) /
-				(pfv0->v[0] - pfv1->v[0]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
-	}
 }
 
 
-void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
-	finalvert_t *out)
+void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
 {
 	float		scale;
 	int			i;
 
-	if (pfv0->v[1] >= pfv1->v[1])
-	{
-		scale = (float)(r_refdef.aliasvrectright - pfv0->v[0]) /
-				(pfv1->v[0] - pfv0->v[0]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	if(pfv0->v >= pfv1->v){
+		scale = (float)(r_refdef.aliasvrectright - pfv0->u) / (pfv1->u - pfv0->u);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv0->x[i] + (pfv1->x[i] - pfv0->x[i])*scale + 0.5;
+	}else{
+		scale = (float)(r_refdef.aliasvrectright - pfv1->u) / (pfv0->u - pfv1->u);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv1->x[i] + (pfv0->x[i] - pfv1->x[i])*scale + 0.5;
 	}
-	else
-	{
-		scale = (float)(r_refdef.aliasvrectright - pfv1->v[0]) /
-				(pfv0->v[0] - pfv1->v[0]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
-	}
 }
 
 
@@ -119,44 +109,33 @@
 	float		scale;
 	int			i;
 
-	if (pfv0->v[1] >= pfv1->v[1])
-	{
-		scale = (float)(r_refdef.aliasvrect.y - pfv0->v[1]) /
-				(pfv1->v[1] - pfv0->v[1]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
+	if(pfv0->v >= pfv1->v){
+		scale = (float)(r_refdef.aliasvrect.y - pfv0->v) / (pfv1->v - pfv0->v);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv0->x[i] + (pfv1->x[i] - pfv0->x[i])*scale + 0.5;
+	}else{
+		scale = (float)(r_refdef.aliasvrect.y - pfv1->v) / (pfv0->v - pfv1->v);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv1->x[i] + (pfv0->x[i] - pfv1->x[i])*scale + 0.5;
 	}
-	else
-	{
-		scale = (float)(r_refdef.aliasvrect.y - pfv1->v[1]) /
-				(pfv0->v[1] - pfv1->v[1]);
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
-	}
 }
 
 
-void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
-	finalvert_t *out)
+void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
 {
 	float		scale;
 	int			i;
 
-	if (pfv0->v[1] >= pfv1->v[1])
-	{
-		scale = (float)(r_refdef.aliasvrectbottom - pfv0->v[1]) /
-				(pfv1->v[1] - pfv0->v[1]);
+	if(pfv0->v >= pfv1->v){
+		scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) / (pfv1->v - pfv0->v);
 
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i])*scale + 0.5;
-	}
-	else
-	{
-		scale = (float)(r_refdef.aliasvrectbottom - pfv1->v[1]) /
-				(pfv0->v[1] - pfv1->v[1]);
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv0->x[i] + (pfv1->x[i] - pfv0->x[i])*scale + 0.5;
+	}else{
+		scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) / (pfv0->v - pfv1->v);
 
-		for (i=0 ; i<6 ; i++)
-			out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i])*scale + 0.5;
+		for (i=0 ; i<nelem(out->x) ; i++)
+			out->x[i] = pfv1->x[i] + (pfv0->x[i] - pfv1->x[i])*scale + 0.5;
 	}
 }
 
@@ -180,13 +159,13 @@
 		{
 			clip (&in[j], &in[i], &out[k]);
 			out[k].flags = 0;
-			if (out[k].v[0] < r_refdef.aliasvrect.x)
+			if (out[k].u < r_refdef.aliasvrect.x)
 				out[k].flags |= ALIAS_LEFT_CLIP;
-			if (out[k].v[1] < r_refdef.aliasvrect.y)
+			if (out[k].v < r_refdef.aliasvrect.y)
 				out[k].flags |= ALIAS_TOP_CLIP;
-			if (out[k].v[0] > r_refdef.aliasvrectright)
+			if (out[k].u > r_refdef.aliasvrectright)
 				out[k].flags |= ALIAS_RIGHT_CLIP;
-			if (out[k].v[1] > r_refdef.aliasvrectbottom)
+			if (out[k].v > r_refdef.aliasvrectbottom)
 				out[k].flags |= ALIAS_BOTTOM_CLIP;
 			k++;
 		}
@@ -228,7 +207,7 @@
 			fv[0][i] = pfinalverts[ptri->vertindex[i]];
 
 			if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM) )
-				fv[0][i].v[2] += r_affinetridesc.seamfixupX16;
+				fv[0][i].s += r_affinetridesc.seamfixupX16;
 		}
 	}
 
@@ -255,8 +234,7 @@
 
 	if (clipflags & ALIAS_LEFT_CLIP)
 	{
-		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
-							ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
 		if (k == 0)
 			return;
 
@@ -265,8 +243,7 @@
 
 	if (clipflags & ALIAS_RIGHT_CLIP)
 	{
-		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
-							ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
 		if (k == 0)
 			return;
 
@@ -275,8 +252,7 @@
 
 	if (clipflags & ALIAS_BOTTOM_CLIP)
 	{
-		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
-							ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
 		if (k == 0)
 			return;
 
@@ -285,8 +261,7 @@
 
 	if (clipflags & ALIAS_TOP_CLIP)
 	{
-		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
-							ALIAS_TOP_CLIP, k, R_Alias_clip_top);
+		k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], ALIAS_TOP_CLIP, k, R_Alias_clip_top);
 		if (k == 0)
 			return;
 
@@ -295,15 +270,15 @@
 
 	for (i=0 ; i<k ; i++)
 	{
-		if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x)
-			fv[pingpong][i].v[0] = r_refdef.aliasvrect.x;
-		else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright)
-			fv[pingpong][i].v[0] = r_refdef.aliasvrectright;
+		if (fv[pingpong][i].u < r_refdef.aliasvrect.x)
+			fv[pingpong][i].u = r_refdef.aliasvrect.x;
+		else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
+			fv[pingpong][i].u = r_refdef.aliasvrectright;
 
-		if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y)
-			fv[pingpong][i].v[1] = r_refdef.aliasvrect.y;
-		else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom)
-			fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom;
+		if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
+			fv[pingpong][i].v = r_refdef.aliasvrect.y;
+		else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
+			fv[pingpong][i].v = r_refdef.aliasvrectbottom;
 
 		fv[pingpong][i].flags = 0;
 	}
@@ -322,4 +297,3 @@
 		D_PolysetDraw (currententity->colormap);
 	}
 }
-
--- a/r_alias.c
+++ b/r_alias.c
@@ -9,8 +9,8 @@
 finalvert_t			*pfinalverts;
 static mdl_t		*pmdl;
 static vec3_t		r_plightvec;
-static int			r_ambientlight;
-static float		r_shadelight;
+static int			r_ambientlight[3];
+static float		r_shadelight[3];
 static aliashdr_t	*paliashdr;
 static float		ziscale;
 static model_t		*pmodel;
@@ -248,13 +248,13 @@
 		{
 			 R_AliasProjectFinalVert (fv, av);
 
-			if (fv->v[0] < r_refdef.aliasvrect.x)
+			if (fv->u < r_refdef.aliasvrect.x)
 				fv->flags |= ALIAS_LEFT_CLIP;
-			if (fv->v[1] < r_refdef.aliasvrect.y)
+			if (fv->v < r_refdef.aliasvrect.y)
 				fv->flags |= ALIAS_TOP_CLIP;
-			if (fv->v[0] > r_refdef.aliasvrectright)
+			if (fv->u > r_refdef.aliasvrectright)
 				fv->flags |= ALIAS_RIGHT_CLIP;
-			if (fv->v[1] > r_refdef.aliasvrectbottom)
+			if (fv->v > r_refdef.aliasvrectbottom)
 				fv->flags |= ALIAS_BOTTOM_CLIP;
 		}
 	}
@@ -372,36 +372,35 @@
 */
 static void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts)
 {
-	int		temp;
 	float	lightcos;
 
-	av->fv[0] = DotProduct_(pverts->v, aliastransform[0]) +
-			aliastransform[0][3];
-	av->fv[1] = DotProduct_(pverts->v, aliastransform[1]) +
-			aliastransform[1][3];
-	av->fv[2] = DotProduct_(pverts->v, aliastransform[2]) +
-			aliastransform[2][3];
+	av->fv[0] = DotProduct_(pverts->v, aliastransform[0]) + aliastransform[0][3];
+	av->fv[1] = DotProduct_(pverts->v, aliastransform[1]) + aliastransform[1][3];
+	av->fv[2] = DotProduct_(pverts->v, aliastransform[2]) + aliastransform[2][3];
 
-	fv->v[2] = pstverts->s;
-	fv->v[3] = pstverts->t;
+	fv->s = pstverts->s;
+	fv->t = pstverts->t;
 
 	fv->flags = pstverts->onseam;
 
 	// lighting
 	lightcos = DotProduct(r_avertexnormals[pverts->lightnormalindex], r_plightvec);
-	temp = r_ambientlight;
+	fv->l[0] = r_ambientlight[0];
+	fv->l[1] = r_ambientlight[1];
+	fv->l[2] = r_ambientlight[2];
 
 	if (lightcos < 0)
 	{
-		temp += (int)(r_shadelight * lightcos);
+		fv->l[0] += r_shadelight[0] * lightcos;
+		fv->l[1] += r_shadelight[1] * lightcos;
+		fv->l[2] += r_shadelight[2] * lightcos;
 
 		// clamp; because we limited the minimum ambient and shading light, we
 		// don't have to clamp low light, just bright
-		if (temp < 0)
-			temp = 0;
+		fv->l[0] = max(0, fv->l[0]);
+		fv->l[1] = max(0, fv->l[1]);
+		fv->l[2] = max(0, fv->l[2]);
 	}
-
-	fv->v[4] = temp;
 }
 
 
@@ -412,44 +411,44 @@
 */
 void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts, trivertx_t *pverts)
 {
-	int			i, temp;
+	int			i;
 	float		lightcos, zi;
 
 	for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
 	{
 		// transform and project
-		zi = 1.0 / (DotProduct_(pverts->v, aliastransform[2]) +
-				aliastransform[2][3]);
+		zi = 1.0 / (DotProduct_(pverts->v, aliastransform[2]) + aliastransform[2][3]);
 
 		// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
 		// scaled up by 1/2**31, and the scaling cancels out for x and y in the
 		// projection
-		fv->v[5] = zi;
+		fv->zi = zi;
 
-		fv->v[0] = ((DotProduct_(pverts->v, aliastransform[0]) +
-				aliastransform[0][3]) * zi) + aliasxcenter;
-		fv->v[1] = ((DotProduct_(pverts->v, aliastransform[1]) +
-				aliastransform[1][3]) * zi) + aliasycenter;
+		fv->u = ((DotProduct_(pverts->v, aliastransform[0]) + aliastransform[0][3]) * zi) + aliasxcenter;
+		fv->v = ((DotProduct_(pverts->v, aliastransform[1]) + aliastransform[1][3]) * zi) + aliasycenter;
 
-		fv->v[2] = pstverts->s;
-		fv->v[3] = pstverts->t;
+		fv->s = pstverts->s;
+		fv->t = pstverts->t;
 		fv->flags = pstverts->onseam;
 
 		// lighting
 		lightcos = DotProduct(r_avertexnormals[pverts->lightnormalindex], r_plightvec);
-		temp = r_ambientlight;
+		fv->l[0] = r_ambientlight[0];
+		fv->l[1] = r_ambientlight[1];
+		fv->l[2] = r_ambientlight[2];
 
 		if (lightcos < 0)
 		{
-			temp += (int)(r_shadelight * lightcos);
+			fv->l[0] += r_shadelight[0] * lightcos;
+			fv->l[1] += r_shadelight[1] * lightcos;
+			fv->l[2] += r_shadelight[2] * lightcos;
 
 			// clamp; because we limited the minimum ambient and shading light, we
 			// don't have to clamp low light, just bright
-			if (temp < 0)
-				temp = 0;
+			fv->l[0] = max(0, fv->l[0]);
+			fv->l[1] = max(0, fv->l[1]);
+			fv->l[2] = max(0, fv->l[2]);
 		}
-
-		fv->v[4] = temp;
 	}
 }
 
@@ -466,10 +465,10 @@
 	// project points
 	zi = 1.0 / av->fv[2];
 
-	fv->v[5] = zi * ziscale;
+	fv->zi = zi * ziscale;
 
-	fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
-	fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
+	fv->u = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
+	fv->v = (av->fv[1] * aliasyscale * zi) + aliasycenter;
 }
 
 
@@ -494,8 +493,7 @@
 		D_PolysetDrawFinalVerts (fv, r_anumverts, colormap, currententity->alpha);
 
 	r_affinetridesc.pfinalverts = pfinalverts;
-	r_affinetridesc.ptriangles = (mtriangle_t *)
-			((byte *)paliashdr + paliashdr->triangles);
+	r_affinetridesc.ptriangles = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
 	r_affinetridesc.numtriangles = pmdl->numtris;
 
 	D_PolysetDraw (colormap);
@@ -564,29 +562,27 @@
 */
 void R_AliasSetupLighting (alight_t *plighting)
 {
+	int i;
+
 	// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
 	// to clamp off the bottom
-	r_ambientlight = plighting->ambientlight;
+	for(i = 0; i < 3; i++){
+		r_ambientlight[i] = plighting->ambientlight[i];
+		if (r_ambientlight[i] < LIGHT_MIN)
+			r_ambientlight[i] = LIGHT_MIN;
+		r_ambientlight[i] = (255 - r_ambientlight[i]) << VID_CBITS;
+		if (r_ambientlight[i] < LIGHT_MIN)
+			r_ambientlight[i] = LIGHT_MIN;
+		r_shadelight[i] = plighting->shadelight[i];
+		if (r_shadelight[i] < 0)
+			r_shadelight[i] = 0;
+		r_shadelight[i] *= VID_GRADES;
+	}
 
-	if (r_ambientlight < LIGHT_MIN)
-		r_ambientlight = LIGHT_MIN;
-
-	r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
-
-	if (r_ambientlight < LIGHT_MIN)
-		r_ambientlight = LIGHT_MIN;
-
-	r_shadelight = plighting->shadelight;
-
-	if (r_shadelight < 0)
-		r_shadelight = 0;
-
-	r_shadelight *= VID_GRADES;
-
 	// rotate the lighting vector into the model's frame of reference
-	r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
-	r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
-	r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
+	r_plightvec[0] = DotProduct(plighting->plightvec, alias_forward);
+	r_plightvec[1] = -DotProduct(plighting->plightvec, alias_right);
+	r_plightvec[2] = DotProduct(plighting->plightvec, alias_up);
 }
 
 /*
@@ -646,8 +642,8 @@
 */
 void R_AliasDrawModel (alight_t *plighting)
 {
-	static finalvert_t		finalverts[MAXALIASVERTS];
-	static auxvert_t		auxverts[MAXALIASVERTS];
+	static finalvert_t finalverts[MAXALIASVERTS];
+	static auxvert_t auxverts[MAXALIASVERTS];
 	trivertx_t *pverts;
 
 	// cache align
@@ -656,9 +652,9 @@
 	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
 	pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
 
-	R_AliasSetupSkin ();
-	R_AliasSetUpTransform (currententity->trivial_accept);
-	R_AliasSetupLighting (plighting);
+	R_AliasSetupSkin();
+	R_AliasSetUpTransform(currententity->trivial_accept);
+	R_AliasSetupLighting(plighting);
 	pverts = R_AliasSetupFrame ();
 
 	if (!currententity->colormap)
--- a/r_light.c
+++ b/r_light.c
@@ -115,9 +115,9 @@
 =============================================================================
 */
 
-int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
+int
+RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end, int *r)
 {
-	int			r;
 	float		front, back, frac;
 	int			side;
 	mplane_t	*plane;
@@ -130,7 +130,7 @@
 	unsigned	scale;
 	int			maps;
 
-	if (node->contents < 0)
+	if(node->contents < 0)
 		return -1;		// didn't hit anything
 
 	// calculate mid point
@@ -137,12 +137,12 @@
 
 	// FIXME: optimize for axial
 	plane = node->plane;
-	front = DotProduct (start, plane->normal) - plane->dist;
-	back = DotProduct (end, plane->normal) - plane->dist;
+	front = DotProduct(start, plane->normal) - plane->dist;
+	back = DotProduct(end, plane->normal) - plane->dist;
 	side = front < 0;
 
-	if ( (back < 0) == side)
-		return RecursiveLightPoint (node->children[side], start, end);
+	if((back < 0) == side)
+		return RecursiveLightPoint(node->children[side], start, end, r);
 
 	frac = front / (front-back);
 	mid[0] = start[0] + (end[0] - start[0])*frac;
@@ -150,37 +150,34 @@
 	mid[2] = start[2] + (end[2] - start[2])*frac;
 
 	// go down front side
-	r = RecursiveLightPoint (node->children[side], start, mid);
-	if (r >= 0)
-		return r;		// hit something
+	if(RecursiveLightPoint(node->children[side], start, mid, r) >= 0)
+		return 0;		// hit something
 
-	if ( (back < 0) == side )
-		return -1;		// didn't hit anuthing
+	if((back < 0) == side)
+		return -1;		// didn't hit anything
 
 	// check for impact on this node
 
 	surf = cl.worldmodel->surfaces + node->firstsurface;
-	for (i=0 ; i<node->numsurfaces ; i++, surf++)
-	{
-		if (surf->flags & SURF_DRAWTILED)
+	for(i = 0; i < node->numsurfaces; i++, surf++){
+		if(surf->flags & SURF_DRAWTILED)
 			continue;	// no lightmaps
 
 		tex = surf->texinfo;
 
-		s = DotProductDouble (mid, tex->vecs[0]) + tex->vecs[0][3];
-		t = DotProductDouble (mid, tex->vecs[1]) + tex->vecs[1][3];;
+		s = DotProductDouble(mid, tex->vecs[0]) + tex->vecs[0][3];
+		t = DotProductDouble(mid, tex->vecs[1]) + tex->vecs[1][3];
 
-		if (s < surf->texturemins[0] ||
-		t < surf->texturemins[1])
+		if(s < surf->texturemins[0] || t < surf->texturemins[1])
 			continue;
 
 		ds = s - surf->texturemins[0];
 		dt = t - surf->texturemins[1];
 
-		if ( ds > surf->extents[0] || dt > surf->extents[1] )
+		if(ds > surf->extents[0] || dt > surf->extents[1])
 			continue;
 
-		if (!surf->samples)
+		if(!surf->samples)
 			return 0;
 
 		ds >>= 4;
@@ -187,51 +184,50 @@
 		dt >>= 4;
 
 		lightmap = surf->samples;
-		r = 0;
-		if (lightmap)
-		{
+		r[0] = r[1] = r[2] = 0;
+		if(lightmap != nil){
+			lightmap += (dt * ((surf->extents[0]>>4)+1) + ds) * 3;
 
-			lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
-
-			for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
-					maps++)
-			{
+			for(maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++){
 				scale = d_lightstylevalue[surf->styles[maps]];
-				r += *lightmap * scale;
-				lightmap += ((surf->extents[0]>>4)+1) *
-						((surf->extents[1]>>4)+1);
+				r[0] += lightmap[0] * scale;
+				r[1] += lightmap[1] * scale;
+				r[2] += lightmap[2] * scale;
+				lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1) * 3;
 			}
 
-			r >>= 8;
+			r[0] >>= 8;
+			r[1] >>= 8;
+			r[2] >>= 8;
 		}
 
-		return r;
+		return 0;
 	}
 
 	// go down back side
-	return RecursiveLightPoint (node->children[!side], mid, end);
+	return RecursiveLightPoint(node->children[!side], mid, end, r);
 }
 
-int R_LightPoint (vec3_t p)
+void
+R_LightPoint(vec3_t p, int *r)
 {
 	vec3_t		end;
-	int			r;
 
-	if (!cl.worldmodel->lightdata)
-		return 255;
+	if (!cl.worldmodel->lightdata){
+		r[0] = 255;
+		r[1] = 255;
+		r[2] = 255;
+		return;
+	}
 
 	end[0] = p[0];
 	end[1] = p[1];
 	end[2] = p[2] - 2048;
 
-	r = RecursiveLightPoint (cl.worldmodel->nodes, p, end);
-
-	if (r == -1)
-		r = 0;
-
-	if (r < r_refdef.ambientlight)
-		r = r_refdef.ambientlight;
-
-	return r;
+	r[0] = r[1] = r[2] = -1024;
+	RecursiveLightPoint (cl.worldmodel->nodes, p, end, r);
+	r[0] = max(r[0], r_refdef.ambientlight[0]);
+	r[1] = max(r[1], r_refdef.ambientlight[1]);
+	r[2] = max(r[2], r_refdef.ambientlight[2]);
 }
 
--- a/r_local.h
+++ b/r_local.h
@@ -22,8 +22,8 @@
 // viewmodel lighting
 
 typedef struct {
-	int			ambientlight;
-	int			shadelight;
+	int			ambientlight[3];
+	int			shadelight[3];
 	float		*plightvec;
 } alight_t;
 
@@ -115,9 +115,10 @@
 void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
 void R_TransformFrustum (void);
 void R_SetSkyFrame (void);
-void R_DrawSurfaceBlock8 (void);
 texture_t *R_TextureAnimation (texture_t *base);
 
+pixel_t addlight(pixel_t x, int lr, int lg, int lb);
+
 void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags);
 void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel);
 
@@ -228,7 +229,7 @@
 
 void R_StoreEfrags (efrag_t **ppefrag);
 void R_AnimateLight (void);
-int R_LightPoint (vec3_t p);
+void R_LightPoint (vec3_t p, int *r);
 void R_SetupFrame (void);
 void R_cshift_f (void);
 void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
--- a/r_main.c
+++ b/r_main.c
@@ -2,7 +2,7 @@
 
 void		*colormap;
 static vec3_t viewlightvec;
-static alight_t r_viewlighting = {128, 192, viewlightvec};
+static alight_t r_viewlighting = {{128,128,128}, {192,192,192}, viewlightvec};
 int			r_numallocatededges;
 int			r_numallocatedbasespans;
 void		*r_basespans;
@@ -466,7 +466,7 @@
 	float		lightvec[3] = {-1, 0, 0}; // FIXME: remove and do real lighting
 	float		minmaxs[6];
 	vec3_t		dist, oldorigin;
-	float		add;
+	int		add;
 	model_t		*clmodel;
 
 	if(!r_drawentities.value || e == &cl_entities[cl.viewentity])
@@ -493,26 +493,30 @@
 		if(!R_AliasCheckBBox())
 			break;
 
-		j = R_LightPoint(currententity->origin);
-		lighting.ambientlight = j;
-		lighting.shadelight = j;
+		R_LightPoint(currententity->origin, lighting.ambientlight);
+		lighting.shadelight[0] = lighting.ambientlight[0];
+		lighting.shadelight[1] = lighting.ambientlight[1];
+		lighting.shadelight[2] = lighting.ambientlight[2];
 		lighting.plightvec = lightvec;
 
-		add = 0;
 		for(k = 0; k < MAX_DLIGHTS; k++){
 			if(cl_dlights[k].die < cl.time || cl_dlights[k].radius == 0)
 				continue;
 			VectorSubtract(e->origin, cl_dlights[k].origin, dist);
-			add += cl_dlights[k].radius - Length(dist);
-			if(add > 0)
-				lighting.ambientlight += add;
+			add = cl_dlights[k].radius - Length(dist);
+			if(add > 0){
+				lighting.ambientlight[0] += add;
+				lighting.ambientlight[1] += add;
+				lighting.ambientlight[2] += add;
+			}
 		}
 
 		// clamp lighting so it doesn't overbright as much
-		if(lighting.ambientlight > 128)
-			lighting.ambientlight = 128;
-		if(lighting.ambientlight + lighting.shadelight > 192)
-			lighting.shadelight = 192 - lighting.ambientlight;
+		for(j = 0; j < 3; j++){
+			lighting.ambientlight[j] = min(lighting.ambientlight[j], 128);
+			if(lighting.ambientlight[j] + lighting.shadelight[j] > 192)
+				lighting.shadelight[j] = 192 - lighting.ambientlight[j];
+		}
 
 		R_AliasDrawModel(&lighting);
 		break;
@@ -601,8 +605,7 @@
 {
 	// FIXME: remove and do real lighting
 	float		lightvec[3] = {-1, 0, 0};
-	int			j;
-	int			lnum;
+	int			lnum, i;
 	vec3_t		dist;
 	float		add;
 	dlight_t	*dl;
@@ -626,13 +629,15 @@
 	VectorCopy (vup, viewlightvec);
 	VectorInverse (viewlightvec);
 
-	j = R_LightPoint (currententity->origin);
+	R_LightPoint(currententity->origin, r_viewlighting.ambientlight);
+	// always give some light on gun
+	r_viewlighting.ambientlight[0] = max(r_viewlighting.ambientlight[0], 24);
+	r_viewlighting.ambientlight[1] = max(r_viewlighting.ambientlight[1], 24);
+	r_viewlighting.ambientlight[2] = max(r_viewlighting.ambientlight[2], 24);
+	r_viewlighting.shadelight[0] = r_viewlighting.ambientlight[0];
+	r_viewlighting.shadelight[1] = r_viewlighting.ambientlight[1];
+	r_viewlighting.shadelight[2] = r_viewlighting.ambientlight[2];
 
-	if (j < 24)
-		j = 24;		// always give some light on gun
-	r_viewlighting.ambientlight = j;
-	r_viewlighting.shadelight = j;
-
 	// add dynamic lights
 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
 	{
@@ -642,19 +647,23 @@
 
 		VectorSubtract (currententity->origin, dl->origin, dist);
 		add = dl->radius - Length(dist);
-		if (add > 0)
-			r_viewlighting.ambientlight += add;
+		if (add > 0){
+			r_viewlighting.ambientlight[0] += add;
+			r_viewlighting.ambientlight[1] += add;
+			r_viewlighting.ambientlight[2] += add;
+		}
 	}
 
 	// clamp lighting so it doesn't overbright as much
-	if (r_viewlighting.ambientlight > 128)
-		r_viewlighting.ambientlight = 128;
-	if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
-		r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
+	for(i = 0; i < 3; i++){
+		r_viewlighting.ambientlight[i] = min(r_viewlighting.ambientlight[i], 128);
+		if(r_viewlighting.ambientlight[i] + r_viewlighting.shadelight[i] > 192)
+			r_viewlighting.shadelight[i] = 192 - r_viewlighting.ambientlight[i];
+	}
 
 	r_viewlighting.plightvec = lightvec;
 
-	R_AliasDrawModel (&r_viewlighting);
+	R_AliasDrawModel(&r_viewlighting);
 }
 
 /*
--- a/r_misc.c
+++ b/r_misc.c
@@ -127,10 +127,9 @@
 				r_numallocatededges, r_maxedgesseen);
 	}
 
-	r_refdef.ambientlight = r_ambient.value;
-
-	if (r_refdef.ambientlight < 0)
-		r_refdef.ambientlight = 0;
+	r_refdef.ambientlight[0] = max(0, r_ambient.value);
+	r_refdef.ambientlight[1] = max(0, r_ambient.value);
+	r_refdef.ambientlight[2] = max(0, r_ambient.value);
 
 	R_CheckVariables ();
 
--- a/r_shared.h
+++ b/r_shared.h
@@ -15,8 +15,6 @@
 
 //===================================================================
 
-extern void	R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
-
 extern int		cachewidth;
 extern pixel_t	*cacheblock;
 extern int		screenwidth;
--- a/r_surf.c
+++ b/r_surf.c
@@ -2,30 +2,20 @@
 
 drawsurf_t	r_drawsurf;
 
-static int sourcetstep, lightleftstep, lightrightstep;
+static int sourcetstep;
 static int surfrowbytes;	// used by ASM files
 static int r_stepback;
 static int r_numhblocks, r_numvblocks;
 static pixel_t *r_source, *r_sourcemax;
-static unsigned *r_lightptr;
+static unsigned *r_lightptr[3];
 static int r_lightwidth;
 static pixel_t *pbasesource;
 static void *prowdestbase;
 
-static void R_DrawSurfaceBlock8_mip0 (void);
-static void R_DrawSurfaceBlock8_mip1 (void);
-static void R_DrawSurfaceBlock8_mip2 (void);
-static void R_DrawSurfaceBlock8_mip3 (void);
+static void R_DrawSurfaceBlock8(int mip);
 
-static void (*surfmiptable[4])(void) = {
-	R_DrawSurfaceBlock8_mip0,
-	R_DrawSurfaceBlock8_mip1,
-	R_DrawSurfaceBlock8_mip2,
-	R_DrawSurfaceBlock8_mip3
-};
+static unsigned blocklights[3][18*18];
 
-static unsigned blocklights[18*18];
-
 /*
 ===============
 R_AddDynamicLights
@@ -89,8 +79,11 @@
 					dist = sd + (td>>1);
 				else
 					dist = td + (sd>>1);
-				if (dist < minlight)
-					blocklights[t*smax + s] += (rad - dist)*256;
+				if (dist < minlight){
+					blocklights[0][t*smax + s] += (rad - dist)*256;
+					blocklights[1][t*smax + s] += (rad - dist)*256;
+					blocklights[2][t*smax + s] += (rad - dist)*256;
+				}
 			}
 		}
 	}
@@ -122,16 +115,17 @@
 
 	if (r_fullbright.value || !cl.worldmodel->lightdata)
 	{
-		for (i=0 ; i<size ; i++)
-			blocklights[i] = 0;
+		memset(blocklights, 0, sizeof(blocklights));
 		return;
 	}
 
 	// clear to ambient
-	for (i=0 ; i<size ; i++)
-		blocklights[i] = r_refdef.ambientlight<<8;
+	for (i=0 ; i<size ; i++){
+		blocklights[0][i] = r_refdef.ambientlight[0]<<8;
+		blocklights[1][i] = r_refdef.ambientlight[1]<<8;
+		blocklights[2][i] = r_refdef.ambientlight[2]<<8;
+	}
 
-
 	// add all the lightmaps
 	if (lightmap)
 		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
@@ -138,9 +132,12 @@
 			 maps++)
 		{
 			scale = r_drawsurf.lightadj[maps];	// 8.8 fraction
-			for (i=0 ; i<size ; i++)
-				blocklights[i] += lightmap[i] * scale;
-			lightmap += size;	// skip to next lightmap
+			for (i=0 ; i<size ; i++){
+				blocklights[0][i] += lightmap[i*3+0] * scale;
+				blocklights[1][i] += lightmap[i*3+1] * scale;
+				blocklights[2][i] += lightmap[i*3+2] * scale;
+			}
+			lightmap += size * 3;	// skip to next lightmap
 		}
 
 	// add all the dynamic lights
@@ -150,12 +147,12 @@
 	// bound, invert, and shift
 	for (i=0 ; i<size ; i++)
 	{
-		t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
-
-		if (t < (1 << 6))
-			t = (1 << 6);
-
-		blocklights[i] = t;
+		t = (255*256 - (int)blocklights[0][i]) >> (8 - VID_CBITS);
+		blocklights[0][i] = max(t, (1<<6));
+		t = (255*256 - (int)blocklights[1][i]) >> (8 - VID_CBITS);
+		blocklights[1][i] = max(t, (1<<6));
+		t = (255*256 - (int)blocklights[2][i]) >> (8 - VID_CBITS);
+		blocklights[2][i] = max(t, (1<<6));
 	}
 }
 
@@ -210,7 +207,6 @@
 	int				soffset, basetoffset, texwidth;
 	int				horzblockstep;
 	pixel_t	*pcolumndest;
-	void			(*pblockdrawer)(void);
 	texture_t		*mt;
 
 	// calculate the lightings
@@ -235,7 +231,6 @@
 	r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
 	r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
 
-	pblockdrawer = surfmiptable[r_drawsurf.surfmip];
 	// TODO: only needs to be set when there is a display settings change
 	horzblockstep = blocksize;
 
@@ -259,13 +254,15 @@
 
 	for (u=0 ; u<r_numhblocks; u++)
 	{
-		r_lightptr = blocklights + u;
+		r_lightptr[0] = blocklights[0] + u;
+		r_lightptr[1] = blocklights[1] + u;
+		r_lightptr[2] = blocklights[2] + u;
 
 		prowdestbase = pcolumndest;
 
 		pbasesource = basetptr + soffset;
 
-		(*pblockdrawer)();
+		R_DrawSurfaceBlock8(r_drawsurf.surfmip);
 
 		soffset = soffset + blocksize;
 		if (soffset >= smax)
@@ -279,30 +276,29 @@
 //=============================================================================
 
 pixel_t
-addlight(pixel_t x, int light)
+addlight(pixel_t x, int lr, int lg, int lb)
 {
-	int r, g, b, y;
+	int r, g, b, y[3];
 	r = (x>>16) & 0xff;
 	g = (x>>8)  & 0xff;
 	b = (x>>0)  & 0xff;
-	y = (light & 0xff00) >> 8;
+	y[0] = (lr & 0xff00) >> 8;
+	y[1] = (lg & 0xff00) >> 8;
+	y[2] = (lb & 0xff00) >> 8;
 
-	r = (r * (63-y)+16) >> 5; r = min(r, 255);
-	g = (g * (63-y)+16) >> 5; g = min(g, 255);
-	b = (b * (63-y)+16) >> 5; b = min(b, 255);
+	r = (r * (63-y[0])+16) >> 5; r = min(r, 255);
+	g = (g * (63-y[1])+16) >> 5; g = min(g, 255);
+	b = (b * (63-y[2])+16) >> 5; b = min(b, 255);
 	x = (x & ~0xffffff) | r<<16 | g<<8 | b<<0;
 
 	return x;
 }
 
-/*
-================
-R_DrawSurfaceBlock8_mip0
-================
-*/
-static void R_DrawSurfaceBlock8_mip0 (void)
+static void
+R_DrawSurfaceBlock8(int mip)
 {
-	int				b, v, i, lightstep, lighttemp, light, lightleft, lightright;
+	int b, v, i, j, lightstep[3], light[3], lightleft[3], lightright[3];
+	int lightleftstep[3], lightrightstep[3];
 	pixel_t	*psource, *prowdest;
 
 	psource = pbasesource;
@@ -310,163 +306,34 @@
 
 	for (v=0 ; v<r_numvblocks ; v++)
 	{
-		// FIXME: use delta rather than both right and left, like ASM?
-		lightleft = r_lightptr[0];
-		lightright = r_lightptr[1];
-		r_lightptr += r_lightwidth;
-		lightleftstep = (r_lightptr[0] - lightleft) >> 4;
-		lightrightstep = (r_lightptr[1] - lightright) >> 4;
-
-		for (i=0 ; i<16 ; i++)
-		{
-			lighttemp = lightleft - lightright;
-			lightstep = lighttemp >> 4;
-
-			light = lightright;
-			for(b = 15; b >= 0; b--){
-				prowdest[b] = addlight(psource[b], light);
-				light += lightstep;
-			}
-
-			psource += sourcetstep;
-			lightright += lightrightstep;
-			lightleft += lightleftstep;
-			prowdest += surfrowbytes;
+		for(j = 0; j < 3; j++){
+			lightleft[j] = r_lightptr[j][0];
+			lightright[j] = r_lightptr[j][1];
+			r_lightptr[j] += r_lightwidth;
+			lightleftstep[j] = (r_lightptr[j][0] - lightleft[j]) >> (4-mip);
+			lightrightstep[j] = (r_lightptr[j][1] - lightright[j]) >> (4-mip);
 		}
 
-		if (psource >= r_sourcemax)
-			psource -= r_stepback;
-	}
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip1
-================
-*/
-static void R_DrawSurfaceBlock8_mip1 (void)
-{
-	int				v, i, b, lightstep, lighttemp, light, lightleft, lightright;
-	pixel_t	*psource, *prowdest;
-
-	psource = pbasesource;
-	prowdest = prowdestbase;
-
-	for (v=0 ; v<r_numvblocks ; v++)
-	{
-		// FIXME: use delta rather than both right and left, like ASM?
-		lightleft = r_lightptr[0];
-		lightright = r_lightptr[1];
-		r_lightptr += r_lightwidth;
-		lightleftstep = (r_lightptr[0] - lightleft) >> 3;
-		lightrightstep = (r_lightptr[1] - lightright) >> 3;
-
-		for (i=0 ; i<8 ; i++)
+		for (i=0 ; i<16>>mip ; i++)
 		{
-			lighttemp = lightleft - lightright;
-			lightstep = lighttemp >> 3;
-
-			light = lightright;
-			for(b = 7; b >= 0; b--){
-				prowdest[b] = addlight(psource[b], light);
-				light += lightstep;
+			for(j = 0; j < 3; j++){
+				lightstep[j] = (lightleft[j] - lightright[j]) >> (4-mip);
+				light[j] = lightright[j];
 			}
 
-			psource += sourcetstep;
-			lightright += lightrightstep;
-			lightleft += lightleftstep;
-			prowdest += surfrowbytes;
-		}
-
-		if (psource >= r_sourcemax)
-			psource -= r_stepback;
-	}
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip2
-================
-*/
-static void R_DrawSurfaceBlock8_mip2 (void)
-{
-	int v, i, b, lightstep, lighttemp, light, lightleft, lightright;
-	pixel_t *psource, *prowdest;
-
-	psource = pbasesource;
-	prowdest = prowdestbase;
-
-	for (v=0 ; v<r_numvblocks ; v++)
-	{
-		// FIXME: use delta rather than both right and left, like ASM?
-		lightleft = r_lightptr[0];
-		lightright = r_lightptr[1];
-		r_lightptr += r_lightwidth;
-		lightleftstep = (r_lightptr[0] - lightleft) >> 2;
-		lightrightstep = (r_lightptr[1] - lightright) >> 2;
-
-		for (i=0 ; i<4 ; i++)
-		{
-			lighttemp = lightleft - lightright;
-			lightstep = lighttemp >> 2;
-
-			light = lightright;
-			for(b = 3; b >= 0; b--){
-				prowdest[b] = addlight(psource[b], light);
-				light += lightstep;
+			for(b = (16>>mip)-1; b >= 0; b--){
+				prowdest[b] = addlight(psource[b], light[0], light[1], light[2]);
+				light[0] += lightstep[0];
+				light[1] += lightstep[1];
+				light[2] += lightstep[2];
 			}
 
 			psource += sourcetstep;
-			lightright += lightrightstep;
-			lightleft += lightleftstep;
 			prowdest += surfrowbytes;
-		}
-
-		if (psource >= r_sourcemax)
-			psource -= r_stepback;
-	}
-}
-
-
-/*
-================
-R_DrawSurfaceBlock8_mip3
-================
-*/
-static void R_DrawSurfaceBlock8_mip3 (void)
-{
-	int v, i, b, lightstep, lighttemp, light, lightleft, lightright;
-	pixel_t *psource, *prowdest;
-
-	psource = pbasesource;
-	prowdest = prowdestbase;
-
-	for (v=0 ; v<r_numvblocks ; v++)
-	{
-		// FIXME: use delta rather than both right and left, like ASM?
-		lightleft = r_lightptr[0];
-		lightright = r_lightptr[1];
-		r_lightptr += r_lightwidth;
-		lightleftstep = (r_lightptr[0] - lightleft) >> 1;
-		lightrightstep = (r_lightptr[1] - lightright) >> 1;
-
-		for (i=0 ; i<2 ; i++)
-		{
-			lighttemp = lightleft - lightright;
-			lightstep = lighttemp >> 1;
-
-			light = lightright;
-			for(b = 1; b >= 0; b--){
-				prowdest[b] = addlight(psource[b], light);
-				light += lightstep;
+			for(j = 0; j < 3; j++){
+				lightright[j] += lightrightstep[j];
+				lightleft[j] += lightleftstep[j];
 			}
-
-			psource += sourcetstep;
-			lightright += lightrightstep;
-			lightleft += lightleftstep;
-			prowdest += surfrowbytes;
 		}
 
 		if (psource >= r_sourcemax)
--- a/render.h
+++ b/render.h
@@ -81,7 +81,7 @@
 
 	float		fov_x, fov_y;
 
-	int			ambientlight;
+	int			ambientlight[3];
 } refdef_t;