World Aligned Textures with the Texture Object

I have a game where you can paint surfaces with different paint and I wanted to give the paint texture, but due to the nature of my paint splats they have to overlap with one another to look good. Of course this means if I want to use materials I can’t because the Z fighting would be very obvious and would look terrible.


With Materials:

(its kind of hard to see but in game it looks terrible)

Up until now I settled with smoothplastic as it has no texture detail and therefore there is no z fighting. I then remembered how Unreal Engine has World Aligned Textures and was wondering on how I could recreate that effect using the Texture object in ROBLOX and its StudOffset U and V properties. However, I am very lost on how to approach this.

(Go to WorldAlignedTexture near the bottom)


(You can see where they overlap here but that is because the image has transparency - you get the idea I hope)

Basically, I want to be able to take the position and size of a part into account and use them to create an offset that means the origin point that the textures would “start” from would be at world 0, 0, 0, meaning no matter where they are they would line up perfectly with one another. I don’t care too much about rotation as I wont be using the Y component (relative to the flat face), in other words none of this:

I attempted this myself but it did not work the way I wanted it too, and I also couldn’t figure out how to accommodate for size.

TL;DR: I want to be able to make the texture object line up with the world’s origin so that the textures of any overlapping parts line up perfectly seamless, regardless of size or position. I don’t really mind about rotation since it’s probably impossible with what tools we have.

Is there any way I can do this?

1 Like

Maybe you could union them with a negated part somewhere far off in space to offset textures/materials??

local function onSplatterCreated(splatterPart)
	local negatePart1 = Instance.new("Part")
	negatePart.Position = Vector3.new(10000, 10000, 10000)
	
	local negatePart2 = Instance.new("Part")
	negatePart2.Position = Vector3.new(-10000, -10000, -10000)

	-- set the splatter part's position/orientation here if you haven't already
	
	local union = splatterPart:SubtractAsync(
		{negatePart1, negatePart2},
		-- optional CollisionFidelity and RenderFidelity enums
	)
	
	-- apply textures/materials to the union
end

My theory is the negated parts will offset the “bounding box” of the union, and applied textures rely on this as a base for its starting position. My second guess would be to create a negated part in all 8 corners of Workspace and try it again.

This sounds very far-fetched even for me, so let me know if it doesn’t do what you hoped.

1 Like

So I would union all splatters together with a negative part somewhere in the distance? It could work, but my only concern is that union operations are fairly slow and would make the splats delayed from when the ball hits the surface…
Another thing as well is I have to fire rays to find the top normal of these parts (I’m using EgoMoose’s Gravity Controller Module), so I would have to use precise convex decomposition, which could be bad for performance? I’m not 100% sure but I will try this, thanks!

I’m not able to test this now but I will try it tomorrow. If anyone else has any ideas in the meantime please let me know!

1 Like