Repeating texture?

Is there a way to somehow expand the size of a sprite (or some other component) and have the texture repeat inside the expanded area?

Yes, this is possible. Maybe someone else has a more elegant way of doing it.

You want to have an atlas per tiled texture you want to use. The important thing is that there is no gap around the tiled texture which means nothing else can be on it and it must be a power of 2.

Then you want a sprite material with wrap mode repeat.

Inside this shader you can have code such as

varying mediump vec2 var_texcoord0;

uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;
uniform lowp vec4 scale;

void main()
{
    // Pre-multiply alpha since all runtime textures already are
    lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
    lowp vec2 uv = vec2(var_texcoord0.x * scale.x, var_texcoord0.y * scale.y);
    gl_FragColor = texture2D(texture_sampler, uv.xy) * tint_pm;
}

Then you update the scale constant with a script

function init(self)
	local scale = go.get_scale()
	sprite.set_constant("#sprite", "scale", vmath.vector4(scale.x, scale.y, 1, 1))
	
end

In editor your tiled thing will look wrong, but in engine it should look right

2019-04-13%2009_14_32-Window

2019-04-13%2009_15_49-Window

If you want like a looping repeating background which moves in some direction that is possible to add too.

function init(self)
	local scale = go.get_scale()
	sprite.set_constant("#sprite", "scale", vmath.vector4(scale.x, scale.y, 1, 1))
	self.offset = {x = 0, y = 0}
end

function update(self, dt)
	self.offset.x = self.offset.x + dt
	self.offset.y = self.offset.y + dt / 2

	sprite.set_constant("#sprite", "offset", vmath.vector4(self.offset.x, self.offset.y, 0, 0))
end

varying mediump vec2 var_texcoord0;

uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;
uniform lowp vec4 scale;
uniform lowp vec4 offset;

void main()
{
    // Pre-multiply alpha since all runtime textures already are
    lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
    lowp vec2 uv = vec2(var_texcoord0.x * scale.x + offset.x, var_texcoord0.y * scale.y + offset.y);
    gl_FragColor = texture2D(texture_sampler, uv.xy) * tint_pm;
}

If youā€™ve seen pixel art games with repeating background patterns this can be a way to accomplish that. You can have multiple layers with parallax pretty easily too if your textures have transparency. When multi texturing comes it will be easier probably.

21 Likes

Great writeup. Would this approach work with flip book animations?

Assuming we get relative UV spaces sometime in the future that will be useful for using this method with animations. You could probably change the texture manually to animate it.

2 Likes

Nice one!

Is there any way to not have to use one atlas per texture that we want to wrap?

We still donā€™t have local UV space so I donā€™t see a way to do that well. Maybe there is a way to easily do it though.

I tried the example above but iā€™ve got only a stretched texture. Is something outdated? Iā€™am using the latest stable version of the editor and dmengine.

Okay, i found the error. go.set(ā€™#spriteā€™, ā€˜scaleā€™, ā€¦) is reserved or something and i couldnā€™t use it in the fragment program. After i changed it to ā€˜scale_repeatā€™ and updated the fragment it worked.

1 Like

What do you mean? Do you have a ticket for this? Repeating textures should be doable with atlases, but I havenā€™t looked at it

Theyā€™re talking about repeating the sprite images within the atlas. They donā€™t have access to the ā€localā€ uv coord, which might be another thing we might want to add in a future vertex format update.

4 Likes

Ah right, I thought we had that but Iā€™m probably thinking of labels ā€œrecipā€ uniform. But yeah, sounds like a thing we might want. Havenā€™t seen a ticket about it though

3 Likes

Added one, maybe it was an issue in the older git that never got migrated.

3 Likes