Files
Fishing2/Assets/Obi/Scripts/Common/Backends/Compute/Rendering/RopeAndRod/ComputeChainRopeRenderSystem.cs
2026-01-22 22:08:21 +08:00

108 lines
4.4 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
using Unity.Profiling;
using System.Collections.Generic;
using Unity.Collections;
namespace Obi
{
public class ComputeChainRopeRenderSystem : ObiChainRopeRenderSystem
{
private ComputeShader ropeShader;
private int updateKernel;
private uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
public ComputeChainRopeRenderSystem(ObiSolver solver) : base(solver)
{
ropeShader = GameObject.Instantiate(Resources.Load<ComputeShader>("Compute/RopeChainRendering"));
updateKernel = ropeShader.FindKernel("UpdateChainMesh");
}
protected override void CloseBatches()
{
// Initialize each batch:
for (int i = 0; i < batchList.Count; ++i)
batchList[i].Initialize(true);
}
public override void Setup()
{
base.Setup();
rendererData.AsComputeBuffer<ChainRendererData>();
chunkData.AsComputeBuffer<ChunkData>();
modifiers.SafeAsComputeBuffer<ObiRopeChainRenderer.LinkModifier>();
elements.AsComputeBuffer<Vector2Int>();
instanceTransforms.AsComputeBuffer<Matrix4x4>();
invInstanceTransforms.AsComputeBuffer<Matrix4x4>();
instanceColors.AsComputeBuffer<Vector4>();
}
public override void Render()
{
using (m_RenderMarker.Auto())
{
var computeSolver = m_Solver.implementation as ComputeSolverImpl;
if (computeSolver.renderablePositionsBuffer != null && computeSolver.renderablePositionsBuffer.count > 0 && elements.count > 0)
{
ropeShader.SetBuffer(updateKernel, "rendererData", rendererData.computeBuffer);
ropeShader.SetBuffer(updateKernel, "chunksData", chunkData.computeBuffer);
ropeShader.SetBuffer(updateKernel, "modifiers", modifiers.computeBuffer);
ropeShader.SetBuffer(updateKernel, "elements", elements.computeBuffer);
ropeShader.SetBuffer(updateKernel, "renderablePositions", computeSolver.renderablePositionsBuffer);
ropeShader.SetBuffer(updateKernel, "renderableOrientations", computeSolver.renderableOrientationsBuffer);
ropeShader.SetBuffer(updateKernel, "principalRadii", computeSolver.renderableRadiiBuffer);
ropeShader.SetBuffer(updateKernel, "colors", computeSolver.colorsBuffer);
ropeShader.SetBuffer(updateKernel, "instanceTransforms", instanceTransforms.computeBuffer);
ropeShader.SetBuffer(updateKernel, "invInstanceTransforms", invInstanceTransforms.computeBuffer);
ropeShader.SetBuffer(updateKernel, "instanceColors", instanceColors.computeBuffer);
ropeShader.SetMatrix("solverToWorld", m_Solver.transform.localToWorldMatrix);
ropeShader.SetInt("chunkCount", chunkData.count);
int threadGroups = ComputeMath.ThreadGroupCount(chunkData.count, 32);
ropeShader.Dispatch(updateKernel, threadGroups, 1, 1);
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
mpb.SetBuffer("_InstanceTransforms", instanceTransforms.computeBuffer);
mpb.SetBuffer("_InvInstanceTransforms", invInstanceTransforms.computeBuffer);
mpb.SetBuffer("_Colors", instanceColors.computeBuffer);
for (int i = 0; i < batchList.Count; ++i)
{
var batch = batchList[i];
if (batch.mesh == null)
continue;
args[0] = (uint)batch.mesh.GetIndexCount(0);
args[1] = (uint)batch.instanceCount;
args[2] = (uint)batch.mesh.GetIndexStart(0);
args[3] = (uint)batch.mesh.GetBaseVertex(0);
args[4] = (uint)batch.firstInstance;
batch.argsBuffer.SetData(args);
var rp = batch.renderParams;
rp.material = batch.material;
rp.worldBounds = m_Solver.bounds;
rp.matProps = mpb;
Graphics.RenderMeshIndirect(rp, batch.mesh, batch.argsBuffer);
}
}
}
}
}
}