change brush model surface flags based on entity

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
qbism
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am
Contact:

change brush model surface flags based on entity

Post by qbism »

Let's say we've got entity->foo. The entity has a brush model. I'd like create a new surface flag, so that " if entity->foo then all surfaces->flag = SURF_FOO". Where in the code can I dig into that with brush models?

What I'm really talking about is entity->alpha. I can't find the spot where a func_wall could access surface flags. I'd like to do it as soon as brush models and/or entities are loaded.

BTW, I've looked briefly at how Makaqu 1.5 does it. I think this is different, it assigns a blend function per entity. But I don't really have a grasp of that, either.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: change brush model surface flags based on entity

Post by mh »

You'd need to do this at protocol level (although Spike will no doubt suggest CSQC ;) )
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: change brush model surface flags based on entity

Post by Spike »

I would be hesitant to change model data to follow a *specific* entity that uses that model.

and no, csqc cannot edit actual models. it can spew forth its own polygons, it can generate sketal poses, but cannot hack random fields of random model formats.
it can override blend modes. but then so can ssqc via the .effects field (DP added an EF_ADDITIVE).

If you're talking software rendering, the surface flags are tested in D_DrawSurfaces. Its best to just check s->entity->somecustomfield there instead of some hacked-on flag.

If you really really want to edit the model flags based upon some entity using that model without protocol changes, you'll have to parse the entities lump clientside and match the entity to the model via the entity's model string, then loop through that model's surfaces (for (i = submodel->firstsurface; i < submodel->firstsurface + submodel->surfacecount; i++)submodel->surfaces.flags |= SURF_FOO; to constrain the flag to the submodel rather than affecting world too).

But yeah, you're best off with a protocol change. Including for static entities.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Re: change brush model surface flags based on entity

Post by mh »

It would be a little bit more complex as each surface would need to remember the last flag it was set to and remove that too.

One nasty way that springs to mind would be to add a SetSurfaceFlags command that takes an entity name (or number) and a flag as params, then stuffcmd it. Of course that won't persist across multiple sessions so you need a way of saving it out and restoring it. Adding a new entity field and setting that through QC, then adding a new protocol message and sending it through SV_WriteEntitiesToClient seems cleanest.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
qbism
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am
Contact:

Re: change brush model surface flags based on entity

Post by qbism »

Thanks, I see how the protocol change works. Alias models check currententity->foo in D_RasterizeAliasPolySmooth, and choose a different span function (D_PolysetDrawSpans_fooA, D_PolysetDrawSpans_fooB) depending on the value of foo. That's how Makaqu 1.3 handles alpha. So currently I'm looking for a similar way to do it for brush models. These go down a different set of functions for rendering.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: change brush model surface flags based on entity

Post by Spike »

d_edge.c D_DrawSurfaces is where the other flags are checked, looks like s->entity is valid in there.
You'll likely need to take care with the existing flags, or only add it just before the else case.

note that d_drawspans is merely a pointer to either D_DrawSpans16 or 8, depending on how accurate you want perspective correction on textures. You can likely get away with hardcoding it to just D_DrawSpans8.
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Re: change brush model surface flags based on entity

Post by mankrip »

qbism wrote:That's how Makaqu 1.3 handles alpha. So currently I'm looking for a similar way to do it for brush models.
There's no way to code it that easy for brush models. Makaqu 1.5 does it in the simplest way I could devise while still retaining compatibility with most possible cases.

First, opaque BSP surfaces doesn't use the Z buffer for clipping. The only way to be able to do that is by semi-reinitializing the BSP renderering of the current frame, which is what Makaqu 1.3 does for liquid surfaces.

However, once you've semi-reinitialized it, all surfaces you draw afterwards will be clipped against each other, just like before. This is why Makaqu 1.3 doesn't display multiple layers of translucent liquids.

Reinitializing the BSP renderer for each surface would most likely be too slow, so that's why I've done it per-entity in Makaqu 1.5.
The only exception are the world's liquids, which have their BSP rendering semi-reinitialized once for each kind of liquid. This doesn't allow multiple layers of the same kind of liquid to be seen over each other (e.g. the water pool to the fourth episode in the start map), but it does allow e.g. translucent portals to be seen through translucent water, which is much more relevant to the gameplay.

In Makaqu 1.5, liquid surfaces that doesn't belong to the world don't follow this. They follow the blending settings of their currententity. This way, a map can have multiple pools of a same liquid with different levels and/or modes of translucency (e.g. opaque lava in a deep river, and additive lava in a small pool).
Checking the alpha level for things like this on each surface would be hell. There would be too many very specific cases to check, in several different parts of the renderer, and doing so many checks on every frame would be slow. This is why Makaqu 1.5 checks everything way before the rendering, when the server message is received by the client. This way, all checks are done only once, all in the same place, and only when receiving an update from the server. From there, nothing else needs to be checked, the renderer just uses the functions and parameters that have been set.

This is really the simplest solution I've figured out. Anything else would have been more complicated, less flexible and too prone to problems.

There are some more advanced per-surface manipulations that I've still not implemented, and I'd need that to get opaque "fence textures" working. Such textures really need the BSP rendering to be reinitialized once for every surface using them, and such surfaces would have to be rendered separately from the rest of their models, to avoid unnecessary overdraw. Also, those "fence textures" may not have transparent pixels in all their mipmap levels, so this is one more thing that could be checked to avoid unnecessary overdraw.
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
qbism
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am
Contact:

Re: change brush model surface flags based on entity

Post by qbism »

mankrip wrote:First, opaque BSP surfaces doesn't use the Z buffer for clipping. The only way to be able to do that is by semi-reinitializing the BSP renderering of the current frame, which is what Makaqu 1.3 does for liquid surfaces.

However, once you've semi-reinitialized it, all surfaces you draw afterwards will be clipped against each other, just like before. This is why Makaqu 1.3 doesn't display multiple layers of translucent liquids.

Reinitializing the BSP renderer for each surface would most likely be too slow, so that's why I've done it per-entity in Makaqu 1.5.
I was getting to the point of semi-reinitializing, after various per-surface or per-entity schemes, and hitting the wall of clipping as described. The explanation helps me understand the sorting and separate drawing pass for blended entities in 1.5. There's no easy shortcuts for this one! The result on-screen is fast and accurate transparency, so there's no motivation to sweat the strategy from a performance standpoint.
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Re: change brush model surface flags based on entity

Post by mankrip »

By the way...
mankrip wrote:Makaqu 1.5 checks everything way before the rendering, when the server message is received by the client. This way, all checks are done only once, all in the same place, and only when receiving an update from the server.
There are some exceptions to this. Most notably, for the viewmodel and for the world's liquids. The viewmodel copies some parameters from its player's external entity, and it may also use different blending settings according to the current power-ups (e.g. having the ring of shadows + quad damage results in additive blending instead of weighted mean). And iirc, the drawing functions and parameters of the world's liquids are set either by a callback function in their corresponding cvars, or by a worldspawn flag when they're set to follow r_wateralpha. The chase camera also changes the blending functions and parameters of the player's external model when it's too close to him.
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
Post Reply