Index | FAQ | Search | Memberlist | Usergroups | Profile | Log in to check your private messages | Log in | Register

Tutorial: Adding Alpha Transparency to stock GLQUAKE Goto page 1, 2 Next

| Inside3d Forums Forum Index -> Programming Tutorials

View previous topic :: View next topic
Author | Message
--- | ---
Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Fri Nov 21, 2008 1:43 pm Post subject: Tutorial: Adding Alpha Transparency to stock GLQUAKE |

Adding Alpha Transparency to stock GLQUAKE Alpha support lets an engine render func_walls and other map objects with transparency.

Quote:
Currently alpha brush supporting: DarkPlaces, FTEQW, JoeQuake, Qrack and aguirRe GLQuake and probably a number of modder engines. Currently NOT alpha brush supporting: FitzQuake, ezQuake, FuhQuake, TyrQuake, most others.

There are some other modified engines with alpha brush support, but I'm not going to do research on it except I know the following engines do NOT have it:
This tutorial is for support of alpha brushes (i.e. not monsters and sprites). I can't think of a good use of transparent monsters or sprites, but I do like the option of maps with glass looking objects in them.
This tutorial won't give WinQuake this effect, but nothing in this tutorial adversely affects WinQuake (it will compile and run fine with this code).
Before we begin:
1. A good example map is Forwards Compatible (link)
2. Enabling alpha support requires a custom progs.dat file. Merely grab the QuakeC 1.06 source (download). Open up defs.qc and add this to the bottom of the file and compile it with your QuakeC compiler of choice (like FTEQCC).

Quote:

Code:
.float alpha;

3. To make a func_wall or other map object transparent, make sure the brush has an alpha field with some value less than 1 but greater than 0 in the .map file (you'd probably need to manually add the field to a map editor entity definition file.)

Quote:

Code:
{ "classname" "func_wall" "alpha" "0.2" "targetname" "fiendfield" ...
}

Instuctions adding it to stock GLQuake
We are going to do some light changes to NINE files.
Let's hit the header files first.
1. glquake.h

Quote:
glquake.h - Locate "texture_t *R_TextureAnimation ..."; insert this line right after:

Code:
#define ISTRANSPARENT(ent) ((ent)->istransparent && (ent)->transparency > 0 && (ent)->transparency < 1)

We are defining the test of whether or not a brush is transparent.

2. progs.h

Quote:
progs.h - At bottom of file add ...:

Code:
#define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t *)((byte *)&ed->v + fieldoffset) : NULL) // alpha support extern int eval_alpha;

We are borrowing JoeQuake's speedy field lookup shortcut for checking entities. The field we will be using this with is alpha, of course.

3. protocol.h

Quote:
protocol.h - Find "#define U_LONGENTITY (1<<14)", insert after:

Code:
// alpha support #ifdef GLQUAKE #define U_TRANS (1<<15) #endif

We need to add a transparency bit to the protocol definition.

4. render.h

Quote:
render.h - Find "struct mnode_s *topnode;", insert after:

Code:
#ifdef GLQUAKE // alpha support float transparency; qboolean istransparent; #endif

We need the transparency characteristics of the entities stored and readily available.

Now let's do the actual code ...
5. cl_main.c

Quote:
cl_main.c: Find our CL_RelinkEntities. Find this at the end of the procedure ...

Code:
if (cl_numvisedicts < MAX_VISEDICTS) { cl_visedicts[cl_numvisedicts] = ent; cl_numvisedicts++; }

Add this immediately after:

Code:
#ifdef GLQUAKE if (!ent->transparency) ent->transparency = 1; #endif

This was in JoeQuake 0.14 Build 839. Seems superfluous to me. Looks like it is making sure any value of 0 is set as 1. I'm pretty sure this isn't needed, but just to be safe.

6. cl_parse.c

Quote:
cl_parse.c: Find "void CL_ParseUpdate (int bits)". Find this ...

Code:
if ( bits & U_NOLERP ) ent->forcelink = true;

Add immediately before:

Code:
#ifdef GLQUAKE if (bits & U_TRANS) { int temp; temp = MSG_ReadFloat ();
ent->istransparent = true;
ent->transparency = MSG_ReadFloat ();
}
else
{
ent->istransparent = false;
ent->transparency = 1.0;
}
#endif

This is where the client is reading the data from the server and if the transparency bit is set, it needs to read in the transparency and set the entity attributes accordingly.

7. gl_rsurf.c

Quote:
gl_rsurf.c: Find "void R_DrawBrushModel (entity_t *e)". Find this ...

Code:
if (R_CullBox (mins, maxs)) return; glColor3f (1,1,1);

(7A) Replace with this:

Code:
if (R_CullBox (mins, maxs)) return; if (ISTRANSPARENT(e)) { glEnable (GL_BLEND); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f (1, 1, 1, e->transparency);
} else {
glColor3f (1,1,1);
}

There is where we are drawing the brush models and if there is transparency we need it to render tranparently.
Now we need to turn it off afterwards ...
FIND about 30 lines further down in gl_rsurf.c:

Code:
R_BlendLightmaps (); glPopMatrix ();

(7B) Add after:

Code:
if (ISTRANSPARENT(e)) { glColor3f (1,1,1); glDisable (GL_BLEND); }

8. pr_edict.c

Quote:
pr_edict.c: Find:

Code:
typedef struct { ddef_t *pcache; char field[MAX_FIELD_LEN]; } gefv_cache; static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};

(8A) Add this immediately after:

Code:
// alpha specific int eval_alpha; ddef_t *ED_FindField (char *name); int FindFieldOffset (char *field) {
ddef_t *d;
if (!(d = ED_FindField(field)))
return 0;
return d->ofs*4;
}
void FindEdictFieldOffsets (void)
{
eval_alpha = FindFieldOffset ("alpha");
}

(8B) Now at bottom of PR_LoadProgs find:

Code:
for (i=0 ; i<progs->numglobals ; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);

And replace with:

Code:
for (i=0 ; i<progs->numglobals ; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); FindEdictFieldOffsets ();

Speedy field lookup functions.

9. LAST: sv_main.c

Quote:
sv_main.c : Find "SV_WriteEntitiesToClient" ... you will see:

Code:
int e, i; int bits; byte *pvs; vec3_t org; float miss;
edict_t *ent;

(9A) Add this immediately after:

Code:
#ifdef GLQUAKE eval_t *val; float alpha; #endif

Find:

Code:
if (ent->baseline.modelindex != ent->v.modelindex) bits |= U_MODEL;

(9B) Add this immediately after:

Code:
#ifdef GLQUAKE // nehahra: model alpha if ((val = GETEDICTFIELDVALUE(ent, eval_alpha))) alpha = val->_float; else
alpha = 1;
if (alpha < 1 && alpha > 0)
bits |= U_TRANS;
#endif

Find:

Code:
if (bits & U_ANGLE3) MSG_WriteAngle(msg, ent->v.angles[2]);

(9C) Add this immediately after:

Code:
#ifdef GLQUAKE if (bits & U_TRANS) { MSG_WriteFloat (msg, 2); MSG_WriteFloat (msg, alpha);
}
#endif

The above is where the server sends the data to the client if the tranparency bit is set.

THE END

Back to top |

avirox Joined: 16 Aug 2006 Posts: 109 |

Posted: Fri Nov 21, 2008 8:28 pm Post subject: |

Baker you are a life saver! I've been trying to figure out getting alpha to work on brush models in ezquake. I'll give this a shot tomorrow night, and hopefully if it works the ezq devs will add my alpha .patch to the SVN build along with your brush alpha method. Thanks!

Back to top |

Spike Joined: 05 Nov 2004 Posts: 944 Location: UK |

Posted: Fri Nov 21, 2008 8:29 pm Post subject: |

MSG_WriteFloat (msg, 2); MSG_WriteFloat (msg, alpha); I'm sorry, but... EGADS! the first float is redundant, the second float is 4 times as large as is really useful. looks good other than that though.
_________________
What's a signature?

Back to top |

