Forum

Page 3 of 3

Re: Software Edge Clipping With GL?

PostPosted: Mon Oct 27, 2014 11:37 pm
by Baker
mankrip wrote:but I don't fully understand that part of the code yet.
Hehe, well you understand the software renderer code far more than myself. Hence, I asked you. :D

Re: Software Edge Clipping With GL?

PostPosted: Tue Oct 28, 2014 1:18 am
by mankrip
Ok, I'm with my two laptops here now.

In R_DrawBEntity, near the end, BSP models that aren't in a single leaf are sent to R_DrawSolidClippedSubmodelPolygons, to be clipped against the world.

In R_DrawSolidClippedSubmodelPolygons, the medge_t data from the model is copied to a bedge_t struct, and then the bedge_t data is passed to R_RecursiveClipBPoly along with the model's surfaces and nodes.

R_RecursiveClipBPoly clips the edges from the medge_t data, and apparently it stores the resulting edges into the local psideedges array. Since this function is recursive, it means that every time it's called, a new copy of psideedges is allocated, so the code can allocate exactly the required amount of RAM for the clipped edges, without ever knowing how many edges will be generated. This is why I couldn't find any data set for clipped edges before. After each finalized polygon is generated, it's sent to R_RenderBmodelFace.

R_RenderBmodelFace calls R_ClipEdge to clip the edges of the polygon against the screen, and stores the resulting data in the surf_t *surfaces list through the surface_p pointer. The surfaces list is allocated in R_NewMap through the line surfaces = Hunk_AllocName (r_cnumsurfs * sizeof (surf_t), "surfaces");

Why such a generic name was used for a global variable so important? I've had to search for surfaces[, *surfaces and surfaces = to be able to track the parts of the code that uses it.

Anyway, R_RenderBmodelFace doesn't do anything afterwards. The surfaces data is rendered through D_DrawSurfaces, which is called by R_ScanEdges, which is called by R_EdgeDrawing after all R_DrawSolidClippedSubmodelPolygons calls have been issued by R_DrawBEntitiesOnList, which R_EdgeDrawing had also called before.

Holy crap.

Re: Software Edge Clipping With GL?

PostPosted: Tue Oct 28, 2014 3:43 am
by Baker
Thanks for the explanation as it can be very difficult at times to make heads or tails of the code at times (due to the cryptic names, the local variables vs. the large number of globals).

Sometimes even finding something is a maze in WinQuake.

Re: Software Edge Clipping With GL?

PostPosted: Sat Nov 01, 2014 11:41 am
by mankrip
Took another look to figure out the Z-sorting of spans, and nothing yet. They seem to be sorted by R_EmitEdge, but a quick test didn't work.

Re: Software Edge Clipping With GL?

PostPosted: Sun Nov 02, 2014 5:09 am
by Baker
I noticed the qsort on the entities in your source. Of course not the same as the spans.

/Darn software renderer cryptically cloaking what it is doing

Re: Software Edge Clipping With GL?

PostPosted: Mon Nov 03, 2014 12:05 am
by mankrip
Yeah, that's for translucent entities. But "fence" textures requires a per-surface solution, and disabling the Z-sorting would be the ideal one for this.

Eventually, I also want to modularize the whole renderer, to make it more flexible and less confusing.

Re: Software Edge Clipping With GL?

PostPosted: Fri Nov 07, 2014 12:53 am
by qbism
I'm looking back through the Q2 software renderer (KM's 3.24 engine). Q2 elegantly chains together alpha surfaces in R_RenderFace and R_RenderBmodelFace into one list

