Solutions for projecting a blood texture on many surfaces?

Godot Version

4.4

Question

I’m working on a blood pool/decal system and I’m trying to come up with a solution to project the blood on any surface on my map.

The current system writes blood textures into a subViewport, which I can then run a shader on and make the ‘decals’ interact with each other and animate them (see the attachment).

The problem is - it works good only for one surface. It’s basically a megatexture (1080x1080) that covers the floor and I want it properly conform to underlying surfaces so the blood could cover walls, ceilings and such.
I found this tutorial which is great but works only if you have one texture that covers the whole map, while I have many materials (generated by Qodot, for example). Any ideas how I can approach this?
I know that Portal 2’s gels were stored in a lightmap-like texture. I thought about solutions as crazy as creating my own atlas texture that would contain all the surfaces that need the blood projected on them (faces somehow derived from the meshes). Simple decals are out of the question as they z-fight and can’t be easily cut off on the edges and I need a shader that runs on the texture and it would be impossible to have many decals that way, as Godot shaders support only 1 per-instance texture uniform

2 Likes

You can use the decal node and some particles for creating realistic blood effect. Using shaders for it is not necessary.

Did you read my post? I listed many reasons why decals are out of the question [sic] and I need the shader for visual effects (such as using the screen’s normal texture).

1 Like

Oh sorry, actually I not have much knowledge on shaders but I think creating that blood effect on both wall and floor with decals node will possible if one decal node is rotated somehow and the other normal.

I need the decals to have an animation and to interact with each other seamlessly. The decal approach won’t work because

Simple decals are out of the question as they z-fight and can’t be easily cut off on the edges and I need a shader that runs on the texture

And also they won’t seamlessly blend with each other. My current approach makes the blood’s edges more saturated, and if they were separate decals the seams would be seen. Keeping them in one texture allows me to read it from a shader and apply effects on it as a whole, so it blends in a seamless way.

All the other problems still apply. Z-fighting, stacking up causing performance cost, non-conforming to the underlying surfaces (decal extends beyond the face it’s on) and I couldn’t use a simple shader material this way because

Godot shaders support only 1 per-instance texture uniform

1 Like

Have you tried applying your shader to the Material Override? (Inspector → GeometryInstance3D → Geometry → Material Override)

On the surface that’s supposed to have the decals on them? This is a good idea, but they are still stored in one texture and I first have to divide it somehow

I’d think you could split the texture by just starting it at different offsets based on what’s around it.

Can you expand on this thought? I didn’t really understand what you were saying here.

Also, are you doing this as a normal code shader or a visual shader?

Yup, that’s what I’ve been thinking too. This would require me to create an atlas of all faces that need the blood to be displayed on them. Seems like an insane task but it’s probably doable.

Can you expand on this thought? I didn’t really understand what you were saying here.

What I was initially trying to do (with meshes that acted as decals) was having a simple texture uniform uniform sampler2D texture: hint_default_black; and pass the blood texture to the shader this way.
However, updating the texture in one shader changed the effect on every other instance. This would be fixed with instance uniform sampler2D texture: hint_default_black; if it was supported by Godot, but it isn’t
The 'SCOPE_UNSTANCE' qualifier is not supported for sampler types.

The shader is written in gdshader

I think there’d be a programmatic way. Find the polygon face of the first surface and use that to calculate the start for the other adjoining faces. It’d be more difficult initially, but you’d never have to worry about what was in your scene. Basically like using your faces like a cookie-cutter - or fitting a puzzle together.

Any uniform sampler2D texture you create can be made unique in the editor, which means there’s a way to do it through code - just perhaps not in the shader code. Apply the shader, make the texture unique, should be good.

Most of what I know about gdshader I’ve learned by converting 3.5 gdshaders to 4.x Visual Shaders.

1 Like

Maybe there’s a way of doing this I didn’t think of, but having multiple (possibly hundreds, thousands) shader materials would probably impact the performance way too much

Definitely. A guy was doing something similar in the link In my original post, to paint on textures in real time. So there is a way, but I feel like I’m fighting with the engine this way. Trying to brainstorm

Is there a reason your shaders can’t disappear after a while?

FWIW, I’m going to play with decals. I didn’t even know they existed in Godot until your post. I’ve been reading up on them. I’m going to try creating a frost effect with them I can apply to an object. Right now I’m using the overlay and a Visual Shader to make only part of the object frosted. I think this will work better. If I come up with any ideas, I’ll let you know.

1 Like

They could, but still using decals for this would be a terrible solution, as I mentioned there will be z-fighting issues, the decals won’t blend with each other and they just don’t know the underlying geometry. I need something way more flexible.

FWIW, I’m going to play with decals. I didn’t even know they existed in Godot until your post

What I usually mean by decals is just a quadmesh that I use as a decal, as simple godot decals are way too restrictive and for advanced use cases it’s better to just write your own solution. But for quick enhancements of visuals of environments for example they are great

1 Like

I’m sorry I couldn’t help more.

1 Like

You did help, I thought of a different way of getting the face I want to apply the blood on from the mesh because of your responses. Thanks for chiming in

Awesome! I’m glad to hear it! I definitely learned some new things about Godot, which is awesome! I really enjoy this engine despite it’s quirks.

1 Like