Tilemap issues

Hello,

after installing version 1.2.161 I’m getting design time issues with tilemaps

Tilemaps are always shown at the origin (0,0) in the designer grid.

I’m getting this issue at runtime

up to version 1.2.160 it was like this

with version 1.2.161 the tilemap is picking an incorrect tilesource

Thanks in advance

Thank you for reporting. We are working on a fix.

Temporary workaround:

I’m not sure it is the same issue.

I grabbed a video, hope it helps :slight_smile:

There’s a fix coming in the next release, you can preview it here:
Win64
OSX

2 Likes

I’ve tried the fix, but it is till picking tiles form incorrect source in the first layer of the tilemap.

The project is build with 1.2.160 then the issue is in the dmengine.

The tilemap uses “rounding.tilesource”

Version 1.2.161 (and also the fix) at runtime show only the first layer “layer” with tiles from “blocks.tilesource”

1 Like

Ok, could you create a minimal repro case and post it here, please?

1 Like

There he is :sweat_smile:

repro.zip (78.9 KB)

3 Likes

Thanks for the repro case!

We now have an alpha build with some tilemap fixes:

3 Likes

Now works well! :+1:

Thanks :upside_down_face:

3 Likes

Very good.
Thanks for testing @lrx!

3 Likes

Hi @Mathias_Westerdahl,

while developing lighting effect in shader I’ve found an issue related to the scale of the game object containing the tilemap

With version 1.2.160 by dividing position by tilesize (in the fragment shader) I obtain right tile indexes.

The shader is not ended, but you can see the lighting scan is perfecty aligned with tiles using a scale of 0.5 (I’m currently using for all the boards)

Also applying an “odd scale” 0.3 0.6

With version 1.2.161 and 1.2.162.alpha I obtain lighing tiles as if position is unscaled.

Scale 0.5

Scale 0.3 0.6

And with a scale of 1 lighting tiles are correctly sized but misaligned:

Vertex shader:

uniform highp mat4 view_proj;
uniform mediump mat4 world;

uniform lowp vec4 tilesize;

attribute highp vec4 position;
attribute mediump vec2 texcoord0;

varying mediump vec2 var_texcoord0;

varying mediump vec2 tilexy;

void main()
{
	highp mat4 mvp = view_proj * world;
	gl_Position = mvp * vec4(position.xyz, 1.0);
	var_texcoord0 = texcoord0;
	
	tilexy=vec2(position.x/tilesize.x,position.y/tilesize.y);
}

Fragment shader:

varying mediump vec2 var_texcoord0;

uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;

uniform lowp vec4 tilesize;
uniform lowp vec4 bounds; 
uniform lowp vec4 time_duration_speed_over; // x is timeloop from -n to n
											// y is lightin duration
											// z is lighting speed
											// w is alpha overburn

uniform lowp vec4 abk;						// x is cos(angle)
											// y is sin(angle)
											// z is abs(x)+abs(y)

varying mediump vec2 tilexy;

void main()
{
	// as obtained from tilemap.get_bounds z is width and w is height
	float width=bounds.z;
	float height=bounds.w;
	
	float alpha=-(abk.x*floor(tilexy.x)/width+abk.y*floor(tilexy.y)/height)/abk.z; //  alpha -0.5  0.5
	alpha=alpha*time_duration_speed_over.y;
	alpha=max((time_duration_speed_over.z-abs(alpha-time_duration_speed_over.x))/time_duration_speed_over.z,0); // triangular shape
	float over=mix(1,time_duration_speed_over.w,alpha);
	
	// Pre-multiply alpha since all runtime textures already are
	//lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w);
	lowp vec4 tint_pm = vec4(tint.xyz * over, over);
	//gl_FragColor = texture2D(texture_sampler, var_texcoord0.xy) * tint_pm; // final effect
	
	gl_FragColor = vec4(alpha,alpha,alpha,1.0); // alpha burn test
}

Hope this helps.

2 Likes

The tilemaps are always rendered in world space.
The change we’ve done is to make the tilemap regions (32x32) tiles batch with other regions, possibly from other tilemaps (with different scale). This means that the world matrix is unused (if it’s not set to the identity matrix, it’s a bug)

You can for instance add a uniform to the shader and material (e.g. “properties”) and then set it via script (just like you would for tint:

go.set("#tilemap", "properties", vmath.vector4(scale, 0,0,0))

Setting different values on components with the same material will break up the batching.

2 Likes

Thank you for the explanation!

I didn’t see the changes in the tilemap.vp :see_no_evil:

I’ve easily fixed by getting the world transform from the game object then inverting it.

With the inverse matrix in the shader I can tranform back position in object space. :+1:

But … :upside_down_face:

The only tricky thing is passing a matrix4 into the material because tilemap.set_constant only supports vector4, so it requires 4 uniforms.

image

The init function the matrix is splitted …

function init(self)
	self.tilemap="#level_animator"
	self.half_inteval=self.interval/2
	self.elapsed=self.half_inteval-self.speed*2
	self.time_pos=-self.half_inteval
	local x,y,w,h=tilemap.get_bounds(self.tilemap)
	tilemap.set_constant(self.tilemap,"bounds", vmath.vector4(x,y,w,h))
	local world=go.get_world_transform()
	local iworld=vmath.inv(world)
	tilemap.set_constant(self.tilemap,"iworldc0", iworld.c0)
	tilemap.set_constant(self.tilemap,"iworldc1", iworld.c1)
	tilemap.set_constant(self.tilemap,"iworldc2", iworld.c2)
	tilemap.set_constant(self.tilemap,"iworldc3", iworld.c3)
	update_tdso(self)
	compute(self)
end

And in the shared is recomposed …

uniform highp mat4 view_proj;

uniform lowp vec4 tilesize;

attribute highp vec4 position;
attribute mediump vec2 texcoord0;

varying mediump vec2 var_texcoord0;

varying mediump vec2 tilexy;

uniform mediump vec4 iworldc0;
uniform mediump vec4 iworldc1;
uniform mediump vec4 iworldc2;
uniform mediump vec4 iworldc3;

void main()
{
	gl_Position = view_proj * vec4(position.xyz, 1.0);
	
	var_texcoord0 = texcoord0;
	
	mat4 mediump iworld=mat4(iworldc0,iworldc1,iworldc2,iworldc3);
	
	vec4 highp iposition=iworld * vec4(position.xyz, 1.0);
	
	tilexy=vec2(iposition.x/tilesize.x,iposition.y/tilesize.y);
}

And so the next question(s) are:

  • Allowing to pass an matrix4 to material?
  • Or better, add the inverse world transformation matrix as chooseable option when building a material .

Thanks in advance

Sure, it’s currently possible to set vector4’s (we hopefully have some better support soon)

But is there really a need to send all that data? Aren’t you just using uniform scale?
Then it should be enough to send only that single float.

At now I’m using uniform scale and position, so yes, i can fit all them in a vect4 (x,y,z,uscale)
But maybe I’ll will slightly rotate the game grid so having the inverse transform matrix will cover all use cases.

1 Like