ref: 7240eb5e3f0f766939ab5f14add6384b286d253a
parent: acad4d590f4d8484a9e5ec692bc57dc3dddacd8e
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Oct 26 22:01:46 EDT 2023
.alpha: part 2 - drawing/blending
--- a/cl_parse.c
+++ b/cl_parse.c
@@ -590,6 +590,7 @@
// copy it to the current state
ent->model = cl.model_precache[ent->baseline.modelindex];
+ ent->alpha = ent->baseline.alpha;
ent->frame = ent->baseline.frame;
ent->colormap = vid.colormap;
ent->skinnum = ent->baseline.skin;
--- /dev/null
+++ b/d_alpha.c
@@ -1,0 +1,65 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#include "fns.h"
+
+/* FIXME(sigrid): this is super dumb.
+ *
+ * how it SHOULD be done:
+ * 1) no point in 256 alphamaps, a'=255-a → (x->a->y) ≡ (y->a'->x)
+ * 1.1) these are 8-bit colors, no way there are *different* variations for each alpha
+ * eg: x=3, y=9 → a≠a' → there is a very high chance (x->a->y) = (x->a'->y) if a is close to a'
+ * 2) use k-d (3-d in this case) tree to look up colors faster
+ * 3) if it's fast enough, can build all alpha maps just once on startup
+ * 4) try different color models, this alpha blending looks like crap with liquids
+ */
+byte *alphamap[256];
+
+void
+buildalpha(int alpha)
+{
+ extern s32int fbpal[256];
+ int a, b;
+ byte *ca, *cb, *p;
+ int rr, gg, bb;
+ int i, dst, x, best;
+
+ if(alphamap[alpha] != nil)
+ return;
+ alphamap[alpha] = malloc(256*256);
+ p = (byte*)fbpal;
+ ca = p;
+ for(a = 0; a < 256; a++, ca += 4){
+ cb = p;
+ for(b = 0; b < 256; b++, cb++){
+ rr = (alpha*ca[0] + (255 - alpha)*(*cb++))>>8;
+ gg = (alpha*ca[1] + (255 - alpha)*(*cb++))>>8;
+ bb = (alpha*ca[2] + (255 - alpha)*(*cb++))>>8;
+ dst = 9999999;
+ best = 255;
+ for(i = 0; i < 768; i += 4){
+ x = (rr-p[i+0])*(rr-p[i+0]) +
+ (gg-p[i+1])*(gg-p[i+1]) +
+ (bb-p[i+2])*(bb-p[i+2]);
+ if(x < dst){
+ dst = x;
+ best = i;
+ }
+ }
+ alphamap[alpha][a<<8 | b] = best/4;
+ }
+ }
+}
+
+float
+alphafor(int flags)
+{
+ if(flags & (SURF_TELE|SURF_FENCE))
+ return 1.0;
+ if(flags & SURF_LAVA)
+ return r_lavaalpha.value;
+ if(flags & SURF_SLIME)
+ return r_slimealpha.value;
+ return r_wateralpha.value;
+}
--- a/d_edge.c
+++ b/d_edge.c
@@ -144,18 +144,6 @@
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
-static float
-alphafor(surf_t *s)
-{
- if((s->flags & (SURF_LAVA|SURF_SLIME|SURF_TELE)) == 0)
- return r_wateralpha.value;
- if(s->flags & SURF_LAVA)
- return r_lavaalpha.value;
- if(s->flags & SURF_SLIME)
- return r_slimealpha.value;
- return 1.0;
-}
-
/*
==============
D_DrawSurfaces
@@ -168,6 +156,7 @@
surfcache_t *pcurrentcache;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
+ byte alpha;
currententity = &cl_entities[0];
TransformVector (modelorg, transformed_modelorg);
@@ -196,8 +185,16 @@
if (!s->spans)
continue;
- if((s->flags & SURF_TRANS) ^ r_drawflags)
+ if((surfdrawflags(s) | entdrawflags(s->entity)) ^ r_drawflags)
continue;
+ alpha = 255;
+ if(enthasalpha(s->entity) && s->entity->alpha != 255)
+ alpha = s->entity->alpha;
+ else if(s->flags & SURF_TRANS)
+ alpha *= alphafor(s->flags);
+ if(alpha < 1)
+ alpha = 255;
+ buildalpha(alpha);
r_drawnpolycount++;
@@ -245,7 +242,7 @@
}
D_CalcGradients (pface);
- Turbulent8 (s->spans, alphafor(s));
+ Turbulent8 (s->spans, alpha);
D_DrawZSpans (s->spans);
if (s->insubmodel)
@@ -296,11 +293,11 @@
D_CalcGradients (pface);
if(s->flags & SURF_FENCE)
- D_DrawSpans16_Fence(s->spans);
- else
- (*d_drawspans) (s->spans, 1.0);
-
- D_DrawZSpans (s->spans);
+ D_DrawSpans16_Fence(s->spans, alpha);
+ else{
+ (*d_drawspans) (s->spans, alpha);
+ D_DrawZSpans (s->spans);
+ }
if (s->insubmodel)
{
--- a/d_iface.h
+++ b/d_iface.h
@@ -119,7 +119,7 @@
void D_Aff8Patch (void *pcolormap);
void D_PolysetDraw (void);
-void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts);
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts, byte alpha);
void D_DrawParticle (particle_t *pparticle);
void D_DrawPoly (void);
void D_DrawSprite (void);
--- a/d_init.c
+++ b/d_init.c
@@ -18,7 +18,7 @@
extern int d_aflatcolor;
-void (*d_drawspans) (espan_t *pspan, float alpha);
+void (*d_drawspans) (espan_t *pspan, byte alpha);
/*
--- a/d_local.h
+++ b/d_local.h
@@ -51,11 +51,10 @@
fixed16_t bbextents, bbextentt;
void D_DrawSpans8 (espan_t *pspans);
-void D_DrawSpans16 (espan_t *pspans, float alpha);
+void D_DrawSpans16 (espan_t *pspans, byte alpha);
void D_DrawZSpans (espan_t *pspans);
-void Turbulent8 (espan_t *pspan, float alpha);
-void D_SpriteDrawSpans (sspan_t *pspan);
-void D_DrawSpans16_Fence (espan_t *pspan);
+void Turbulent8 (espan_t *pspan, byte alpha);
+void D_DrawSpans16_Fence (espan_t *pspan, byte alpha);
void D_DrawSkyScans8 (espan_t *pspan);
void D_DrawSkyScans16 (espan_t *pspan);
@@ -83,5 +82,12 @@
extern int d_minmip;
extern float d_scalemip[3];
-extern void (*d_drawspans) (espan_t *pspan, float alpha);
+extern void (*d_drawspans) (espan_t *pspan, byte alpha);
+extern byte *alphamap[256];
+
+#define blendalpha(a, b, alpha) \
+ alphamap[alpha][(u16int)((a)<<8 | (b))]
+
+void buildalpha(int alpha);
+float alphafor(int flags);
--- a/d_polyse.c
+++ b/d_polyse.c
@@ -90,7 +90,7 @@
void D_PolysetCalcGradients (int skinwidth);
void D_DrawSubdiv (void);
void D_DrawNonSubdiv (void);
-void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
+void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3, byte alpha);
void D_PolysetSetEdgeTable (void);
void D_RasterizeAliasPolySmooth (void);
void D_PolysetScanLeftEdge (int height);
@@ -125,7 +125,7 @@
D_PolysetDrawFinalVerts
================
*/
-void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
+void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts, byte alpha)
{
int i, z;
uzint *zbuf;
@@ -139,14 +139,19 @@
{
z = fv->v[5]>>16;
zbuf = zspantable[fv->v[1]] + fv->v[0];
- if (z >= *zbuf)
- {
- int pix;
-
- *zbuf = z;
- pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
- pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
- d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+ if (z >= *zbuf){
+ if(r_drawflags & DRAW_BLEND){
+ int n = d_scantable[fv->v[1]] + fv->v[0];
+ int pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+ pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
+ d_viewbuffer[n] = blendalpha(pix, d_viewbuffer[n], alpha);
+ }else{
+ int pix;
+ *zbuf = z;
+ pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
+ pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
+ d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
+ }
}
}
}
@@ -187,7 +192,7 @@
if (ptri[i].facesfront)
{
- D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+ D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v, currententity->alpha);
}
else
{
@@ -204,7 +209,7 @@
if (index2->flags & ALIAS_ONSEAM)
index2->v[2] += r_affinetridesc.seamfixupX16;
- D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
+ D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v, currententity->alpha);
index0->v[2] = s0;
index1->v[2] = s1;
@@ -287,7 +292,7 @@
D_PolysetRecursiveTriangle
================
*/
-void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
+void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3, byte alpha)
{
int *temp;
int d;
@@ -349,19 +354,23 @@
z = new[5]>>16;
zbuf = zspantable[new[1]] + new[0];
- if (z >= *zbuf)
- {
- int pix;
-
- *zbuf = z;
- pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
- d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+ if (z >= *zbuf){
+ if(r_drawflags & DRAW_BLEND){
+ int n = d_scantable[new[1]] + new[0];
+ int pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+ d_viewbuffer[n] = blendalpha(pix, d_viewbuffer[n], alpha);
+ }else{
+ int pix;
+ *zbuf = z;
+ pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
+ d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
+ }
}
nodraw:
// recursively continue
- D_PolysetRecursiveTriangle (lp3, lp1, new);
- D_PolysetRecursiveTriangle (lp3, new, lp2);
+ D_PolysetRecursiveTriangle (lp3, lp1, new, alpha);
+ D_PolysetRecursiveTriangle (lp3, new, lp2, alpha);
}
@@ -547,26 +556,8 @@
a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
}
-
/*
-byte gelmap[256];
-void InitGel (byte *palette)
-{
- int i;
- int r;
-
- for (i=0 ; i<256 ; i++)
- {
-// r = (palette[i*3]>>4);
- r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
- gelmap[i] = 0 + r; // 64
- }
-}
-*/
-
-
-/*
-================
+================
D_PolysetDrawSpans8
================
*/
@@ -952,76 +943,3 @@
pedgetable = &edgetables[edgetableindex];
}
-
-
-/*
-void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
-{
- int d;
- int new[6];
- int ofs;
-
- d = lp2[0] - lp1[0];
- if (d < -1 || d > 1)
- goto split;
- d = lp2[1] - lp1[1];
- if (d < -1 || d > 1)
- goto split;
-
- return; // line is completed
-
-split:
-// split this edge
- new[0] = (lp1[0] + lp2[0]) >> 1;
- new[1] = (lp1[1] + lp2[1]) >> 1;
- new[5] = (lp1[5] + lp2[5]) >> 1;
- new[2] = (lp1[2] + lp2[2]) >> 1;
- new[3] = (lp1[3] + lp2[3]) >> 1;
- new[4] = (lp1[4] + lp2[4]) >> 1;
-
-// draw the point
- ofs = d_scantable[new[1]] + new[0];
- if (new[5] > d_pzbuffer[ofs])
- {
- int pix;
-
- d_pzbuffer[ofs] = new[5];
- pix = skintable[new[3]>>16][new[2]>>16];
-// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
- d_viewbuffer[ofs] = pix;
- }
-
-// recursively continue
- D_PolysetRecursiveDrawLine (lp1, new);
- D_PolysetRecursiveDrawLine (new, lp2);
-}
-
-void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
-{
- int d;
- int new[4];
-
- d = lp2[0] - lp1[0];
- if (d < -1 || d > 1)
- goto split;
- d = lp2[1] - lp1[1];
- if (d < -1 || d > 1)
- goto split;
- return;
-
-split:
-// split this edge
- new[0] = (lp1[0] + lp2[0]) >> 1;
- new[1] = (lp1[1] + lp2[1]) >> 1;
- new[5] = (lp1[5] + lp2[5]) >> 1;
- new[2] = (lp1[2] + lp2[2]) >> 1;
- new[3] = (lp1[3] + lp2[3]) >> 1;
- new[4] = (lp1[4] + lp2[4]) >> 1;
-
- D_PolysetRecursiveDrawLine (new, lp3);
-
-// recursively continue
- D_PolysetRecursiveTriangle (lp1, new, lp3);
- D_PolysetRecursiveTriangle (new, lp2, lp3);
-}
-*/
--- a/d_scan.c
+++ b/d_scan.c
@@ -66,47 +66,6 @@
}
}
-static byte *alphamap[256];
-
-static void
-buildalpha(int alpha)
-{
- extern s32int fbpal[256];
- int a, b;
- byte *ca, *cb, *p;
- int rr, gg, bb;
- int i, dst, x, best;
-
- if(alphamap[alpha] != nil)
- return;
- alphamap[alpha] = malloc(256*256);
- p = (byte*)fbpal;
- ca = p;
- for(a = 0; a < 256; a++, ca += 4){
- cb = p;
- for(b = 0; b < 256; b++, cb++){
- rr = (alpha*ca[0] + (255 - alpha)*(*cb++))>>8;
- gg = (alpha*ca[1] + (255 - alpha)*(*cb++))>>8;
- bb = (alpha*ca[2] + (255 - alpha)*(*cb++))>>8;
- dst = 9999999;
- best = 255;
- for(i = 0; i < 768; i += 4){
- x = (rr-p[i+0])*(rr-p[i+0]) +
- (gg-p[i+1])*(gg-p[i+1]) +
- (bb-p[i+2])*(bb-p[i+2]);
- if(x < dst){
- dst = x;
- best = i;
- }
- }
- alphamap[alpha][a<<8 | b] = best/4;
- }
- }
-}
-
-#define blendalpha(a, b, alpha) \
- alphamap[alpha][(u16int)((a)<<8 | (b))]
-
/*
=============
D_DrawTurbulent8Span
@@ -120,13 +79,8 @@
{
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
- if (*r_turb_z <= (izi >> 16)){
- if(alpha == 255 || alpha == 0)
- *r_turb_pdest = *(r_turb_pbase + (tturb<<6) + sturb);
- else
- *r_turb_pdest = blendalpha(*(r_turb_pbase + (tturb<<6) + sturb), *r_turb_pdest, alpha);
- *r_turb_z = (izi >> 16);
- }
+ if (*r_turb_z <= (izi >> 16))
+ *r_turb_pdest = blendalpha(*(r_turb_pbase + (tturb<<6) + sturb), *r_turb_pdest, alpha);
r_turb_s += r_turb_sstep;
r_turb_t += r_turb_tstep;
r_turb_pdest++;
@@ -140,13 +94,12 @@
Turbulent8
=============
*/
-void Turbulent8 (espan_t *pspan, float alpha)
+void Turbulent8 (espan_t *pspan, byte alpha)
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz16stepu, tdivz16stepu, zi16stepu;
- byte balpha;
r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
@@ -158,9 +111,6 @@
sdivz16stepu = d_sdivzstepu * 16;
tdivz16stepu = d_tdivzstepu * 16;
zi16stepu = d_zistepu * 16;
- alpha = clamp(alpha, 0.0, 1.0);
- balpha = alpha * 255;
- buildalpha(balpha);
do
{
@@ -262,7 +212,7 @@
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
- D_DrawTurbulent8Span ((int)(zi * 0x8000 * 0x10000), balpha);
+ D_DrawTurbulent8Span ((int)(zi * 0x8000 * 0x10000), alpha);
r_turb_s = snext;
r_turb_t = tnext;
@@ -274,14 +224,16 @@
#define WRITEFENCE(i) do{ \
fencepix = *(pbase + (s >> 16) + (t >> 16) * cachewidth); \
- if (pz[i] <= (izi >> 16) && fencepix != 255) \
- pdest[i] = fencepix; pz[i] = (izi >> 16); \
+ if (pz[i] <= (izi >> 16) && fencepix != 255){ \
+ pdest[i] = blendalpha(fencepix, pdest[i], alpha); \
+ pz[i] = (izi >> 16); \
+ } \
izi += izistep; \
s += sstep; \
t += tstep; \
}while(0)
-void D_DrawSpans16_Fence (espan_t *pspan)
+void D_DrawSpans16_Fence (espan_t *pspan, byte alpha)
{
byte fencepix;
byte *pbase = (byte *)cacheblock, *pdest;
@@ -433,15 +385,15 @@
D_DrawSpans16
=============
*/
-void D_DrawSpans16 (espan_t *pspan, float alpha) //qbism- up it from 8 to 16
+void D_DrawSpans16 (espan_t *pspan, byte alpha) //qbism- up it from 8 to 16
{
int count, spancount;
unsigned char *pbase, *pdest;
+ uzint *pz;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivzstepu, tdivzstepu, zistepu;
- USED(alpha);
sstep = 0; // keep compiler happy
tstep = 0; // ditto
@@ -455,6 +407,7 @@
{
pdest = (unsigned char *)((byte *)d_viewbuffer +
(screenwidth * pspan->v) + pspan->u);
+ pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
@@ -549,9 +502,14 @@
if(spancount > 0){
void dospan(uchar *, uchar *, int, int, int, int, int, int);
- dospan(pdest, pbase, s, t, sstep, tstep, spancount, cachewidth);
+ void dospan_alpha(uchar *, uchar *, int, int, int, int, int, int, byte, uzint *, int);
+ if(r_drawflags & DRAW_BLEND)
+ dospan_alpha(pdest, pbase, s, t, sstep, tstep, spancount, cachewidth, alpha, pz, (int)(zi * 0x8000 * 0x10000));
+ else
+ dospan(pdest, pbase, s, t, sstep, tstep, spancount, cachewidth);
}
pdest += spancount;
+ pz += spancount;
s = snext;
t = tnext;
@@ -573,6 +531,9 @@
unsigned ltemp;
double zi;
float du, dv;
+
+ if((r_drawflags & DRAW_BLEND) != 0)
+ return;
// FIXME: check for clamping/range problems
// we count on FP exceptions being turned off to avoid range problems
--- a/d_sprite.c
+++ b/d_sprite.c
@@ -13,7 +13,7 @@
D_SpriteDrawSpans
=====================
*/
-void D_SpriteDrawSpans (sspan_t *pspan)
+void D_SpriteDrawSpans (sspan_t *pspan, byte alpha)
{
int count, spancount, izistep;
int izi;
@@ -142,10 +142,13 @@
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (btemp != 255)
{
- if (*pz <= (izi >> 16)) /* FIXME: segfault: assumed 32bit ptr? */
- {
- *pz = izi >> 16;
- *pdest = btemp;
+ if (*pz <= (izi >> 16)){ /* FIXME: segfault: assumed 32bit ptr? */
+ if(r_drawflags & DRAW_BLEND){
+ *pdest = blendalpha(btemp, *pdest, alpha);
+ }else{
+ *pz = izi >> 16;
+ *pdest = btemp;
+ }
}
}
@@ -414,6 +417,6 @@
D_SpriteCalculateGradients ();
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
- D_SpriteDrawSpans (sprite_spans);
+ D_SpriteDrawSpans (sprite_spans, currententity->alpha);
}
--- a/mkfile
+++ b/mkfile
@@ -7,6 +7,7 @@
OFILES=\
pal`{test -f pal_$objtype.s && echo -n _$objtype}.$O\
span`{test -f span_$objtype.s && echo -n _$objtype}.$O\
+ span_alpha.$O\
cd.$O\
cl_demo.$O\
cl_input.$O\
@@ -19,6 +20,7 @@
console.$O\
cvar.$O\
draw.$O\
+ d_alpha.$O\
d_edge.$O\
d_fill.$O\
d_init.$O\
--- a/model.c
+++ b/model.c
@@ -1172,7 +1172,14 @@
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
-
+ mod->blend = false;
+ for(j = bm->firstface; j < bm->firstface+bm->numfaces; j++){
+ if(surfdrawflags(&loadmodel->surfaces[j]) & DRAW_BLEND){
+ mod->blend = true;
+ break;
+ }
+ }
+
VectorCopy (bm->maxs, mod->maxs);
VectorCopy (bm->mins, mod->mins);
mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
--- a/model.h
+++ b/model.h
@@ -292,6 +292,7 @@
{
char name[Npath];
qboolean needload; // bmodels and sprites don't cache normally
+ qboolean blend;
modtype_t type;
int numframes;
--- a/r_alias.c
+++ b/r_alias.c
@@ -518,7 +518,7 @@
R_AliasTransformAndProjectFinalVerts (fv, pstverts);
if (r_affinetridesc.drawtype)
- D_PolysetDrawFinalVerts (fv, r_anumverts);
+ D_PolysetDrawFinalVerts (fv, r_anumverts, currententity->alpha);
r_affinetridesc.pfinalverts = pfinalverts;
r_affinetridesc.ptriangles = (mtriangle_t *)
--- a/r_bsp.c
+++ b/r_bsp.c
@@ -313,6 +313,9 @@
bedge_t *pbedge;
medge_t *pedge, *pedges;
+ if(entdrawflags(currententity) ^ r_drawflags)
+ return;
+
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
@@ -321,8 +324,6 @@
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
- if((psurf->flags & SURF_TRANS) ^ r_drawflags)
- continue;
// find which side of the node we are on
pplane = psurf->plane;
@@ -386,14 +387,14 @@
// FIXME: use bounding-box-based frustum clipping info?
+ if(entdrawflags(currententity) ^ r_drawflags)
+ return;
+
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
- if((psurf->flags & SURF_TRANS) ^ r_drawflags)
- continue;
-
// find which side of the node we are on
pplane = psurf->plane;
--- a/r_draw.c
+++ b/r_draw.c
@@ -353,6 +353,8 @@
r_emitted = 1;
}
+float alphafor(int flags);
+
/*
================
R_RenderFace
@@ -368,6 +370,9 @@
medge_t *pedges, tedge;
clipplane_t *pclip;
+ if(surfdrawflags(fa) ^ r_drawflags)
+ return;
+
// skip out if no more surfs
if ((surface_p) >= surf_max)
{
@@ -381,9 +386,6 @@
r_outofedges += fa->numedges;
return;
}
-
- if((fa->flags & SURF_TRANS) ^ r_drawflags)
- return;
c_faceclip++;
--- a/r_efrag.c
+++ b/r_efrag.c
@@ -221,7 +221,6 @@
void R_StoreEfrags (efrag_t **ppefrag)
{
entity_t *pent;
- model_t *clmodel;
efrag_t *pefrag;
@@ -228,30 +227,15 @@
while ((pefrag = *ppefrag) != nil)
{
pent = pefrag->entity;
- clmodel = pent->model;
- switch (clmodel->type)
+ if ((pent->visframe != r_framecount) &&
+ (cl_numvisedicts < MAX_VISEDICTS))
{
- case mod_alias:
- case mod_brush:
- case mod_sprite:
- pent = pefrag->entity;
-
- if ((pent->visframe != r_framecount) &&
- (cl_numvisedicts < MAX_VISEDICTS))
- {
- cl_visedicts[cl_numvisedicts++] = pent;
-
- // mark that we've recorded this entity for this frame
- pent->visframe = r_framecount;
- }
-
- ppefrag = &pefrag->leafnext;
- break;
-
- default:
- fatal ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
+ cl_visedicts[cl_numvisedicts++] = pent;
+ pent->visframe = r_framecount;
}
+
+ ppefrag = &pefrag->leafnext;
}
}
--- a/r_local.h
+++ b/r_local.h
@@ -2,6 +2,15 @@
#include "r_shared.h"
+enum {
+ DRAW_BLEND = 1<<0,
+};
+
+#define surfdrawflags(s) (((s)->flags & SURF_TRANS) ? DRAW_BLEND : 0)
+#define enthasalpha(e) ((e) && !defalpha((e)->alpha))
+#define entdrawflags(e) (((e) && (!defalpha((e)->alpha) || ((e)->model && (e)->model != cl.worldmodel && (e)->model->blend))) ? DRAW_BLEND : 0)
+
+
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
// normalizing factor so player model works out to about
// 1 pixel per triangle
--- a/r_main.c
+++ b/r_main.c
@@ -470,7 +470,13 @@
if (currententity == &cl_entities[cl.viewentity])
continue; // don't draw the player
+ if(r_drawflags & DRAW_BLEND)
+ buildalpha(currententity->alpha);
+ // FIXME(sigrid): no trans-specific surfaces, hopefully?
+ if(entdrawflags(currententity) ^ r_drawflags)
+ continue;
+
switch (currententity->model->type)
{
case mod_sprite:
@@ -507,7 +513,7 @@
lighting.ambientlight += add;
}
}
-
+
// clamp lighting so it doesn't overbright as much
if (lighting.ambientlight > 128)
lighting.ambientlight = 128;
@@ -682,6 +688,9 @@
{
currententity = cl_visedicts[i];
+ if(entdrawflags(currententity) ^ r_drawflags)
+ continue;
+
switch (currententity->model->type)
{
case mod_brush:
@@ -750,6 +759,8 @@
if (r_pefragtopnode)
{
+ if(r_drawflags & DRAW_BLEND)
+ R_BeginEdgeFrame();
currententity->topnode = r_pefragtopnode;
if (r_pefragtopnode->contents >= 0)
@@ -767,6 +778,8 @@
}
currententity->topnode = nil;
+ if(r_drawflags & DRAW_BLEND)
+ R_ScanEdges();
}
}
@@ -816,7 +829,8 @@
db_time1 = rw_time2;
}
- R_DrawBEntitiesOnList ();
+ if((r_drawflags & DRAW_BLEND) == 0)
+ R_DrawBEntitiesOnList ();
if (r_dspeeds.value)
{
@@ -861,7 +875,6 @@
if (!cl_entities[0].model || !cl.worldmodel)
fatal ("R_RenderView: NULL worldmodel");
- r_drawflags = 0;
R_EdgeDrawing ();
if (r_dspeeds.value)
@@ -888,8 +901,11 @@
R_DrawParticles ();
- r_drawflags = SURF_TRANS;
+ r_drawflags = DRAW_BLEND;
+ r_worldpolysbacktofront = true;
R_EdgeDrawing ();
+ R_DrawBEntitiesOnList();
+ R_DrawEntitiesOnList ();
r_drawflags = 0;
if (r_dspeeds.value)
--- a/span.c
+++ b/span.c
@@ -1,15 +1,22 @@
#include <u.h>
#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+#define P \
+ do{ \
+ *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; \
+ s += sstep; \
+ t += tstep; \
+ }while(0)
+
void
-dospan(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth)
+dospan(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth, u8int alpha, uzint *z, int izi)
{
-#define P *pdest++ = pbase[(s >> 16) + (t >> 16) * cachewidth]; s += sstep; t += tstep
switch(spancount)
{
case 16: P; case 15: P; case 14: P; case 13: P; case 12: P; case 11: P; case 10: P; case 9: P;
case 8: P; case 7: P; case 6: P; case 5: P; case 4: P; case 3: P; case 2: P; case 1: P;
}
-#undef P
- USED(pdest, s, t);
+ USED(pdest, s, t, z);
}
--- /dev/null
+++ b/span_alpha.c
@@ -1,0 +1,25 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "quakedef.h"
+
+#define P \
+ do{ \
+ if(*z <= (izi >> 16)) \
+ *pdest = blendalpha(pbase[(s >> 16) + (t >> 16) * cachewidth], *pdest, alpha); \
+ pdest++; \
+ z++; \
+ s += sstep; \
+ t += tstep; \
+ }while(0)
+
+void
+dospan_alpha(uchar *pdest, uchar *pbase, int s, int t, int sstep, int tstep, int spancount, int cachewidth, u8int alpha, uzint *z, int izi)
+{
+ switch(spancount)
+ {
+ case 16: P; case 15: P; case 14: P; case 13: P; case 12: P; case 11: P; case 10: P; case 9: P;
+ case 8: P; case 7: P; case 6: P; case 5: P; case 4: P; case 3: P; case 2: P; case 1: P;
+ }
+ USED(pdest, s, t, z);
+}