Transparency on Moving Entities (Quake2)
Transparency on Moving Entities (Quake2)
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)
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.
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)
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)
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.Barnes wrote:try this
-
- Posts: 63
- Joined: Thu Feb 09, 2012 1:55 am
Re: Transparency on Moving Entities (Quake2)
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.
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.
-
- Posts: 63
- Joined: Thu Feb 09, 2012 1:55 am
Re: Transparency on Moving Entities (Quake2)
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:
Top of gl_rsurf.c:
Modified R_TextureAnimation (takes surface as parameter instead of texinfo):
R_DrawInlineBmodel:
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):
Addition to start of R_DrawWorld:
Additions to R_DrawAlphaSurfaces:
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;
Code: Select all
int r_worldframe; // Knightmare- added for trans animations
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;
}
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
}
}
.
.
.
Code: Select all
void R_AddWorldSurface (msurface_t *surf)
{
.
.
.
surf->entity = NULL; // make sure this is NULL
.
.
.
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;
.
.
.
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);
.
.
.
}