internal void Dispatch() { if (useBoidsFlocking) { if (m_boidsFlock == null) { CreateBoids(); } m_boidsFlock.UpdateBoids(SystemComp.transform); } if (MaxForces == 0) { return; } if (m_forcesCount[0] > 0) { m_forcesBuffer[0].SetData(m_forcesStruct[0]); ComputeShader.SetBuffer(UpdateForcesKernel, SID._Forces, m_forcesBuffer[0]); Manager.BindPariclesToKernel(ComputeShader, UpdateForcesKernel); ComputeShader.Dispatch(UpdateForcesKernel, Manager.DispatchCount, m_forcesCount[0], 1); } if (m_forcesCount[1] > 0) { m_forcesBuffer[1].SetData(m_forcesStruct[1]); ComputeShader.SetBuffer(UpdateTurbulenceForcesKernel, SID._TurbulenceForces, m_forcesBuffer[1]); for (int k = 0; k < m_forcesCount[1]; ++k) { TCForce force = m_forcesReference[1][k]; if (force.CurrentForceVolume == null) { continue; } ComputeShader.SetTexture(UpdateTurbulenceForcesKernel, SID._TurbulenceTexture, force.CurrentForceVolume); Matrix4x4 rotation = Matrix4x4.TRS(Vector3.zero, force.transform.rotation, Vector3.one); TCHelper.SetMatrix(ComputeShader, SID._TurbulenceRotation, rotation); TCHelper.SetMatrix(ComputeShader, SID._TurbulenceRotationInv, rotation.inverse); //TODO: Just bind one force? ComputeShader.SetInt("turbulenceKernelOffset", k); Manager.BindPariclesToKernel(ComputeShader, UpdateTurbulenceForcesKernel); ComputeShader.Dispatch(UpdateTurbulenceForcesKernel, Manager.DispatchCount, 1, 1); } } }
void DistributeForces() { //easy fix for when forces get registered before system has initialized resources if (m_forcesBuffer == null || MaxForces == 0) { return; } if (m_forcesList == null) { m_forcesList = new List <TCForce>(32); } else { m_forcesList.Clear(); } for (int i = 0; i < Tracker <TCForce> .Count; i++) { TCForce f = Tracker <TCForce> .All[i]; if (ForceLayers == (ForceLayers | (1 << f.gameObject.layer))) { m_forcesList.Add(f); } } if (m_forcesList.Count > MaxForces) { if (m_forceSort == null) { m_forceSort = (f1, f2) => GetForcePoints(f2).CompareTo(GetForcePoints(f1)); } m_forcesList.Sort(m_forceSort); } //Update data for (int t = 0; t < ForceTypeKernelCount; ++t) { m_forcesCount[t] = 0; } for (int i = 0; i < Mathf.Min(MaxForces, m_forcesList.Count); i++) { TCForce f = m_forcesList[i]; int t = f.forceType == ForceType.Turbulence || f.forceType == ForceType.TurbulenceTexture ? 1 : 0; m_forcesReference[t][m_forcesCount[t]] = f; m_forcesCount[t]++; } }
void CreateBuffers() { if (MaxForces == 0) { return; } for (int t = 0; t < ForceTypeKernelCount; ++t) { if (m_forcesBuffer[t] != null) { m_forcesBuffer[t].Release(); } m_forcesBuffer[t] = new ComputeBuffer(MaxForces, ForcesStride); m_forcesStruct[t] = new Force[MaxForces]; m_forcesReference[t] = new TCForce[MaxForces]; } }
float GetForcePoints(TCForce force) { if (BaseForces != null && BaseForces.Contains(force)) { return(float.MaxValue); } if (!force.enabled) { return(float.MinValue); } if (force.transform.parent == SystemComp.transform) { return(float.MaxValue); } float projectedForce = force.power; float dist = (force.transform.position - SystemComp.transform.position).magnitude; switch (force.attenuationType) { case AttenuationType.Linear: case AttenuationType.EaseInOut: projectedForce = projectedForce * (1.0f - dist / force.radius.Max * force.Attenuation); break; case AttenuationType.Divide: projectedForce = Mathf.Lerp(projectedForce, projectedForce / dist, force.Attenuation); break; } var points = Mathf.Abs(projectedForce); return(points); }
protected override void Bind() { DistributeForces(); if (MaxForces == 0 || NumForcesTotal == 0) { return; } Transform systTransform = SystemComp.transform; Vector3 parentPosition = Vector3.zero; if (systTransform.parent != null) { parentPosition = systTransform.parent.position; } for (int t = 0; t < ForceTypeKernelCount; ++t) { for (int f = 0; f < m_forcesCount[t]; ++f) { Force curForce = m_forcesStruct[t][f]; TCForce force = m_forcesReference[t][f]; Transform forceTransform = force.transform; Vector3 forcePos = forceTransform.position; curForce.type = (uint)force.forceType; curForce.axisX = forceTransform.right; curForce.axisY = forceTransform.up; curForce.axisZ = forceTransform.forward; curForce.minRadius = -1.0f; curForce.attenuation = force.Attenuation; switch (force.shape) { case ForceShape.Sphere: curForce.radius = force.radius.Max; if (force.radius.IsConstant) { curForce.minRadius = -1.0f; } else { curForce.minRadius = force.radius.Min * force.radius.Min; } curForce.enclosingRadius = force.radius.Max; curForce.boxSize = Vector3.zero; curForce.vtype = 0; break; case ForceShape.Capsule: float xzScale = Mathf.Max(force.transform.localScale.x, force.transform.localScale.z); float axisHeight = force.height / 2.0f * force.transform.localScale.y - force.radius.Max * xzScale; axisHeight = Mathf.Max(0, axisHeight); curForce.boxSize = new Vector3(0.0f, axisHeight * force.transform.localScale.y, 0.0f); curForce.radius = force.radius.Max; curForce.enclosingRadius = curForce.radius + force.height / 2.0f * force.transform.localScale.y; curForce.vtype = 1; break; case ForceShape.Box: curForce.radius = 0.1f; curForce.boxSize = force.boxSize * 0.5f - new Vector3(0.1f, 0.1f, 0.1f); curForce.boxSize = Vector3.Scale(curForce.boxSize, forceTransform.localScale); curForce.enclosingRadius = Mathf.Max(force.boxSize.x, force.boxSize.y, force.boxSize.z) * 0.5f; curForce.vtype = 2; curForce.attenuation = 0; break; case ForceShape.Hemisphere: curForce.radius = 0.1f; curForce.boxSize = Vector3.Scale(new Vector3(force.radius.Max, force.radius.Max, force.radius.Max), force.transform.localScale); curForce.enclosingRadius = force.radius.Max; curForce.vtype = 3; break; case ForceShape.Disc: curForce.minRadius = -1.0f; curForce.vtype = (uint)force.discType; curForce.radius = Mathf.Max(0.1f, force.discRounding); float rMin = force.radius.IsConstant ? 0.0f : force.radius.Min; float rMax = force.radius.Max; curForce.boxSize = new Vector3(rMin, force.discHeight / 2.0f - force.discRounding, rMax); curForce.enclosingRadius = Mathf.Max(force.discHeight / 2.0f, force.radius.Max + force.discRounding); switch (force.discType) { case DiscType.Full: curForce.vtype = 4; break; case DiscType.Half: curForce.vtype = 5; break; case DiscType.Quarter: curForce.vtype = 6; break; } break; case ForceShape.Constant: curForce.radius = 0.1f; curForce.attenuation = 0.0f; curForce.enclosingRadius = -1.0f; curForce.vtype = 7; break; } curForce.force = force.power * Manager.ParticleTimeDelta; switch (force.forceType) { case ForceType.Vector: if (force.forceDirection != Vector3.zero) { if (force.forceDirectionSpace == TCForce.ForceSpace.World) { curForce.axis = Vector3.Normalize(force.forceDirection); } else { curForce.axis = force.transform.TransformDirection(Vector3.Normalize(force.forceDirection)); } } break; case ForceType.Vortex: curForce.axis = force.vortexAxis; curForce.inwardForce = force.inwardForce / 1000.0f * Manager.ParticleTimeDelta * 60.0f; break; case ForceType.Turbulence: case ForceType.TurbulenceTexture: curForce.axis = force.noiseExtents; break; default: curForce.axis = Vector3.zero; break; } if (force.IsPrimaryForce) { curForce.velocity = force.Velocity * force.InheritVelocity; } else { curForce.velocity = Vector3.zero; } curForce.attenType = (uint)force.attenuationType; curForce.turbulencePosFac = 1.0f - force.smoothness; curForce.pos = forcePos; switch (Manager.SimulationSpace) { case Space.Local: curForce.pos = systTransform.InverseTransformPoint(curForce.pos); curForce.axisX = systTransform.InverseTransformDirection(curForce.axisX); curForce.axisY = systTransform.InverseTransformDirection(curForce.axisY); curForce.axisZ = systTransform.InverseTransformDirection(curForce.axisZ); break; case Space.Parent: curForce.pos = forcePos - parentPosition; break; } m_forcesStruct[t][f] = curForce; } } }