Help with camera Matrix?

This topic seems a little advanced, including for me. In a nutshell, I am making a camera shake that changes the matrix of the camera depending on the distance between the camera and a part. I’m not sure whether I change the math itself or another way to fix the issue.

The first issue I want to resolve is, I want the camera’s shake frequency/sine wave to transition from being normal to shaky depending on the distance. If the player is near out of range, the shake would be less intense, and vice versa if getting closer.

I am trying to remake this camera effect by UglyBurger0 but make it distance based. (If this helps, 0:15 timestamp)

local function Shake(strength, freq, dt)
	local R00_EQUATION = (math.abs(math.sin(tick() * (freq/strength) / dt)) + 4.5) / 5.5
	local MATRIX = CFrame.fromMatrix(
		Vector3.new(0, 0, 0), -- X, Y, Z
		Vector3.new(R00_EQUATION, 0, 0), -- r00, r10, r20
		Vector3.new(0, 1, 0), -- r01, r11, r21
		Vector3.new(0, 0, 1) -- r02, r12, r22
	)

	return MATRIX
end
       local alpha = 1 - (dist / 50)
       alpha = math.clamp(alpha, 0, 1)

       local strength = lerp(0, 1.25, alpha)
       local freq = lerp(1, math.clamp(5 + (10 - 5)*(dist/50), 1, 10), .3)

       Camera.CFrame = Camera.CFrame * Shake(strength, freq, dt)
    end
end)

If you found my explanation confusing, don’t be afraid to tell me what to re-explain.

Looks ok to me at first glance, is it behaving wrongly or are you just looking to have it shake depending on magnitude?

To make it shake depending on magnitude, you could do something like defining a maximum and minimum magnitude, then using inverse linear interpolation which would give you another alpha, by which you can use to interpolate your strength value. It seems like you may be doing something very similar though, which part aren’t you satisfied with?

Anyway, here’s what it might look like but it’s very similar to what you have right now:

local MINIMUM_MAGNITUDE = 5 -- distance from the target at which the maximum strength is obtained. we just clamp the strength
local MAXIMUM_MAGNITUDE = 50 -- "rolloff" distance; the distance at which the player will start to experience camera shaking

local function inverseLerp(a, b, x)
    -- instead of taking 2 numbers and an alpha and returning a value that is interpolated between a and b, inverseLerp takes 3 numbers and then returns an alpha
    return (x - a) / (b - a)
end

-- ...

-- now suppose vec1 is the character and vec2 is the target
local magnitudeFromTarget = (vec1 - vec2).Magnitude

-- now, we can plug the magnitudeFromTarget into inverseLerp to get our new alpha
local alpha = inverseLerp(magnitude, MAXIMUM_MAGNITUDE, MINIMUM_MAGNITUDE)
alpha = math.clamp(alpha, 0, 1) -- you don't really need to clamp this if you want to go above your maximum strength but just for the sake of consistency we can clamp it
-- now finally, we can plug in alpha to strength
local strength = lerp(0, 1.25, alpha)
-- now, pass strength to shake() and so on...

Sorry for taking long to respond. Besides that, this seems to do the opposite. Rather it stops when out of range, it shakes when out of range, and vice versa in range.

I fixed it:

local alpha = 1 - inverseLerp(0, 50, dist)

Switching min and max should make it work as well, oversight on my end sorry. I’ve edited my post

Forgot to ask because I accidentally took a nap, how can I make the shake less intense depending on the distance? Closer being intense, farther being light?

local function Shake(strength, dt)
	local R00_EQUATION = (math.abs(math.sin(tick() * (strength) / dt)) + 4.5) / 5.5
    ...
end

            local alpha = 1 - inverseLerp(10, 50, dist)
			alpha = math.clamp(alpha, 0, 1) -- you don't really need to clamp this if you want to go above your maximum strength but just for the sake of consistency we can clamp it
			-- now finally, we can plug in alpha to strength
			local strength = lerp(0, 1, alpha)
			print(strength)

			Camera.CFrame = Camera.CFrame * Shake(strength, dt) --dt = deltatime

It should be doing that already by multiplying strength by alpha which is obtained via magnitude (you don’t really need to use linear interpolation if your minimum number is 0 and max 1). Is it not working?

It works now, I found the fix earlier yesterday. Thanks for checking!

1 Like

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