Code: Select all
void R_RenderFace (msurface_t *fa, int clipflags)
{
   int         i, lindex;
   unsigned   mask;
   mplane_t   *pplane;
   float      distinv;
   vec3_t      p_normal;
   medge_t      *pedges, tedge;
   clipplane_t   *pclip;

   // translucent surfaces are not drawn by the edge renderer
   if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
   {
      fa->nextalphasurface = r_alpha_surfaces;
      r_alpha_surfaces = fa;
      return;
   }
...


Code: Select all
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
{
   int         i;
   unsigned   mask;
   mplane_t   *pplane;
   float      distinv;
   vec3_t      p_normal;
   medge_t      tedge;
   clipplane_t   *pclip;

   if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
   {
      psurf->nextalphasurface = r_alpha_surfaces;
      r_alpha_surfaces = psurf;
      return;
   }
...


Then it draws them last with R_DrawAlphaSurfaces in R_RenderView. There's no special sorting step. Unwinding the chain draws back to front in correct order. It seems that it would even work if fence textures were in the chain.
Code: Select all
...
R_DrawWorld ();

   R_DrawEntitiesOnList ();

   R_RenderDlights ();

   R_DrawParticles ();

   R_DrawAlphaSurfaces ();

   R_Flash();
...

Re: Software Edge Clipping With GL?

PostPosted: Fri Nov 07, 2014 2:11 pm
by mankrip
It looks like the whole r_ poly.c file from Quake 2 is needed. I'll try to port it.

And I've found a perfect example of how bad the Z-fighting of BSP entities can be. Open the start map of the Contract Revoked mod, and look at the floor of the Normal difficulty room. Both the lava and the bricks on the floor are BSP entities, and there's lots of Z-fighting between them - even though their planes are perpendicular to each other, which surprised me. This happens in all software-rendered Quake engines.

Re: Software Edge Clipping With GL?

PostPosted: Sun Feb 01, 2015 4:38 pm
by mankrip
Here's a screenshot:
Image

Re: Software Edge Clipping With GL?

PostPosted: Sun Feb 01, 2015 11:08 pm
by qbism
I've seen a sawtooth effect similar to that but not as bad as that screenshot.

Re: Software Edge Clipping With GL?

PostPosted: Wed Oct 04, 2017 7:44 pm
by ericw
I was thinking about this again... QuakeSpasm's solution of including hacked .ent files for id1 maps is not the greatest.

First train of thought was,
-add the face plane (float3 normal, float dist) for each vertex to the VBO for BSP models.
-maybe render the world into a float4 FBO color buffer, writing the float4 plane for each fragment.
-read from this texture later and use it as sort of a "extact" depth buffer when drawing the bmodels.

Then I saw this on the GL wiki:
On some SGI OpenGL platforms, an application can use the SGIX_reference_plane extension. With this extension, the user specifies a plane equation in object coordinates corresponding to a set of coplanar primitives. You can enable or disable the plane. When the plane is enabled, all fragment Z values will derive from the specified plane equation. Thus, for any given fragment XY location, the depth value is guaranteed to be identical regardless of which primitive rendered it.

https://www.khronos.org/opengl/wiki/Dra ... gon_Offset

SGIX_reference_plane is a 1996 thing, but it should be easy to implement in GLSL, I think? Just calculate gl_FragDepth using only 1) the plane normal+dist, which you'd add as vertex attributes, 2) gl_FragCoord. This would ensure that a door bmodel that's coplanar with a world face would both generate exactly the same depth values, so they wouldn't Z-fight. You'd also need to pass in the bmodel's offset from the origin, and offset the planes stored in the vertex attributes by that much.

Re: Software Edge Clipping With GL?

PostPosted: Wed Oct 04, 2017 9:27 pm
by Baker
ericw wrote:I was thinking about this again... QuakeSpasm's solution of including hacked .ent files for id1 maps is not the greatest.

Easily beats the choice of either having people complain about E1M1 quad area or having evil gl_ztrick 1 enabled by default.

E1M1 is the main source of complaints.

... since most custom single player don't have z-fighting in their maps.

Not ideal, but keeps an engine author from getting the "z-fighting", "z-fighting", "z-fighting" topic coming up again and again and again, since the external .ents make it relatively scarce for an average user.

Re: Software Edge Clipping With GL?

PostPosted: Wed Oct 04, 2017 9:48 pm
by ericw
Yeah - I mean the .ent's aren't the worst, but if this "emulate SGIX_reference_plane with GLSL" idea actually works, it seems like it would be better, and wouldn't have the issues of adding cracks around secret doors that gl_ztrick does.

If it works, what I was thinking was:
- new "gl_zfightingfix" cvar deafults to "auto" which means "enabled on whitelisted original game levels only". You could manually set it to "1" when playing late 90s maps with z-fighting, to get software-renderer-like behaviour, but otherwise it would default to being off.

Last time I played the original levels I noticed several spots where the QS .ent's missed correcting z-fighting, and it is kind of distracting / takes you out of the game.

Re: Software Edge Clipping With GL?

PostPosted: Mon Oct 09, 2017 9:24 am
by mh
There's a method using the stencil buffer described here: ftp://ftp.sgi.com/opengl/contrib/blythe ... ode20.html

Not certain how robust it is for this particular use case though.