Page 1 of 1
Transparency on Moving Entities (Quake2)
Posted: Wed Jun 12, 2013 10:38 pm
by jitspoe
Surely somebody has already fixed this and can save me the effort... If you use a transparent brush on something like a door, the transparent polygons stay in place while the door moves. Anybody know of some code or an engine that fixes this?
Re: Transparency on Moving Entities (Quake2)
Posted: Thu Jun 13, 2013 12:14 am
by Spike
transparent polys are added to some separate list when drawn. just the polygons, so they loose all context regarding their owning entity. which means they don't have the right matrix and can't move/rotate.
fte builds batch lists, ordered by blend mode and grouped by texture+entity. each batch retains the context of the render-entity thus any origin/angles/alpha/colormod/light directions/etc all carry through to the polys that need them.
the code is quite different from vanilla q2 though, so I don't know how useful knowing that is to you.
either build a per-entity list instead of a single global list for transparent surfaces, or just store a pointer to the owning entity with each surface and update the modelview matrix if that rentity pointer changes from one surface to the next.
Re: Transparency on Moving Entities (Quake2)
Posted: Thu Jun 13, 2013 8:08 am
by Barnes
try this
Code: Select all
void R_DrawAlphaPoly(void)
{
msurface_t *s;
//
// go back to the world matrix
//
qglLoadMatrixf(r_world_matrix);
qglDepthMask(0);
for (s = r_alpha_surfaces; s; s = s->texturechain) {
if (s->ent)
R_RotateForLightEntity(s->ent);
if (s->texinfo->flags & SURF_TRANS33)
shadelight_surface[3] = 0.33;
else
if (s->texinfo->flags & SURF_TRANS66)
shadelight_surface[3] = 0.66;
else
shadelight_surface[3] = 1.0;
if (s->flags & SURF_DRAWTURB)
R_DrawWaterPolygons(s);
else if (s->texinfo->flags & SURF_FLOWING)
DrawGLFlowingPolyGLSL(s);
else
DrawGLPolyGLSL(s);
}
qglColor4f(1, 1, 1, 1);
qglDepthMask(1);
r_alpha_surfaces = NULL;
}
Re: Transparency on Moving Entities (Quake2)
Posted: Thu Jun 13, 2013 5:50 pm
by jitspoe
Barnes wrote:try this
I guess that would require adding an ent pointer to all the surfaces... not sure how much memory overhead that would have, but it may be the easiest solution.
Re: Transparency on Moving Entities (Quake2)
Posted: Sat Jun 15, 2013 6:55 am
by Knightmare
This is one of the oldest Q2 rendering bugs that has a fix available. I think it was Quake2Max that first addressed it back in 2002. Hard to believe that R1GL still doesn't have this fixed.
Be sure to load the world matrix before caling R_RotateForEntity() for each surface, and again after the last one, or it will end up moving the first-person weapon model, too.
These bmodel alpha surfs aren't depth-sorted from traversing the BSP tree, so they will occlude others behind them (due to being stuffed at the front of the alpha chain). Various attempts to depth sort them failed, so I ended up just disabling the depth mask when rendering them.
You can also use this surface ent pointer to enable animated textures on both bmodel and world alpha surfaces (see my unofficial v3.24 patch source). The added pointer is only 4 bytes per surface, and the memory use increase is negligible compared to v3.20.
Re: Transparency on Moving Entities (Quake2)
Posted: Thu Jun 27, 2013 11:08 pm
by Knightmare
Here's an except of the changes I made for moving and animating trans faces in Q2's ref_gl.
I tried to make similar changes to ref_soft recently, but the results were disastrous. It's very very difficult to change any functionality in that code.
Definition of msurface_s in gl_model.h:
Code: Select all
typedef struct msurface_s
{
.
.
.
entity_t *entity; // Knightmare- added entity pointer
} msurface_t;
Top of gl_rsurf.c:
Code: Select all
int r_worldframe; // Knightmare- added for trans animations
Modified R_TextureAnimation (takes surface as parameter instead of texinfo):
Code: Select all
image_t *R_TextureAnimation (msurface_t *surf)
{
int c, frame;
mtexinfo_t *tex = surf->texinfo;
if (!tex->next)
return tex->image;
if (tex->flags & (SURF_TRANS33|SURF_TRANS66)) {
if (!surf->entity)
frame = r_worldframe; // use worldspawn frame
else
frame = surf->entity->frame;
}
else
frame = currententity->frame;
c = frame % tex->numframes;
while (c)
{
tex = tex->next;
c--;
}
return tex->image;
}
R_DrawInlineBmodel:
Code: Select all
.
.
.
qboolean duplicate; // Knightmare added
.
.
.
for (i=0 ; i<currentmodel->nummodelsurfaces ; i++, psurf++)
{
.
.
.
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
psurf->entity = NULL; // make sure this is NULL
if ( psurf->texinfo->flags & SURF_SKY )
continue;
if ( psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) )
{
// add to the translucent chain
// if bmodel is used by multiple entities, adding surface
// to linked list more than once would result in an infinite loop
duplicate = false;
for (s = r_alpha_surfaces; s; s = s->texturechain)
if (s == psurf)
{
duplicate = true;
break;
}
if (!duplicate) // Don't allow surface to be added twice (fixes hang)
{
psurf->texturechain = r_alpha_surfaces;
r_alpha_surfaces = psurf;
psurf->entity = e; // entity pointer to support movement
}
}
.
.
.
R_RecursiveWorldNode or other function that adds world surfaces to chains (calling GL_RenderLightmappedPoly directly from R_RecursiveWorldNode is very bad for performance, it causes a pipeline stall when recursing after drawing each face):
Code: Select all
void R_AddWorldSurface (msurface_t *surf)
{
.
.
.
surf->entity = NULL; // make sure this is NULL
.
.
.
Addition to start of R_DrawWorld:
Code: Select all
.
.
.
// auto cycle the world frame for texture animation
memset (&ent, 0, sizeof(ent));
// Knightmare- added r_worldframe for trans animations
ent.frame = r_worldframe = (int)(r_newrefdef.time*2);
currententity = &ent;
.
.
.
Additions to R_DrawAlphaSurfaces:
Code: Select all
.
.
.
image_t *image; // Knightmare added
.
.
.
for (s = r_alpha_surfaces; s; s = s->texturechain)
{
// go back to the world matrix
qglLoadMatrixf (r_world_matrix);
// disable depth testing for all bmodel surfs (which are not BSP-sorted)
if (s->entity)
GL_DepthMask (false);
else
GL_DepthMask (true);
// moving trans brushes
if (s->entity)
R_RotateForEntity (s->entity, true);
// Knightmare- use animated texture
// GL_Bind(s->texinfo->image->texnum);
image = R_TextureAnimation (s);
GL_Bind(image->texnum);
// Draw surface here
.
.
.
}
.
.
.
// go back to the world matrix after shifting trans faces
qglLoadMatrixf (r_world_matrix);
// re-enable depth masking
qglDepthMask (true);
.
.
.
}