Suppose I have this local script that (supposedly) makes everything 4x bigger:
local function createZoom(scale)
return CFrame.new(
0, 0, 0,
scale, 0, 0,
0, scale, 0,
0, 0, 1)
end
game:GetService("RunService"):BindToRenderStep("ZoomOrtho", Enum.RenderPriority.Camera.Value + 1, function()
workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * createZoom(4)
end)
It does nothing, since for some reason the scale value doesn’t register in Roblox’s camera system above 1. When it’s a fractional value however, it works just fine:
The above script works, and makes everything 0.1x as large (10x smaller). It looks like the internal camera system Roblox uses has some sort of screen bounds testing in place - these modified CFrames also break when you scale down and try moving the view position until it intersects or escapes the screen bounds.
The camera’s CFrame is the view matrix, not the projection, so I’m not exactly sure what you mean by the screen bounds. As for why it works, the setter for Camera.CFrame does not try to orthonormalize the CFrame’s rotation matrix, it appears only to check elementwise if the values have absolute value less than 1.2. Why the limit is 1.2, I have no idea. A proper rotation matrix is normalized, so no element should have magnitude > 1. I honestly don’t know if this is a generous allowance for floating-point inexactness, or if there is something special about 1.2.
As for why it does what you see, that part is easy to explain. The matrix you set is used as-is, so the scale is incorporated into the view-projection matrix directly, scaling your view. You can give the camera any linear transformation of x, y, and z that you can express with a 3x3 matrix of values in the (-1.2,1.2) range, which includes rotations, shears, reflections, non-uniform scaling, and even projections that collapse the 3d view to a plane, line or the origin. If the determinant of the CFrame’s upper 3x3 is negative, you’ll also flip everything inside out (everything in the scene will appear like the normals have been flipped). The translation components of the CFrame are just the camera position, so that bit is straightforward and unexciting.