Uneven Water Terrain Edges

Hello,

I’m currently working on a kind of water poolfeature for my game, but I’ve encountered a frustrating issue with how the water edges work/ are rendering. Some areas of the water appear to have an awkward slope, creating an unintended wedge effect rather than a flat, seamless surface.

I’ve tried adjusting the terrain settings and checking for any overlapping parts, but nothing seems to correct the issue. Has anyone experienced something similar? Any suggestions or solutions on how to achieve a more uniform edge for the water would be greatly appreciated!


Thank you in advance for your help!

3 Likes

Add water outside the walls! ,I think it should works

2 Likes

That’s the problem… next to the pool is another pool that needs to stay empty…

As far as I know, the only option is to make the walls thicker and place water in them ):

So Roblox has no other way of making water flatt?.. Thats kinda wierd…

1 Like

Evidency?


This is possible! However, achieving this effect requires a decent knowledge of how the Terrain system works on Roblox. I might write a more in-depth explanation later, but basically you want to create a shell of low occupancy voxels (Occupancy = 1 / 256) around a volume of full occupancy voxels (Occupancy = 1).

The images below show a 4x3x4 region of voxels with the voxel boundary box in black. The green cube in the 2nd image shows the bounding box of a single voxel, and the third image shows a texture on the surface of the bounding box representing the outer faces of the voxels.

This technique can be applied to most terrain-compatible material, however depending on the geometry of the material, results may vary. The Material Manager allows custom materials to choose the “Pattern” which is a reference to a Enum.TerrainPattern type, however there’s seemingly missing EnumItems since terrain Water appears to be a unique case and renders lower (roughly half a voxel) than other materials with identical occupancy data. Some materials, like WoodPlanks, can only render as completely full voxels or completely empty voxels.

Anyways, here’s some code you can use to generate “sharp terrain cubes” like the images shown above. I didn’t add checks for ensuring the position and size of the region are aligned to the voxel grid, but if you pass in the Position and Size of a Part that is aligned to the voxel grid it should work fine:

The code:
--!strict

--Helper function to generate 3D arrays used when calling `Terrain:WriteVoxels()`
local function makeVoxelArray<T>(size: Vector3, v: T): {{{T}}}
	local array = {}
	for x = 1, size.X do
		array[x] = {}
		for y = 1, size.Y do
			array[x][y] = {}
			for z = 1, size.Z do
				array[x][y][z] = v
			end
		end
	end
	return array
end

--This function will fill a region with a "sharp" cube of terrain voxels
--The bounding box of the `size` parameter (centered on `centerPos`) *should* be aligned to the voxel grid (aka it's corners should be on voxel corners)
function fillSharpTerrainCube(centerPos: Vector3, size: Vector3, material: Enum.Material)
	local voxelSize: Vector3 = size / 4
	local corner1: Vector3 = centerPos - 2 * voxelSize
	local corner2: Vector3 = centerPos + 2 * voxelSize
	local region: Region3 = Region3.new(
		Vector3.new(
			math.min(corner1.X, corner2.X),
			math.min(corner1.Y, corner2.Y),
			math.min(corner1.Z, corner2.Z)
		),
		Vector3.new(
			math.max(corner1.X, corner2.X),
			math.max(corner1.Y, corner2.Y),
			math.max(corner1.Z, corner2.Z)
		)
	)

	local matArray = makeVoxelArray(voxelSize, material)
	local occArray = makeVoxelArray(voxelSize, 1)

	for x = 1, voxelSize.X do
		for y = 1, voxelSize.Y do
			for z = 1, voxelSize.Z do
				local isEdgeX: boolean = x == 1 or x == voxelSize.X
				local isEdgeY: boolean = y == 1 or y == voxelSize.Y
				local isEdgeZ: boolean = z == 1 or z == voxelSize.Z
				if isEdgeX or isEdgeY or isEdgeZ then
					occArray[x][y][z] = 1 / 256
				end
			end
		end
	end

	workspace.Terrain:WriteVoxels(region, 4, matArray, occArray)
end
4 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.