[SOLVED] Mesh texture bleeding

Why sometimes texture in mesh are leaking? Trying to make tilemap with mesh-component and sometimes, 1/10, there weird artifact happening (blue is artifact):

full script:

local POS_STREAM_ID = hash("position")
local POS_VERT_COUNT = 18
local TEX_STREAM_ID = hash("texcoord0")
local TEX_VERT_COUNT = 12

local function set_pos_vertices(stream, offset, u, v, w, h, z)
	--[[
		       0-1-2  0-2-3
		3---2      2  3---2
		|2 /|     /|  |2 /
		|/ 1|    /1|  |/
		0---1  0---1  0
	--]]
	stream[offset + 01], stream[offset + 02], stream[offset + 03] = u,   v,   z
	stream[offset + 04], stream[offset + 05], stream[offset + 06] = u+w, v,   z
	stream[offset + 07], stream[offset + 08], stream[offset + 09] = u+w, v+h, z
	--
	stream[offset + 10], stream[offset + 11], stream[offset + 12] = u,   v,   z
	stream[offset + 13], stream[offset + 14], stream[offset + 15] = u+w, v+h, z
	stream[offset + 16], stream[offset + 17], stream[offset + 18] = u,   v+h, z
end

local function set_tex_vertices(stream, offset, u, v, w, h)
	--[[
		         00-01-11 00-11-01
		01---11       11  01---11
		| 2 / |      / |  | 2 /
		| / 1 |    / 1 |  | /
		00---01  00---01  00
	--]]
	stream[offset + 01], stream[offset + 02] = u,   v
	stream[offset + 03], stream[offset + 04] = u+w, v
	stream[offset + 05], stream[offset + 06] = u+w, v+h
	--
	stream[offset + 07], stream[offset + 08] = u,   v
	stream[offset + 09], stream[offset + 10] = u+w, v+h
	stream[offset + 11], stream[offset + 12] = u,   v+h
end

local function new_buffer(width, height)
	local buff = buffer.create(width * height * (POS_VERT_COUNT / 2), {
		{ name = POS_STREAM_ID, type = buffer.VALUE_TYPE_FLOAT32, count = 3 },
		{ name = TEX_STREAM_ID, type = buffer.VALUE_TYPE_FLOAT32, count = 2 }
	})
	resource.set_buffer(go.get("#mesh", "vertices"), buff)
	return buff
end

