Improved Water with the Shorelines Beta

Hm, interesting… does this work for you?

Example script
local size = 100;

local solidMin = 2;
local solidSlopeZ = 0.05;
local waterLevel = 4;
local resolution = Vector3int16.new(size, size, size)

local terrainSize = Vector3int16.new(4,4,4) * resolution
local terrain = Game.Workspace.Terrain;
local region = Region3.new(Vector3.new(4,0,4), Vector3.new(terrainSize.X+4,terrainSize.Y,terrainSize.Z+4))
region = region:ExpandToGrid(4)

local function create3dTable(size)
	local ret = {}
	for x = 1, size.X do
		ret[x] = {}
		for y = 1, size.Y do
			ret[x][y] = {}
		end
	end	
	return ret
end

local material = create3dTable(Vector3.new(resolution.X,resolution.Y,resolution.Z))
local occupancy = create3dTable(Vector3.new(resolution.X,resolution.Y,resolution.Z))

for x = 1, resolution.X,1 do
	for z = 1, resolution.Z,1 do

		local ySolid = solidMin + (z-1) * solidSlopeZ;
		local ySolidInt = math.floor(ySolid);
		for y = 1, resolution.Y,1 do
			-- Note that this is NOT the correct calculation for occupancy of a perfect slope, but the approximation should be ok for this example
			local o = math.clamp(ySolid+1-y, 0, 1);
			occupancy[x][y][z] = o
			material[x][y][z] = if o>0 then Enum.Material.Sand else Enum.Material.Air; 
		end
	end
end

terrain:WriteVoxels(region, 4, material, occupancy)

local waterRegion = Region3.new(Vector3.new(-4,0,-4), Vector3.new(terrainSize.X+8,waterLevel*4,terrainSize.Z+8))
game.Workspace.Terrain:ReplaceMaterial(waterRegion, 4, Enum.Material.Air, Enum.Material.Water)

It should generate a gentle beach slope with shallow water, like this:

2 Likes

So, I tried the script, and I put a little delay at the start to give time for me to select ‘upgrade’ before rendering.
It worked as you posted, however, when looking at the code, I see you are creating the column for land, then as an after effect, creating a region 3 and using a ‘replace’ method to crate the water.

I modified the code to eliminate this extra step by adding the water into the creating of the table

for x = 1, resolution.X,1 do
	for z = 1, resolution.Z,1 do

		local ySolid = solidMin + (z-1) * solidSlopeZ;
		local ySolidInt = math.floor(ySolid);
		for y = 1, resolution.Y,1 do
			-- Note that this is NOT the correct calculation for occupancy of a perfect slope, but the approximation should be ok for this example
			local o = math.clamp(ySolid+1-y, 0, 1);
			occupancy[x][y][z] = o
			material[x][y][z] = Enum.Material.Sand
			if o <= 0 then 
				if y <= waterLevel then
					material[x][y][z] = Enum.Material.Water
					occupancy[x][y][z] = 1
				else
					material[x][y][z] = Enum.Material.Air
				end
			end
		end
	end
end

terrain:WriteVoxels(region, 4, material, occupancy)

--local waterRegion = Region3.new(Vector3.new(-4,0,-4), Vector3.new(terrainSize.X+8,waterLevel*4,terrainSize.Z+8))
--game.Workspace.Terrain:ReplaceMaterial(waterRegion, 4, Enum.Material.Air, Enum.Material.Water)

However when inserted directly into the table to be send to write voxels I get the same bad results I was getting in my own code.
image

So my questions…
Does this mean terrain:WriteVoxels is not capable of taking advantage of this water update?
and if that is true, do you think there are plans to allow for this?

Also what is the hit on performance in using the Terrain:ReplaceMaterial to add the water in the second step?

