Skip to content

Allow more element types as engineApplyShaderToWorldTexture targets - #5328

Open
Flashmyname wants to merge 4 commits into
multitheftauto:masterfrom
Flashmyname:fix/1111-shader-target-element
Open

Allow more element types as engineApplyShaderToWorldTexture targets#5328
Flashmyname wants to merge 4 commits into
multitheftauto:masterfrom
Flashmyname:fix/1111-shader-target-element

Conversation

@Flashmyname

@Flashmyname Flashmyname commented Sep 5, 2026

Copy link
Copy Markdown

Summary

engineApplyShaderToWorldTexture accepts any element as targetElement, but only vehicles, objects, peds and buildings could ever match, because the render hook resolves the drawn entity through CPools::GetClientEntity. For everything else the call returned true and did nothing. This PR adds the element types MTA draws itself, one commit per type:

image
  • Pickups and projectiles. Their game objects are never registered in the object pool, so they are resolved in the entity render handler when the pool lookup misses.
  • Searchlights. Not game entities, so the cone draw in CClientSearchLight::Render is tagged with the element. The cone binds no texture and used to fall into the generic unnamed bucket with every other untextured draw, so it gets a name of its own, searchlight. The ground spot shares the texture the game uses for street lamp light pools, so a copy is registered as shad_searchlight.
  • Blips. Both CRadar::DrawCoordBlip call sites are hooked and the draw is tagged through a game marker to element map.
  • Markers, meaning cylinders, arrows, rings, the checkpoint tube and coronas. Both game objects carry the identifier MTA gave them, which resolves back to the element. The same corona hook, with one on CHeli::RenderAllHeliSearchLights, also covers the searchlight of a game helicopter, resolved to its vehicle.
image

Element types the render hooks cannot tell apart, colshapes and sounds for example, now return false with a script warning instead of silently succeeding.

Motivation

Fixes #1111. A shader can currently only be limited to a vehicle, object, ped or building. Tinting one pickup, one blip or one marker without touching every other element sharing the texture is not possible, and nothing tells the script that the call did nothing.

Behaviour worth noting: searchlight cones used to be reachable through the unnamed texture name, which matched every other untextured draw as well. They are now searchlight, and engineGetVisibleTextureNames reports it. * keeps working.

Test plan

Test resource attached, it spawns two of every element type in front of the player and tints the left one of each pair:

shadertargettest.zip

  1. The tinted element changes colour, the one next to it sharing the same texture does not.
  2. engineRemoveShaderFromWorldTexture restores it.
  3. Tinting both of a pair in different colours keeps them apart.
  4. An unsupported target such as a colshape returns false and logs a warning.
  5. Several lit police Mavericks at once, each with its own shader targeted at that vehicle, keep their own cone colour, and one left without a shader stays plain.
  6. 300 to 500 cycles per type of create, target, change, stream out and in, destroy, with no crash and no leftover entries in the identifier maps.
image

The ground spot of a searchlight cannot be targeted per element. It is stored as a shadow and drawn later in one batch, when the owner is no longer known, so a shader on shad_searchlight tints every spot at once. That is what the separate texture name is for.

Checklist

  • Your code should follow the coding guidelines.
  • Smaller pull requests are easier to review. If your pull request is beefy, your pull request should be reviewable commit-by-commit.

The objects behind pickups and projectiles are never registered in the object
pool, so the render hook could not resolve them and a shader targeted at one
matched nothing while the call still returned true. Resolve them in the entity
render handler when the pool lookup misses. CPools::GetClientEntity is left
alone, its other callers rely on getting NULL for these objects.

Element types the render hooks cannot tell apart now fail with a script warning
instead of silently returning true.

Part of multitheftauto#1111.
Searchlights are not game entities, so the entity render hook never saw them.
The cone is drawn by MTA itself, so tag that draw with the element around the
RenderHeliLight call.

The cone binds no texture and fell into the generic unnamed bucket together with
every other untextured draw, so it gets a name of its own, "searchlight". The
ground spot is stored with the texture the game also uses for the light pools of
street lamps, so a copy of it is registered as "shad_searchlight" and a shader on
the spots leaves the lamps alone.

Part of multitheftauto#1111.
Radar blips are drawn one sprite at a time by CRadar::DrawCoordBlip with no game
entity behind them. Hook both call sites, the regular pass and the one for the
waypoint icon, and tag the draw through a game marker to element map kept by
CClientRadarMarkerManager.

Not covered: icons 0 and 1, which are drawn without a texture, blips the game
creates itself, and the F11 map, which has its own textures.

Part of multitheftauto#1111.
Markers have no game entity behind them either. Cylinders, arrows, rings and the
checkpoint tube are C3dMarker objects, corona markers are registered coronas, and
both carry the identifier MTA gave them, so hook the per-marker draw in the two
render loops and resolve that identifier back to the element.

The same corona hook, together with one on CHeli::RenderAllHeliSearchLights,
covers the searchlight of a game helicopter, which is registered with the vehicle
pointer plus 0xB as its id.

Part of multitheftauto#1111.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More target elements for engineApplyShaderToWorldTexture

1 participant