local function new_tileset(self, width, height)
	-- fill table with uv coords
	local ts = { [0] = { u=0, v=0, w=0, h=0} } -- empty 0 tile
	for y = 0, width / self.cell_w - 1 do
		for x = 0, height / self.cell_h - 1 do
			local tile = {
				u = (x*self.cell_w) / width,
				v = (y*self.cell_h) / height,
				w = self.cell_w / width,
				h = self.cell_h / height,
			}
			tile.v = 1 - (tile.v + tile.h) -- flip y coordinate
			ts[#ts + 1] = tile
		end
	end
	return ts
end

local function load_map(self, tiles, width, height)
	local tex = buffer.get_stream(self.buffer, TEX_STREAM_ID)
	local pos = buffer.get_stream(self.buffer, POS_STREAM_ID)

	for y = 0, height-1 do
		for x = 0, width-1 do
			local idx = y * width + x
			-- local tile = tiles[#tiles-idx]
			local tile = tiles[1+idx]
			local lookup = self.tileset[tile]
			if tile == 0 then
				set_pos_vertices(pos, idx * POS_VERT_COUNT, x, y, 0, 0, 0)
			else
				set_pos_vertices(pos, idx * POS_VERT_COUNT, x, y, 1, 1, 1)
			end
			set_tex_vertices(tex, idx * TEX_VERT_COUNT, lookup.u, lookup.v, lookup.w, lookup.h)
		end
	end

	resource.set_buffer(go.get("#mesh", "vertices"), self.buffer)
	
	local stream_positions = buffer.get_stream(self.buffer, "position")
	for i=1,#stream_positions do
		print(i, stream_positions[i])
	end
end

function init(self)
	local tiles = {
		1,1,1,
		1,1,1,
		1,1,1,
	}
	self.cell_w, self.cell_h = 16, 16
	self.buffer = new_buffer(3, 3)
	self.tileset = new_tileset(self, 32, 32)
	load_map(self, tiles, 3, 3)
end

this how look positions stream:

DEBUG:SCRIPT: 234	5.7453237037317e-44
DEBUG:SCRIPT: 235	1.6263382085862e+22
DEBUG:SCRIPT: 236	8.2049239736307e-23
DEBUG:SCRIPT: 237	0
DEBUG:SCRIPT: 238	2.8025969286496e-45
DEBUG:SCRIPT: 239	0
DEBUG:SCRIPT: 240	0
DEBUG:SCRIPT: 241	-8.8907364410882e-36
DEBUG:SCRIPT: 242	-1.0102671716601e+21
DEBUG:SCRIPT: 243	8.4077907859489e-45

here MRP:

keep pressing F2 to try/catch bug

Empty Project.zip (81.7 KB)

Maybe it is floating point errors in here..

Personally I would change this function so that it doesnt use self, and that width and height is the number of tiles:

local function new_tileset(cell_w, cell_h, size_w, size_h)
	-- fill table with uv coords
	local ts = { [0] = { u=0, v=0, w=0, h=0} } -- empty 0 tile
         local invsize_w = 1/size_w
         Local invsize_h = 1/size_h
	for y = 0, size_w - 1 do
		for x = 0, size_h - 1 do
			local tile = {
				u = x * invsize_w,
				v = y * invsize_h,
				w = invsize_w,
				h = invsize_h,
			}
			tile.v = 1 - (tile.v + tile.h) -- flip y coordinate
			ts[#ts + 1] = tile
		end
	end
	return ts
end

Then

self.tileset = new_tileset(self.cell_w, self.cell_h, 2, 2)

I dont know if it will fix your bleeding problem, but here we compute once the size factor, so it could be more consistant

tried to change script, issue still occurs.

i bellieve, issue with position stream

local function set_pos_vertices(stream, offset, u, v, w, h, z)
	--[[
		       0-1-2  0-2-3
		3---2      2  3---2
		|2 /|     /|  |2 /
		|/ 1|    /1|  |/
		0---1  0---1  0
	--]]
	stream[offset + 01], stream[offset + 02], stream[offset + 03] = u,   v,   z
	stream[offset + 04], stream[offset + 05], stream[offset + 06] = u+w, v,   z
	stream[offset + 07], stream[offset + 08], stream[offset + 09] = u+w, v+h, z
	--
	stream[offset + 10], stream[offset + 11], stream[offset + 12] = u,   v,   z
	stream[offset + 13], stream[offset + 14], stream[offset + 15] = u+w, v+h, z
	stream[offset + 16], stream[offset + 17], stream[offset + 18] = u,   v+h, z
end

-- if i call this (x,y,w,h,z)
set_pos_vertices(pos, idx * POS_VERT_COUNT, x, y, 1, 1, 1)

-- why position stream sometimes becomes like this:
--[[
DEBUG:SCRIPT: 159	1
DEBUG:SCRIPT: 160	2
DEBUG:SCRIPT: 161	3
DEBUG:SCRIPT: 162	1
DEBUG:SCRIPT: 163	3.2229864679471e-44
DEBUG:SCRIPT: 164	4.5937646517189e-40
--]]

replace

width * height * (POS_VERT_COUNT / 2)

with:


width * height * (POS_VERT_COUNT / 3)

just make sure that buffer size is EXACT SIZE, if not you’ll get:

  1. texture bleeding
  2. random values in buffer

just got gaps between tiles when scrolling and zooming, but this is different issue.

2 Likes