metlslime Joined: 05 Feb 2008 Posts: 177 |

Posted: Fri Nov 21, 2008 10:31 pm Post subject: |

currently, this tutorial creates an engine that is only good for single-player, and won't even be able to read stock quake demos. might be good to: 1. change the protocol number so other clients will know they can't talk to this modified server, and can't play demos recorded with this modified client.
2. have the modified client check for protocol version and not read the extra bytes if protocol == 15, otherwise you won't be able to read stock protocol 15 demos.
3. get rid of most of the #ifdef GLQUAKE lines, otherwise the win and gl compiles from the same codebase won't even be able to talk to each other. The only thing winquake should do differently from glquake is ignore transparency when rendering. The network code and server-side stuff should be identical between the two builds.

Back to top |

Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Fri Nov 21, 2008 11:11 pm Post subject: |

metlslime wrote:
currently, this tutorial creates an engine that is only good for single-player, and won't even be able to read stock quake demos.

I'm going to write another tutorial replacing this one with the rest of the Nehahra supported added in, so the protocol used in the demos at least matches something that exists.
I'll have to check and find out what protocol number Nehahra uses (I hope it does have its own and isn't using 15).
The above is derived from JoeQuake and it will play regular Quake demos. And write regular Quake demos if the transparency feature isn't being used (id1, etc.), but if a demo were recorded running a mod with the alpha transparency field ...
I'll do some research into what aguirRe's convert demos utility does and see maybe if there is some way to add some sort of universal [ish] demo compatibility.
So I'll see what the existing Nehahra standard is.
Last edited by Baker on Fri Nov 21, 2008 11:40 pm; edited 1 time in total

Back to top |

metlslime Joined: 05 Feb 2008 Posts: 177 |

Posted: Fri Nov 21, 2008 11:39 pm Post subject: |

actually, i realize i was wrong about demos, it won't actually choke on quake demos, since without that U_TRANS flag, it won't try to read extra floats. But i think it is correct that if the modified server claims to use protocol 15, regular clients will crash when they see a transparent entity. And a demo with transparent entities in it will crash a standard client.

Back to top |

Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Fri Nov 21, 2008 11:43 pm Post subject: |

metlslime wrote:
actually, i realize i was wrong about demos, it won't actually choke on quake demos, since without that U_TRANS flag, it won't try to read extra floats. But i think it is correct that if the modified server claims to use protocol 15, regular clients will crash when they see a transparent entity. And a demo with transparent entities in it will crash a standard client.

