Colour in objects based on temperature

Hi
I am using math.noise to generate numbers between -1 and 1 to make a temperature map. I then use a function I wrote to convert it into:

  • 0 to 2 instead of -1 to 1
  • to percentage e.g. 100
  • to rgb value e.g. 255
  • create Color3.new() based on the rgb value

Which gives me this:


(The brighter the colour the hotter the temperature and the darker the colder)

But now I want to change it up into colours so objects with very high temperature (very light colour) will be yellow for sand, very cold (very dark colour) will be white for snow, greyish colour will be green for grass etc. And it would be cool if it could smoothly transfer between the 2 so grass between sand would slowly fade into the other one just like it does right now.

I use @CoderHusk linear mapping function math.bound in his math library which does the job quite well to change the range to 0 to 1 which can be changed comfortably through multiplication.

I also use ColorSequences to map the colors as it accepts a number from 0 - 1 perfect with math.bound

Here is an example how to change the range of math.noise. You will also need the evalCS to get color at that number in the range 0-1

evalCS
function evalCS(cs, time)
	-- If we are at 0 or 1, return the first or last value respectively
	if time == 0 then return cs.Keypoints[1].Value end
	if time == 1 then return cs.Keypoints[#cs.Keypoints].Value end
	-- Step through each sequential pair of keypoints and see if alpha
	-- lies between the points' time values.
	for i = 1, #cs.Keypoints - 1 do
		local this = cs.Keypoints[i]
		local next = cs.Keypoints[i + 1]
		if time >= this.Time and time < next.Time then
			-- Calculate how far alpha lies between the points
			local alpha = (time - this.Time) / (next.Time - this.Time)
			-- Evaluate the real value between the points using alpha
			return Color3.new(
				(next.Value.R - this.Value.R) * alpha + this.Value.R,
				(next.Value.G - this.Value.G) * alpha + this.Value.G,
				(next.Value.B - this.Value.B) * alpha + this.Value.B
			)
		end
	end
end
--Example color sequence choose from a color design website like adobe kuler (old) or color
local darkGreen = Color3.fromRGB (124,141,76)
local lightGreen = Color3.fromRGB (181,186,97)
local brown = Color3.fromRGB (114,84,40)
local whiteish = Color3.fromRGB (229,217,194)
local blue = Color3.fromRGB (182,227,219)

local terrainColorSequence = ColorSequence.new{
	ColorSequenceKeypoint.new(0, darkGreen),
	ColorSequenceKeypoint.new(0.5, lightGreen),
	--ColorSequenceKeypoint.new(1, brown),
	ColorSequenceKeypoint.new(0.8, whiteish),
	ColorSequenceKeypoint.new(1, blue),
}

local yNoise = math.clamp(noise,-1,1)--clamp it first according to math article
local alpha = MathLib.bound(-1,1,yNoise ) --bound it 0 to 1	
---alpha *= 2 --Make the new range [0*2, 1*2] = [0, 2] if you want it to
alpha = 1 - alpha --reverse the height depends on color sequence order
local wedgeColor = evalCS(terrainColorSequence,alpha)
wedge.Color = wedgeColor

Mine uses the height generated from the terrain instead,

			local alpha = MathLib.bound(minHeight,maxHeight,wedgePos.Y) --min height is terrain bottom, max height is terrain max height (at the very peak)		
			alpha = math.clamp(alpha,0,1)
			alpha = 1 - alpha
			local wedgeColor = evalCS(terrainColorSequence,alpha)
			wedge.Color = wedgeColor

Which ends up like this

5 Likes

Thank you so much man, this is a perfect solution! :grin:

1 Like

NP, also be sure to read up this post for more math.noise knowledge and this website as well, where I also got the idea to change the range.

2 Likes

I just have a little question about eh evalCS function. How would I return the colour but also the name of it e.g. “darkGreen” or “whiteish”?

For that it’s quite difficult since the number can be between colors.

But one way is to round it like if alpha is equal to 0.5 it will be light green which is stored in a seperate table as an estimate.

1 Like