For me there should be only slight extra calculations as I use a chunk based system, and so its fairly easy for me to modify the chunks region3 to create a water region3, and I can even optimize, by adding a flag, that is turned on when a column in the chunk is below water level to trigger the rendering of water. I just worry about it being essentially 2 creations, once with the write voxels, then one with the replace, let alone whatever internal checking is going on in the replace.

Also, though I use 2D noise to generate a ‘surface’ level, if I were to ever use 3D noise to generate caves or other hollow spots under the surface, if those areas were to have water, it might not be a consistent level per chunk. Also on the surface, if I needed a stream that ran downhill, there would be non consistent water level. I would in those cases need to run a ‘replace’ per column (I use a 32x32 chunk) so I would think that could get expensive fast.

Thanks.

4 Likes

Yes, I understand your concern. The intention was to also be able to do that with a second call to WriteVoxels(), like this:

Example Code
-- You'd add this after the initial write...
for x = 1, resolution.X,1 do
	for z = 1, resolution.Z,1 do

		for y = 1, resolution.Y,1 do
			local water = if y>waterBottom and y<=waterLevel then 1 else 0;
			if water>0 and occupancy[x][y][z]<1 then
				occupancy[x][y][z] = water
				material[x][y][z] = Enum.Material.Water;
			end
		end
	end
end

terrain:WriteVoxels(region, 4, material, occupancy)

It seems that there’s a bug preventing it from working as expected. We’ll fix that soon.

But in general, it cannot possibly be achieved with just one write. It has to be either two writes, or a write and a replace. Because this is what it needs to look like:


Note the voxels D1 through G1 in that diagram. They need to have both water, and solid. So you need to write them twice, this way or another.

If the level is consistent, a block replace is simplest. For non-level like streams flowing down-hill, a two-pass write of the entire chunk would be best. Would that work for you (once the bug is fixed and two-pass write works correctly)?

4 Likes

Yes, I can’t really see any use case that a second WriteVoxels couldn’t handle.
Though its a second write, at least it would be able to be per column, and not have any replace.
I think it would be fine. Looking forward to testing it out when the bug is fixed.

Thanks for the answers.

Is there a way to read the water occupancy of a voxel only and ignore the other material? Since water and the normal material is stored separately, it’d be ideal to be able to read the water occupancy of a object too.

Seems like it could be an added property to the part, such as CastShadow.

1 Like

The two-pass writing as described above should now work correctly. Please let me know it you still see issues with it. (Edit: still rolling out - should be fully enabled in ~40 minutes).

1 Like

Hey asimo3089 - and others - we have fixed all known issues, and we managed to make it so that no re-conversion is required. :tada:

I would still advise to retest your particular places carefully before shipping, but it looks like this could be good to go.

Please let me know what you find. Thanks for all the great feedback!

3 Likes

I’ve been getting multiple reports recently of water rendering (or replicating?) incorrectly, typically more water is being drawn than expected. I cannot reproduce this myself at all, but it seems to line up with the recently set DFFlagShorelines_FixWriteVoxels_Rollout flag. All water in my games is created via the WriteVoxels method (server-sided), areas of about 200x1x200 voxels per API call.
My games have not migrated to the new shorelines yet.

In case I determine more clues I’ll post them here too, but hopefully this already helps finding the cause…

We had to roll the flag back, for a different reason, but then I suppose your problem should’ve gone away too.

Can you please provide a simplified reproduction case for your issue, so we csn make sure that’s fixed as well?

I wasn’t able to reproduce it yet, but it’s possible that I wasn’t actually enabling the flag. What format does this flag have, and which value should I use to make sure that it’s always enabled within Studio?

You shouldn’t use the rollout version of the flag. Just setting DFFlagShorelines_FixWriteVoxels to true is best if you want to test it locally. Looking forward to see what you can find.

I’m experiencing two bugs with Shores Beta where upgrading shores before water placement removes the shore benefits, and painting the shore after upgrading removes all shore benefits.

