If this is of any help, here is the code I use for my game:
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local GameSettings = UserSettings().GameSettings
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local LocalTorso = Character:WaitForChild('Torso')
local OceanModule = require(ReplicatedStorage.Modules.Ocean)
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Character, workspace.Rays, OceanModule.OceanFolder}
Params.FilterType = Enum.RaycastFilterType.Blacklist
local function Raycast(Point, Direction)
local Result = workspace:Raycast(Point, Direction, Params)
if Result and Result.Instance then
return Result
end
end
local function FibbonaciSphere(N, Len)
local RandomNum = math.random() * N
local Points = {}
local Offset = 2 / N
local Increment = math.pi * (3 - 5^0.5)
for Point = 1, N do
local Y = ((Point * Offset) - 1) + (Offset / 2)
local R = (1 - Y^2) ^ 0.5
local Phi = ((Point + RandomNum) % N) * Increment
local X = math.cos(Phi) * R
local Z = math.sin(Phi) * R
table.insert(Points, Vector3.new(X * Len, Y * Len, Z * Len))
end
return Points
end
local FibbDirections = FibbonaciSphere(1000, 100)
-- 0 = perfect reflection
-- 1 = absorbs all
local MaterialAbsorptionRates = {
Plastic = 0.2,
Grass = 0.7,
SmoothPlastic = 0.5,
Cobblestone = 0.65,
Concrete = 0.7,
Fabric = 0.7,
Wood = 0.5,
WoodPlanks = 0.5,
Brick = 0.7,
Sand = 0.8,
Ice = 0.3,
Metal = 0.4,
Marble = 0.2,
Granite = 0.2,
}
local ReverbEnabled = false
local EditingSounds = {}
local function InitSound(Sound)
--SoundSystem:Attach(Sound)
local ReverbFX = Instance.new('ReverbSoundEffect')
ReverbFX.DecayTime = 1.5
ReverbFX.Density = 0.4
ReverbFX.Diffusion = 1
ReverbFX.DryLevel = -2
ReverbFX.WetLevel = -10
ReverbFX.Enabled = ReverbEnabled
ReverbFX.Parent = Sound
table.insert(EditingSounds, {
Sound = Sound,
Object = Sound.Parent,
Reverb = ReverbFX
})
end
local NumDirections = #FibbDirections
local function RandomDirection()
return FibbDirections[math.random(1, NumDirections)]
end
local function CalculateReverb(Distance, RayDir, Normal, Absorption)
return (2*Distance)^-2 * RayDir:Dot(Normal) * ((1 - Absorption))
end
local function NestedRaycast(OriginCF, Direction, BounceAmount)
local OriginPos = OriginCF.Position
local InitHit = Raycast(OriginPos, Direction)
if not InitHit then
return 100, 0
end
local ReverbSum = 0
local InitNormal = InitHit.Normal
Direction = Direction - (2 * Direction:Dot(InitNormal) * InitNormal)
local AbsorptionMult = MaterialAbsorptionRates[InitHit.Material.Name] or 0.5
for Bounce = 1, BounceAmount - 1 do
local Hit = Raycast(OriginPos, Direction)
if Hit then
local HitPosition = Hit.Position
local Normal = Hit.Normal
AbsorptionMult *= 1 - (MaterialAbsorptionRates[Hit.Material.Name] or 0.5)
ReverbSum += CalculateReverb((HitPosition - OriginPos).Magnitude, Direction, Normal, AbsorptionMult)
-- r = d - (2 * d:Dot(n) * n)
Direction -= 2 * Direction:Dot(Normal) * Normal
else
return ReverbSum / Bounce --, (InitHit.Position - OriginPos).Magnitude
end
end
return ReverbSum / (BounceAmount - 1)--, (InitHit.Position - OriginPos).Magnitude
end
local NumRays = 10
local BounceNum = 4
local SoundSpeed = 20
local function InitChild(Obj)
if Obj:IsA('Sound') then
InitSound(Obj)
end
end
local function InitCharacter(PlayerCharacter)
local Torso = PlayerCharacter:WaitForChild('Torso')
for _, Obj in next, Torso:GetChildren() do
InitChild(Obj)
end
Torso.ChildAdded:Connect(InitChild)
end
InitCharacter(Character)
local function OnPlayerAdded(Player)
local Char = Player.Character
if Char then
InitCharacter(Player.Character)
end
Player.CharacterAdded:Connect(InitCharacter)
end
local function OnChildAdded(Spell)
wait(0.2)
for _, Obj in next, Spell:GetDescendants() do
InitChild(Obj)
end
end
workspace:WaitForChild('Spells', 15).ChildAdded:Connect(OnChildAdded)
workspace.VFX.ChildAdded:Connect(OnChildAdded)
for _, Player in next, Players:GetPlayers() do
if Player ~= LocalPlayer then
OnPlayerAdded(Player)
end
end
Players.PlayerAdded:Connect(OnPlayerAdded)
local Camera = workspace.CurrentCamera
local function ToggleAllSounds(Bool)
for Idx, Data in next, EditingSounds do
local Sound = Data.Sound
if not Sound:IsDescendantOf(workspace) then
table.remove(EditingSounds, Idx)
continue
else
Data.Reverb.Enabled = Bool
end
end
ReverbEnabled = Bool
end
RunService.Heartbeat:Connect(function()
debug.profilebegin('Reverb SFX')
local ShouldBeDisabled = GameSettings.SavedQualityLevel.Value <= 6
if ShouldBeDisabled then
if ReverbEnabled then
ToggleAllSounds(false)
end
elseif not ShouldBeDisabled then
if not ReverbEnabled then
ToggleAllSounds(true)
end
local CameraCF = Camera.CFrame
local CameraPos = CameraCF.Position
local PlayingSounds = {}
for Idx, Data in next, EditingSounds do
local Sound = Data.Sound
if not Sound:IsDescendantOf(workspace) then
table.remove(EditingSounds, Idx)
continue
end
if Sound.IsPlaying and (CameraPos - Data.Object.Position).Magnitude < Sound.RollOffMaxDistance then
table.insert(PlayingSounds, Data)
end
end
if #PlayingSounds == 0 then
return
end
local ReverbAvgSum = 0
local OriginCF = LocalTorso.CFrame
for _ = 1, NumRays do
ReverbAvgSum += NestedRaycast(OriginCF, RandomDirection(), BounceNum)
end
if ReverbAvgSum > 0 then
local AverageReverb = ReverbAvgSum / NumRays * BounceNum
for _, Data in next, PlayingSounds do
local Reverb = Data.Reverb
Reverb.WetLevel = math.min(AverageReverb * -0.2, -5)
Reverb.DecayTime = AverageReverb / SoundSpeed
end
end
end
debug.profileend()
end)
an issue with this is that it doesn’t properly average all the reverbs - the reverb can get very high if you have two walls close to yourself, which becomes an issue. Hopefully this still helps, though