Possible to modify texture at runtime?

I was wondering if it is possible to modify texture at runtime. Say if a model gets hit by a shot the model itself or (probably easier) the ground could get splashes of red (blood…).

Seems one solution could be to use a projected texture. However I wonder if this is the best way to do it if you have alot of texture changes…

Any ideas greatly appreciated. Thanks.

Sure. See Creating New Textures from Scratch in the manual, which in addition to creating new textures from scratch, also shows how to modify an existing texture.

David

That sounds exciting!

There are a lot of ways to modify a texture at runtime. I haven’t done more than a couple of these, so I can’t tell you much about the runtime efficiency. But perhaps some of these might work for you.

First off, it’s important to note that there are two things you can modify. One would be the bytes making up the texture’s image in memory itself. You can modify these by getting a reference to the texture (which should be as simple as loader.loadTexture(“textureName”)… Panda caches all textures loaded, so you should get a reference to the same texture that is on your model). Then use the PNMImage class to pull the texture into working memory, modify it, and dump your modifications back into the texture. There are probably more steps than that, but that’s the rough-sketch.

However, this may not be the best course of action. You’ll be modifying the source texture using this method; if you have more than one model using this texture, they’d all pick up the change—not what you want. A better approach would probably be to grab the NodePath of the model section you wish to modify the texture on and replace the texture at that location with something new. If the thing you’re trying to modify is an Actor, you’ll need to use egg-optchar to name the sections of the model that can have their textures modified (see this forum post for more information on that process). The idea is then to grab a NodePath reference to that model part (using NodePath.find) and replace the texture applied to that section with a new texture.

The simplest approach would be to have two texture sets: one for your model in pristine condition, the other for the “messed up” version of your model. Then when your model’s appearance needs to change, you can grab the section that needs to be changed and use section.setTexture(messedUpTexture,3) to override the regular texture with the new one (the 3 guarantees that the messed up texture will be at higher priority, so will clobber any attempts by children of that node to set the texture back to the regular texture).

But to really drive the effect home, you probably want to use texture stages to layer a blood splat (or other texture) on top of the already-existing texture. Unfortunately, I know so little about texture stages that I can’t even pretend to advise you on that approach. Perhaps someone else help?

Best of luck!
-Mark

for things like blood on the ground or walls it’s best to use small flat models which are glued to the walls or the gorund.
its less problematic than modifying a texture which is used all over the level.

if you have a certain character and you want to add such stuff you could just paint sevral player-textures which you can replace completly.
of course you could use several texture layers… but it’s rather complicated to get the result you want=)

That’s fine for little splatters, but what about something that has to follow the curve of the ground, like shadows? How would you do that?

Yes, I disagree that it would be “best” not to modify the texture.

  • for something like the ground there is only one texture so no problems with reuse.

  • having several textures ready made is very rigid. You cant dynamically decide where the blood should be placed for example (depending on where the bullet hits…)

  • For a lot of modifications I think it will be more runtime-efficient to modify the texture rather than creating new objects.

modifying a texture at runtime isn’t really faster than adding a object.
if it’s for bullet-hits on walls or on the floor it’s really simplest to create new planes and stick them to the wall/floor/wherever. most games used techniques immilar to this, of course you could modify a texture or add more texture stages but keep in mind that most cards only support 4 textures per geomobject (i think it was a geom…) modern cards support up to 16 stages. if you dont draw all splashes,bulletholes or whatever into 1 texture stage you’ll be very limited(to 3 bulletholes :stuck_out_tongue: ).
rendering all effects into one texture stage would require offscreen buffers for each manipulated texture, render them again each time a new bullet hits the wall and so on and so on… no to speak of quite some memory usage.

the prebuild “gore-textures” i mentioned earlyer are just for the player models or simmilar.

you might want to have a close look at the game (or UTmod) called Rune.

greetings
thomas e

Yeah, that is kind of what I have seen in games; there seems to be a limited number of eg. bullet holes available to spread over the terrain. Thus bullet holes disappear after a while… This is why I thought of simply modifying the texture. I would imagine - given that the ground texture is used only once - that this would allow for “infinitely” many bullet holes as it is just a new texture that is to be held in memory - not an addition to the texture.

Is this mistaken? I dont know what a stage is… :frowning: (kindly explain if it is not too complex :slight_smile:) When you talk about mem usage problems - is that with the technique of modifying/redrawing the existing texture or when adding new stuff like planes onto the texture? I could imagine putting “planes” to represent blood on the floor would take up lots of mem if there is lots of blood…

I am assuming there would be one big texture for the terrain/floor. But even if the floor is tiled it should still be possible to modify the texture by copying the existing and using this for the particular tile that was splashed. Even if a separate texture is loaded for each tile of floor this shouldnt take up too much memory - especially if the texture is stored in a compressed format like .gif or .png (instead of bmp).

Any comments…? Thanks alot for your input so far.

first of. you can think of a texture-stage as a additional layer (like in better paint-programs).
if you have 1 texture tiled over the floor and you shoot a “hole” in the ground you have to modify either the original texture in memory or add a second texturestage with th bullet hole ( in the end both the same since it will be mixed down)-the problem is that in both cases the bulled hole would be tiled as well. so if you shoot the ground under your feet the hole will appear all around you,too.
you can work around this effect if you split up every surface into a seperate object (not seperate node,since this would be performance suizide). and you could add a texture stage for each of the single surfaces allowing an unlimited number of bullet holes- just like you said… but it costs texture memory. since textures are not stored as png or gif’s inside your texture-memory.

both, your original idea and the workaround are quite memory intense.
a single position for a bullethole takes less memory than a the texture data with lots of pixel-values.
since graficcards can render LOTS of vertices/surfaces and since you can implement culling on these surfaces it’s often easyer and faster do add the additional geometry. you can have several thousands of these bulletholes without any trouble. and if you shoot new holes you can just make the old ones dissapear again (like in most games).

as long as you dont intend to plaster almost every inch of texture with bullet holes you’r probably better of using some kind of these “glued-bulletholes”. dunno, perhaps you can even utilize the particle system for it (havend checked this out,yet.)

In your config make sure you set the following:
prefer-parasite-buffer 0

Create a RTT (Render-To-Texture)
Create a separate camera for the RTT.
Render your ground texture into the RTT using the camera.
Turn OFF buffer clears (z clears and color buffer clears) for the RTT.
Use the RTT as your ground texture instead of the original texture.
Turn the RTT camera OFF.

When you want to add damage effects to the ground texture do the following:

Turn the RTT camera ON.
Render damage effects with z-test off and z-writes off.
Turn the RTT camera OFF.

You can replace “camera ONâ€