 # Smooth gradient between parts textures

How would I go about changing the color in between these parts for a procedural island to match like a gradient?

Example of what it does:

You can see how the colors just stop

Code for the coloring portion:

``````-- Generation
local w1 = wedge:Clone();
w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back)));
w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back);
w1.Parent = game.Workspace.Island.Terrain;

local w2 = wedge:Clone();
w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back)));
w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back);
w2.Parent = game.Workspace.Island.Terrain;

-- Coloring

local w2height, w1height = w2.Position.Y, w1.Position.Y

if w2height <= -4 and w1height <= -4 then -- if the wedge heights are under -4 it will set that to sand.
w1.BrickColor = BrickColor.new("Cool yellow") -- sets w1 wedge to a sandy color
w2.BrickColor = BrickColor.new("Cool yellow") -- sets w2 wedge to a sandy color also
end
``````

How I would go about doing this would be to set each wedge’s color based on how far it is way from a given height; in your case, the change from grass to sand happens at y-level -4.

You choose two points around that height, a start and end for your gradient, then find the ratio of your wedge’s position between those points. This ratio would control how far into the gradient you are, with 0.5 being the middle of the two colors. Basically just linear interpolation, like a tween or lerp.

Something like this should, I tested what I could, without actually making a terrain generation system:

``````-- Make some variables or a table for your colors
local TerrainColors = {
Grass = BrickColor.new("Parsley green"),
Sand = BrickColor.new("Cool yellow")
}

-- getColorGradient(colors : table, gradientPos : float)
-- Calculates the R, G, B values based on position in the gradient
local R = colors.R + (colors.R - colors.R) * gradientPos
local G = colors.G + (colors.G - colors.G) * gradientPos
local B = colors.B + (colors.B - colors.B) * gradientPos

return Color3.fromRGB(R * 255, G * 255, B * 255) -- Reformats the values and converts them into a Color3
end

-- getGradientPosition(wedgeHeight: int, height : int, spread : int)
local startHeight = (height + spread)
local endHeight = (height - spread)

return math.clamp((wedgeHeight - endHeight)/ (startHeight - endHeight), 0, 1)
end

local w2height, w1height = w2.Position.Y, w1.Position.Y

local sandHeight = -4
if w2height <= sandHeight and w1height <= sandHeight then
-- Sets the color to the returned color gradient (based on the Gradient Position) for each wedge
w1.Color = getColorGradient({TerrainColors.Grass, TerrainColors.Sand}, getGradientPosition(w1height, sandHeight, 5))
w2.Color = getColorGradient({TerrainColors.Grass, TerrainColors.Sand}, getGradientPosition(w2height, sandHeight, 5))
end
``````
• `getColorGradient()`: creates a color between two given colors in a table (the start and end colors). While using a gradient position, the ratio between the two points that the wedge is, to decide how much of each color should be present within the returned color.

• `getGradientPosition()`: calculates the ratio of a given wedge height between two points. The points are calculated using a height (the point where the colors should change) and the spread (how far the gradient should spread in studs) around that height.

2 Likes

Thank you for replying! I tested it and got and error about the R G B on colors[]

` 'R' is not a valid member of BrickColor`

Any idea how to fix that?

Oh my bad BrickColor uses lowercase for its RGB values. For the colors inside the TerrainColors table, if you are going to use BrickColor values make sure to add `.Color` to the end of each color.

``````local TerrainColors = {
Grass = BrickColor.new("Parsley green").Color,
Sand = BrickColor.new("Cool yellow").Color
}
``````

Change the order of the colors in the colors table of the getColorGradient function. If it’s inverted it’s because the start and end points are swapped.

``````w1.Color = getColorGradient({TerrainColors.Sand, TerrainColors.Grass}, getGradientPosition(w1height, sandHeight, 5))
w2.Color = getColorGradient({TerrainColors.Sand, TerrainColors.Grass}, getGradientPosition(w2height, sandHeight, 5))
``````

See if that helps 1 Like