Ah you replied while I was editing.
This topic needs some more research. Because I can see some very fun protocol breaking extras that would keep running into this issue again, again above and beyond this.
Not to mention whatever you have cooked up for FitzQuake 0.85 (aguirRe's protocol?)

Back to top |

metlslime Joined: 05 Feb 2008 Posts: 177 |

Posted: Sat Nov 22, 2008 12:58 am Post subject: |

Baker wrote:
This topic needs some more research. Because I can see some very fun protocol breaking extras that would keep running into this issue again, again above and beyond this. Not to mention whatever you have cooked up for FitzQuake 0.85 (aguirRe's protocol?)

I think in general, when making a new protocol you should use a new number, and have both client and server be able to handle both 15 and any new number you want to implement. There are several protocol 15s out there now, and most of them do operate on the philosophy that "if you happen to run a map/mod that doesn't use these features, it will devolve into standard protocol 15."
That may be true, but the whole point of a protocol number is to tell the client whether the information is going to be comprehensible. But with these protocols, you get a "maybe it'll work, maybe you'll crash halfway through."
As for fitzquake's protocol, my plan has been to basically pack as much as i reasonably can into one new protocol, rather than slowly adding a feature at a time and then having 10 different versions to support. There will still probably be a need for another version someday, but I'd rather have a few major version than many minor versions floating around.

Back to top |

goldenboy Joined: 05 Sep 2008 Posts: 310 Location: Kiel |

Posted: Fri Nov 28, 2008 7:38 pm Post subject: |

The only thing winquake should do differently from glquake is ignore transparency when rendering. The network code and server-side stuff should be identical between the two builds. Exactly. I think "Winquake" should simply not render transparent brush entities - so you can still look through windows. All other transparent entities should just be solid in software.
Sure, you'll alert monsters etc - but that's the mapper's problem. Monsters behind an .alpha func_wall really should be alerted, too.

Back to top |

leileilol Joined: 15 Oct 2004 Posts: 1321 |

Posted: Fri Nov 28, 2008 7:50 pm Post subject: |

Then add alpha transparency to stock winquake too to make it fair - just rip the code from Quake2!

Back to top |

Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Sat Nov 29, 2008 12:23 pm Post subject: |

leileilol wrote:
Then add alpha transparency to stock winquake too to make it fair - just rip the code from Quake2!

Looks like that might take a little bit of work

Quake 2 source wrote:
pixel_t *alphamap; // 256 * 256 translucency map

It is my understanding that the winquake window is initialized in a 256 color palette mode. It looks like the q2 method uses 256^2 colors.
Options:
1. Increase the # of colors available in WinQuake to 2^16 or 2^24 so the alpha effect is possible (might reduce speed, then again Quake 2 doesn't seem slow in software rendering mode .. but I don't have a slow 400 Mhz machine to be able to know).
2. Render transparent brushes in WinQuake as a "screen" where 25% of the pixels [or some other ratio] are fully transparent (Half-Life appears to do this.] using a predefined mask.
3. Some sort of improvised 256 color method that fakes an alpha table with the palette.

Back to top |

leileilol Joined: 15 Oct 2004 Posts: 1321 |

Posted: Sat Nov 29, 2008 12:59 pm Post subject: |

*facepalm* You completely misunderstood the code. Quake2 uses 256 colors. What that comment means a lookup table at the size of 256x256 pixels big.

Back to top |

Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Sat Nov 29, 2008 3:08 pm Post subject: |

leileilol wrote:
*facepalm* You completely misunderstood the code. Quake2 uses 256 colors. What that comment means a lookup table at the size of 256x256 pixels big.

Color mixing table: color (0-255) with alpha (0-255) = result color2 (0-255)? If so, wouldn't this table be sort of a pain to figure out for Quake 1.
Either way, that leads to a simple idea on how to quickly make a translucent looking glass in software not as fancy as Quake 2.
Create a function to return the palette position a couple of columns shifted based on the alpha. It could look wrong with colors in the fullbright rows, but a minor side downside on a small minority of colors.
Or at least in theory it might look ok.
Unless someone has an idea on how the Quake 2 method (that I still may or may not completely understand) could be employed.

Back to top |

r00k Joined: 13 Nov 2004 Posts: 483 |

Posted: Sat Nov 29, 2008 7:06 pm Post subject: |

Spike wrote:
MSG_WriteFloat (msg, 2); MSG_WriteFloat (msg, alpha); I'm sorry, but... EGADS! the first float is redundant, the second float is 4 times as large as is really useful. looks good other than that though.

the 1st float of 2 it to set FULLBRIGHT entities in Nehahra,

Code:
if (bits & U_TRANS) { int fullbright, temp; temp = MSG_ReadFloat (); ent->transparency = MSG_ReadFloat ();
if (temp == 2)
fullbright = MSG_ReadFloat ();
}

which seems odd cause temp is always going to be 2

Code:
if (bits & U_TRANS) { MSG_WriteFloat (msg, 2); MSG_WriteFloat (msg, alpha); MSG_WriteFloat (msg, fullbright);
}

Back to top |

goldenboy Joined: 05 Sep 2008 Posts: 310 Location: Kiel |

Posted: Sat Nov 29, 2008 11:33 pm Post subject: |

I can run Quake 2 on a Pentium 1, and software transparency on those windows seems no problem at all in 512x384 or 400x300. It's fluid. Same FPS as Quake on that machine. Well maybe 10% less or something. But it runs OK. I think I remember transparent water in software in FTE - dunno if it also does alpha entities. I should test. :-E

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> Programming Tutorials | All times are GMT Goto page 1, 2 Next
Page 1 of 2

Jump to:

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2004 phpBB Group