Forum

Transparency on Moving Entities (Quake2)

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Transparency on Moving Entities (Quake2)

Postby jitspoe » Wed Jun 12, 2013 10:38 pm

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?
jitspoe
 
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Transparency on Moving Entities (Quake2)

Postby Spike » Thu Jun 13, 2013 12:14 am

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.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: Transparency on Moving Entities (Quake2)

Postby Barnes » Thu Jun 13, 2013 8:08 am

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;
}
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Re: Transparency on Moving Entities (Quake2)

Postby jitspoe » Thu Jun 13, 2013 5:50 pm

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.
jitspoe
 
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Transparency on Moving Entities (Quake2)

Postby Knightmare » Sat Jun 15, 2013 6:55 am

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.
Knightmare
 
Posts: 63
Joined: Thu Feb 09, 2012 1:55 am

Re: Transparency on Moving Entities (Quake2)

Postby Knightmare » Thu Jun 27, 2013 11:08 pm

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);
   .
   .
   .
}
Knightmare
 
Posts: 63
Joined: Thu Feb 09, 2012 1:55 am


Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest