Scrollable textures for MeshParts

As a Roblox developer it is currently too difficult to achieve animated texture effects on curved surfaces.

The use-cases

There are many 20+ year old games that achieve incredible visual effects by simply applying scrolling textures onto curved surfaces. Below are some examples of beautiful effects you could create with this approach.

Water streams

In The Legend of Zelda: The Wind Waker (2003) scrolling textures are used to create the illusion of a water stream.

Quicksand

In Super Mario Galaxy (2007) scrolling textures are used frequently for waterfalls but also for quicksand.

Animated signs

In Mario Kart: Double Dash (2003) scrolling textures are used to animate the arrows on these animated signs.

The problem

Roblox currently offers very little options for artists to animate static surfaces. And the options we do have can only be used in very specific cases. Here are some of the options we have currently and why none of them work well on curved surfaces.

SurfaceGui

Although SurfaceGuis would work well to animate billboards, they do not have the option to curve with a surface. As such they cannot be used to create any of the above effects.

Beam

When you want to animate a surface by sticking a Beam on it, you will always have to offset your Beam because it will otherwise flicker against the surface it is on, or in other words ‘cause Z-fighting’.

image

On top of that, Beam instances cannot easily wrap around curved surfaces given the limited number of segments you work with. Especially considering that lower end devices which will automatically reduce your ‘Segments’ property you will often end up ‘clipping’ the beam into the curved surface’s geometry.

MeshPart.TextureID

You could theoretically animate a curved surface if that geometry is created through a MeshPart. However, for each ‘frame’ in the animation you would need a unique texture which completely overflows your memory budget.

Texture

Like with MeshPart.TextureID, Texture instances actually properly maps onto a curved surface. The OffsetStudsU and OffsetStudsV properties can also be used to create a scrolling texture of sorts. However, developers have no control over how exactly Texture instances map their image onto a mesh. From how I understand it the texture is simply projected orthographically onto the triangles of the mesh depending on the triangles’ surface normals’ directions.

Given the lack of projection control there is also no way to use a Texture instance to create an ‘outwards pulsing’ effect such as in the quicksand example. You also cannot add any sort of wobble required to achieve the effect of the water stream example.

A potential solution

One potential solution that would enable developers to create effects similar to the examples above would be to add a ‘UV offset’ property of sorts. If a developer has properly UV-unwrapped their mesh, they should be able to create all of the effects above by simply shifting their mesh’s UV map on the X-axis or Y-axis.

Below is an example of a smoke cloud I created in which the cloud texture properly rotates around the curved surface simply by moving the UV map to the left or right.

And here is a quick-and-dirty example of how you could use this same feature to create a quicksand effect.

Note that I am only providing some implementation ideas here. I do not care about the actual implementation so long as developers are enabled to create the aforementioned visual effects.

43 Likes

I have been informed that it is technically possible to achieve the ‘scrollable UV map’ effect using the new EditableMesh feature. I was unaware of this as I hadn’t had the time yet to look into them. I gave the feature a try and although it is indeed possible to achieve such an effect now, I would say that the UX for artists could use improvements.

Understandably the EditableMesh API is still subject-to-change so the current approach may be out-of-date when the feature is released. And I am hoping that - especially for artists - the feature could be tweaked to better empower artists who have little programming experience.

The current approach

You first create a mesh in Blender/Maya/etc. whose UVs are mapped such that they can be easily scrolled during gameplay. Then in studio you add a snippet of code to the MeshPart to turn it into an EditableMesh, then store the UV coordinates and increase them every frame:

local AssetService = game:GetService("AssetService")
local EditMesh = AssetService:CreateEditableMeshFromPartAsync(script.Parent)

EditMesh.Parent = script.Parent

local vertices = EditMesh:GetVertices()
local StartUVs = {}
for i = 1, #vertices do
	StartUVs[vertices[i]] = EditMesh:GetUV(vertices[i])
end

local startTime = tick()
local t = startTime

while true do
	game:GetService("RunService").Heartbeat:Wait()
	t = tick()
	local x = (startTime - t) / 5 -- determine how fast the UV-map scrolls

	for i = 1, #vertices do
		EditMesh:SetUV(vertices[i], StartUVs[vertices[i]] + Vector2.new(-x, 0))
	end
end

The downsides

  • The only way to test the visual effect is by running your game. Other VFX features like ParticleEmitters and Beams are simulated while in edit mode which is a big UX improvement over the current workflow using EditableMeshes.
  • Achieving the scrollable effect currently requires more than a basic understanding of programming. If you are an artist who has less than a couple days of programming experience you are basically dependent on other programmers if you want to create this sorts of effect.
7 Likes

im new to fx and i can already feel the large limitations. this was one of the issues but particles even worse. basic functions like animating a particles rotation overtime is impossible.

1 Like

Even this code shows the possibilities of this feature, and it would be so nice to create different effects.

2 Likes

copied the code onto this and it looks amazing with surface appearance

1 Like