Backstory: I’m working on making Jailbreak work with shores. Part of this upgrade for Jailbreak involves removing all existing water so we can insert terrain “ramps” at the coasts so vehicles can drive out. Previously land was vertical walls for you to run into. Once all the “ramps” are placed, we place the water back in.

Issues:

  1. Painting the coastal terrain any other material will remove the wavy blend interaction water had. You can see it in this below video. Notice how nice the Grass side looks blended until one side is painted with Ground.
    Video: Shores Beta // Bug 1 - YouTube
    The water shows the same problem @SelDraken had.

  2. As you place water using a part-to-terrain plugin after upgrading shores, you’ll be met with hard edges.
    The only solution is to place all of your water, then upgrade to the Beta when you’re 100% finished with your water placement.
    Video: Shores Beta / Bug 2 - YouTube
    This implies adding new terrain + water in a “Map Expansion” after upgrading could be unfixable.

  3. Oddest yet, I made you a repro file on a fresh empty baseplate and I experience none of these issues. This is specific to my Jailbreak file. If you’d like a copy of the Jailbreak map, send a DM. @hyperhumanist

Issues aside, we are excited to upgrade Jailbreak. Thank you!

EDIT: Studio just updated which required me to close and re-open my files. I’m not sure if an update fixed the problem or reopening the file fixed the problem but my issues have disappeared.

6 Likes

Unfortunately I haven’t been able to reproduce the behavior multiple players saw myself at all with this flag set in Studio. Is there any way to verify that the flag is actually having any effect at all? I haven’t noticed any change in behavior with this flag enabled in Studio.

Sorry about that, asimo3089. When I wrote that we fixed it last week, some flags had to be rolled back afterwards, and some didn’t deploy for various reasons. It should all be fixed now, just flipped the last flag a few minutes ago.
Please let me know if you still see some of the above problems.

Just to clarify - it is not the intention that the “upgrade” process is something special. It is just a helper for easier upgrade. You should be able to achieve all the same results in new edits after the upgrade. If that’s not the case, please let me know.

2 Likes

The issue causing my previously mentioned water issues returned now. It seems like setting the material to Air doesn’t remove water anymore. I’ve only been able to reproduce this in live servers (not in Studio), and only some servers seem to have this broken behavior (probably due to the rollout?).

This seems to reproduce it (in a server-sided script):

local test_region = Region3.new(Vector3.new(0, 0, 0), Vector3.new(4*100, 4, 4*100))

local voxel_material = {}
local voxel_occupancy = {}
for x = 1, 100 do
	voxel_occupancy[x] = {table.create(100, 1)}
end

while true do
	for x = 1, 100 do
		voxel_material[x] = {table.create(100, Enum.Material.Water)}
	end

	game.Workspace.Terrain:WriteVoxels(test_region, 4, voxel_material, voxel_occupancy)
	
	wait(1)

	for x = 1, 100 do
		voxel_material[x] = {table.create(100, Enum.Material.Air)}
	end

	game.Workspace.Terrain:WriteVoxels(test_region, 4, voxel_material, voxel_occupancy)
	
	wait(1)
end

The expected behavior is that the water appears and disappears every second, but in servers with this issue the water will never disappear (setting material to Air has no effect). Area size doesn’t seem to matter.

In cases where the material values are mixed (not just entirely Air or Water like the simple example above), new water will be created in the correct areas as expected, but any existing water will still not be removed.

@Den_S seems that those servers need to be restarted to update the flags.
(Edit: Note that this has nothing to do with water. The same happens with ground as well.)

1 Like

This issue is still occurring in my game, even in fresh servers. It still seems like only some servers are affected.

1 Like

Ok, we’ve rolled back the offending flag. You should not be seeing the issue anymore. If you do, please let me know.
This means that WriteVoxels for Shorelines will not work as expected again, but we should have this corrected again in about a week. Sorry for the mess.
Please let me know if this is still appearing.

4 Likes

Looks like it’s no longer occurring now, thanks for the quick rollback!

1 Like