private bool GetComputeBufferData() { _HeightmapBuffer?.GetData(_Heightmap); _CaveNoiseBuffer?.GetData(_CaveNoise); _HeightmapBuffer?.Release(); _CaveNoiseBuffer?.Release(); return(true); }
private void OnGUI() { if (!terrainEdit) { terrainEdit = Resources.Load <ComputeShader>("TerrainEdit"); } terrainData = (MTerrainData)EditorGUILayout.ObjectField("Terrain Data", terrainData, typeof(MTerrainData), false); if (!terrainData) { return; } chunkPosition = EditorGUILayout.Vector2IntField("Chunk Position", new Vector2Int(chunkPosition.x, chunkPosition.y)); heightTexture = EditorGUILayout.ObjectField("Height Texture", heightTexture, typeof(Texture), false) as Texture; targetChunkCount = EditorGUILayout.IntField("Chunk Count", targetChunkCount); targetChunkCount = max(0, targetChunkCount); int largestChunkCount = (int)(pow(2.0, terrainData.GetLodOffset()) + 0.1); if (GUILayout.Button("Update Height Texture")) { VirtualTextureLoader loader = new VirtualTextureLoader( terrainData.heightmapPath, terrainEdit, largestChunkCount, MTerrain.MASK_RESOLUTION, true, null); RenderTexture cacheRt = new RenderTexture(new RenderTextureDescriptor { width = MTerrain.MASK_RESOLUTION, height = MTerrain.MASK_RESOLUTION, volumeDepth = 1, dimension = UnityEngine.Rendering.TextureDimension.Tex2DArray, msaaSamples = 1, graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat, enableRandomWrite = true }); cacheRt.Create(); int mipLevel = 0; int meshResolution = terrainData.GetMeshResolution(); int saveMipLevel = 0; ComputeBuffer cb = new ComputeBuffer(meshResolution * meshResolution, sizeof(float2)); float2[] resultArr = new float2[meshResolution * meshResolution]; RenderTexture mipRT = new RenderTexture(MTerrain.MASK_RESOLUTION, MTerrain.MASK_RESOLUTION, 0, UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32_SFloat, mipLevel); mipRT.enableRandomWrite = true; mipRT.useMipMap = true; mipRT.autoGenerateMips = false; mipRT.Create(); System.IO.FileStream fsm = new System.IO.FileStream(terrainData.boundPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); for (int i = MTerrain.MASK_RESOLUTION; i > 0; i /= 2) { mipLevel++; if (i <= meshResolution) { saveMipLevel++; } } MTerrainBoundingTree btree = new MTerrainBoundingTree(saveMipLevel); for (int x = 0; x < targetChunkCount; ++x) { for (int y = 0; y < targetChunkCount; ++y) { int2 pos = int2(x, y) + int2(chunkPosition.x, chunkPosition.y); if (pos.x >= largestChunkCount || pos.y >= largestChunkCount) { continue; } terrainEdit.SetTexture(6, ShaderIDs._SourceTex, heightTexture); terrainEdit.SetTexture(6, ShaderIDs._DestTex, cacheRt); terrainEdit.SetInt(ShaderIDs._Count, MTerrain.MASK_RESOLUTION); terrainEdit.SetInt(ShaderIDs._OffsetIndex, 0); terrainEdit.SetVector("_ScaleOffset", float4(float2(1.0 / targetChunkCount), float2(x, y) / targetChunkCount)); const int disp = MTerrain.MASK_RESOLUTION / 16; terrainEdit.Dispatch(6, disp, disp, 1); loader.WriteToDisk(cacheRt, 0, pos); for (int i = 0, res = MTerrain.MASK_RESOLUTION; i < mipLevel; ++i, res /= 2) { int pass; if (i == 0) { pass = 7; terrainEdit.SetTexture(pass, "_SourceArray", cacheRt); terrainEdit.SetTexture(pass, "_Mip1", mipRT); } else { if (res <= meshResolution) { pass = 9; terrainEdit.SetBuffer(pass, "_DataBuffer", cb); } else { pass = 8; } terrainEdit.SetTexture(pass, "_Mip0", mipRT, i - 1); terrainEdit.SetTexture(pass, "_Mip1", mipRT, i); } terrainEdit.SetInt(ShaderIDs._Count, res); int mipdisp = Mathf.CeilToInt(res / 16f); terrainEdit.Dispatch(pass, mipdisp, mipdisp, 1); if (pass == 9) { cb.GetData(resultArr, 0, 0, res * res); int targetMipLevel = mipLevel - 1 - i; for (int xx = 0; xx < res * res; ++xx) { btree[xx, targetMipLevel] = resultArr[xx]; } } } btree.WriteToDisk(fsm, x + y * largestChunkCount); } } btree.Dispose(); cacheRt.Release(); cb.Dispose(); mipRT.Release(); loader.Dispose(); fsm.Dispose(); Debug.Log("Finish!"); } maskTexture = EditorGUILayout.ObjectField("Mask Texture", maskTexture, typeof(Texture), false) as Texture; void SaveToMask(RenderTexture cacheRt) { VirtualTextureLoader loader = new VirtualTextureLoader( terrainData.maskmapPath, terrainEdit, largestChunkCount, MTerrain.MASK_RESOLUTION, false, null); for (int x = 0; x < targetChunkCount; ++x) { for (int y = 0; y < targetChunkCount; ++y) { int2 pos = int2(x, y) + int2(chunkPosition.x, chunkPosition.y); if (pos.x >= largestChunkCount || pos.y >= largestChunkCount) { continue; } terrainEdit.SetTexture(6, ShaderIDs._SourceTex, maskTexture); terrainEdit.SetTexture(6, ShaderIDs._DestTex, cacheRt); terrainEdit.SetInt(ShaderIDs._Count, MTerrain.MASK_RESOLUTION); terrainEdit.SetInt(ShaderIDs._OffsetIndex, 0); terrainEdit.SetVector("_ScaleOffset", float4(float2(1.0 / targetChunkCount), float2(x, y) / targetChunkCount)); const int disp = MTerrain.MASK_RESOLUTION / 16; terrainEdit.Dispatch(6, disp, disp, 1); loader.WriteToDisk(cacheRt, 0, pos); } } loader.Dispose(); } if (GUILayout.Button("Update Mask Texture")) { RenderTexture cacheRt = new RenderTexture(new RenderTextureDescriptor { width = MTerrain.MASK_RESOLUTION, height = MTerrain.MASK_RESOLUTION, volumeDepth = 1, dimension = UnityEngine.Rendering.TextureDimension.Tex2DArray, msaaSamples = 1, graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat, enableRandomWrite = true }); cacheRt.Create(); SaveToMask(cacheRt); cacheRt.Release(); } }
private void SolveBoundaries(ComputeBuffer vBuffer, ComputeBuffer pBuffer, ComputeBuffer dBuffer) { vBuffer.GetData(velocityFieldBuffer); pBuffer.GetData(pressureFieldBuffer); if (dBuffer != null) { dBuffer.GetData(dyeFieldBuffer); } for (uint i = 0; i < particleWidth; ++i) { for (uint j = 0; j < particleWidth; ++j) { uint id = i * particleWidth + j; if (i == 0) { // bottom velocityFieldBuffer[id] = -velocityFieldBuffer[(i + 1) * particleWidth + (j + 1)]; pressureFieldBuffer[id] = pressureFieldBuffer[(i + 1) * particleWidth + (j)]; if (dBuffer != null) { dyeFieldBuffer[id] = 0.0f; } } else if (i == particleWidth - 1) { // top velocityFieldBuffer[id] = -velocityFieldBuffer[(i - 1) * particleWidth + (j)]; pressureFieldBuffer[id] = pressureFieldBuffer[(i - 1) * particleWidth + (j)]; if (dBuffer != null) { dyeFieldBuffer[id] = 0.0f; } } else if (j == 0) { // left velocityFieldBuffer[id] = -velocityFieldBuffer[(i) * particleWidth + (j + 1)]; pressureFieldBuffer[id] = pressureFieldBuffer[(i) * particleWidth + (j + 1)]; if (dBuffer != null) { dyeFieldBuffer[id] = 0.0f; } } else if (j == particleWidth - 1) { // right velocityFieldBuffer[id] = -velocityFieldBuffer[(i) * particleWidth + (j - 1)]; pressureFieldBuffer[id] = pressureFieldBuffer[(i) * particleWidth + (j - 1)]; if (dBuffer != null) { dyeFieldBuffer[id] = 0.0f; } } } } vBuffer.SetData(velocityFieldBuffer); pBuffer.SetData(pressureFieldBuffer); if (dBuffer != null) { dBuffer.SetData(dyeFieldBuffer); } }
protected override void Compute() { const string method = nameof(Compute); logger.Log(Logger.EventType.Method, $"{Context(method)}: started."); //SetStatusMessage($"Step 3/{(writeFactors ? 4 : 3)}: Computing absorption factors..."); // initialize parameters in shader. stopwatch.Record(Category.Shader, SetShaderConstants); logger.Log(Logger.EventType.Step, $"{Context(method)}: Set shader parameters."); stopwatch.Start(Category.Shader); // get kernel handles. var handlePart1 = shader.FindKernel("get_dists_part1"); var handlePart2 = shader.FindKernel("get_dists_part2"); var handleAbsorptions = shader.FindKernel("get_absorptions"); stopwatch.Stop(Category.Shader); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Retrieved kernel handles."); // make buffers. stopwatch.Start(Category.Buffer); var outputBufferCellPart1 = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var outputBufferSamplePart1 = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var outputBufferCellPart2 = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var outputBufferSamplePart2 = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var absorptionsBuffer = new ComputeBuffer(coordinates.Length, sizeof(float) * 3); logger.Log(Logger.EventType.Data, $"{Context(method)}: Created buffers."); // set buffers for part1 kernel. shader.SetBuffer(handlePart1, "coordinates", _inputBuffer); shader.SetBuffer(handlePart1, "distances_sample_part1", outputBufferSamplePart1); shader.SetBuffer(handlePart1, "distances_cell_part1", outputBufferCellPart1); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Wrote data to buffers."); _inputBuffer.SetData(coordinates); stopwatch.Stop(Category.Buffer); // compute part1 distances. logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: part1 distances kernel dispatch."); stopwatch.Record(Category.Shader, () => shader.Dispatch(handlePart1, threadGroupsX, 1, 1)); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: part1 distances kernel return."); stopwatch.Record(Category.Buffer, () => { // set buffers for part2 kernel. shader.SetBuffer(handlePart2, "coordinates", _inputBuffer); shader.SetBuffer(handlePart2, "distances_sample_part2", outputBufferSamplePart2); shader.SetBuffer(handlePart2, "distances_cell_part2", outputBufferCellPart2); // set shared buffers for absorption factor kernel. shader.SetBuffer(handleAbsorptions, "coordinates", _inputBuffer); shader.SetBuffer(handleAbsorptions, "distances_sample_part1", outputBufferSamplePart1); shader.SetBuffer(handleAbsorptions, "distances_cell_part1", outputBufferCellPart1); shader.SetBuffer(handleAbsorptions, "absorptions", absorptionsBuffer); shader.SetBuffer(handleAbsorptions, "indicator_mask", _maskBuffer); }); var absorptionsTemp = new Vector3[coordinates.Length]; Array.Clear(absorptionsTemp, 0, absorptionsTemp.Length); stopwatch.Record(Category.Buffer, () => absorptionsBuffer.SetData(absorptionsTemp)); for (int j = 0; j < _nrAnglesTheta; j++) { // set rotation parameters. var j1 = j; stopwatch.Record(Category.Buffer, () => shader.SetFloats("rot", (float)Math.Cos(Math.PI - GetThetaAt(j1)), (float)Math.Sin(Math.PI - GetThetaAt(j1))) ); // compute part2 distances. stopwatch.Record(Category.Shader, () => shader.Dispatch(handlePart2, threadGroupsX, 1, 1)); // set iterative buffers for absorption factors kernel. stopwatch.Record(Category.Buffer, () => { shader.SetBuffer(handleAbsorptions, "distances_sample_part2", outputBufferSamplePart2); shader.SetBuffer(handleAbsorptions, "distances_cell_part2", outputBufferCellPart2); }); for (int i = 0; i < _nrAnglesAlpha; i++) { var v = GetDistanceVector(i, j); var stretchFactor = GetStretchFactor(v); stopwatch.Record(Category.Buffer, () => shader.SetFloat("stretch_factor", stretchFactor)); stopwatch.Record(Category.Shader, () => shader.Dispatch(handleAbsorptions, threadGroupsX, 1, 1)); stopwatch.Record(Category.Buffer, () => absorptionsBuffer.GetData(absorptionsTemp)); _absorptionFactors[i, j] = GetAbsorptionFactor(absorptionsTemp); } } logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Calculated all absorptions."); // release buffers. stopwatch.Record(Category.Buffer, () => { _inputBuffer.Release(); _maskBuffer.Release(); outputBufferCellPart1.Release(); outputBufferSamplePart1.Release(); outputBufferCellPart2.Release(); outputBufferSamplePart2.Release(); absorptionsBuffer.Release(); }); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Shader buffers released."); logger.Log(Logger.EventType.Method, $"{Context(method)}: done."); }
public void Emulate( int stateCount, int spaceSize, int timeSize, int randSeed, Rule[] rules, bool inPlace ) { Debug.Assert(rules[0].tablePackN == tablePackN); var packer = rules[0].packer; var spaceSizePacked = packer.GetPackedSize(spaceSize); var timestepsPerCall = (timeSize - Rule.timeNeighbourhoodRadius); if (usePackedPacked) { var packedRule = new PackedSpace( new Packer(4 * 4), rules[0].tablePackedNCell.Length); ComputeShaderEx.EnsureBuffer( ref ruleTablePackedNCellBuffer, rules.Length * packedRule.packed.Length, sizeof(int)); for (var i = 0; i < rules.Length; i++) { var rule = rules[i]; for (var j = 0; j < rule.tablePackedNCell.Length; j++) { packedRule[j] = rule.tablePackedNCell[j]; } ruleTablePackedNCellBuffer.SetData( packedRule.packed, 0, i * packedRule.packed.Length, packedRule.packed.Length); } } else { ComputeShaderEx.EnsureBuffer( ref ruleTablePackedNCellBuffer, rules.Length * rules[0].tablePackedNCell.Length, sizeof(int)); for (var i = 0; i < rules.Length; i++) { var rule = rules[i]; ruleTablePackedNCellBuffer.SetData( rule.tablePackedNCell, 0, i * rule.tablePackedNCell.Length, rule.tablePackedNCell.Length); } } var spacetimePackedBufferSize = rules.Length * spaceSizePacked * (inPlace ? 2 : timeSize); ComputeShaderEx.EnsureBuffer( ref spacetimePackedBuffer, spacetimePackedBufferSize, sizeof(int)); ComputeShaderEx.EnsureBuffer( ref flagBuffer, 1, sizeof(int)); shader.Set("_RandSeed", randSeed); shader.Set("_SpaceSize", spaceSize); shader.Set("_TimeSize", inPlace ? 2 : timeSize); shader.Set("_TimeTo", timeSize); var fillStartRandomKernel = this.fillStartRandomKernel; fillStartRandomKernel.SetBuffer( "_SpacetimePacked", spacetimePackedBuffer); fillStartRandomKernel.Dispatch(spaceSizePacked, rules.Length); var emulateKernelName = "CSEmulate"; var emulateKernel = new ShaderKernel(shader, emulateKernelName); emulateKernel.Set( "_SpacetimePacked", spacetimePackedBuffer); emulateKernel.Set( "_Flag", flagBuffer); emulateKernel.Set( "_RuleTablePackedNCell", ruleTablePackedNCellBuffer); var tnr = Rule.timeNeighbourhoodRadius; for (var t = tnr; t < timeSize; t += timestepsPerCall) { shader.SetInt("_TimeStep", t); emulateKernel.Dispatch( spaceSizePacked, rules.Length); } var data = new int[1]; flagBuffer.GetData(data); }
void Update() { if (!m_CS) { return; } if (!m_Shader) { return; } var sourceTex = m_Source.texture; if (!sourceTex) { return; } if (!m_RT) { m_KernelCopy = m_CS.FindKernel("CSCopy"); m_KernelMutate = m_CS.FindKernel("CSMutate"); m_KernelScore = m_CS.FindKernel("CSCalcScore"); uint dummyY, dummyZ; m_CS.GetKernelThreadGroupSizes(m_KernelCopy, out m_GroupsizeCopy, out dummyY, out dummyZ); m_CS.GetKernelThreadGroupSizes(m_KernelScore, out m_GroupsizeScoreX, out m_GroupsizeScoreY, out dummyZ); var desc = new RenderTextureDescriptor { width = sourceTex.width, height = sourceTex.height, dimension = TextureDimension.Tex2D, volumeDepth = 1, msaaSamples = 1, enableRandomWrite = true }; m_RT = new RenderTexture(desc); m_RT.Create(); m_DestImage.texture = m_RT; m_RTBest = new RenderTexture(desc); m_RTBest.Create(); m_BestImage.texture = m_RTBest; m_CS.SetTexture(m_KernelScore, "_SourceTex", sourceTex); m_CS.SetTexture(m_KernelScore, "_DestTex", m_RT); m_Log = $"{sourceTex.name} tris: {m_Triangles}\n"; } if (m_DNA == null) { m_DNA = new ComputeBuffer(m_Triangles * 2, Marshal.SizeOf(typeof(Triangle))); var initData = new Triangle[m_Triangles * 2]; Random.InitState(1); for (var i = 0; i < m_Triangles; ++i) { initData[i].posA = new Vector2(Random.value, Random.value); initData[i].posB = new Vector2(Random.value, Random.value); initData[i].posC = new Vector2(Random.value, Random.value); initData[i].col = new Color(Random.value, Random.value, Random.value, Random.value); initData[i + m_Triangles] = initData[i]; } m_DNA.SetData(initData); m_CS.SetBuffer(m_KernelCopy, "_DNA", m_DNA); m_CS.SetBuffer(m_KernelMutate, "_DNA", m_DNA); } if (m_Params == null) { m_Params = new ComputeBuffer(1, Marshal.SizeOf(typeof(Params))); var para = new Params[1]; para[0].triCount = m_Triangles; para[0].width = sourceTex.width; para[0].height = sourceTex.height; m_Params.SetData(para); m_CS.SetBuffer(m_KernelCopy, "_Params", m_Params); m_CS.SetBuffer(m_KernelMutate, "_Params", m_Params); m_CS.SetBuffer(m_KernelScore, "_Params", m_Params); } var sc = new Score[1]; if (m_Score == null) { m_Score = new ComputeBuffer(1, Marshal.SizeOf(typeof(Score))); sc[0].score = 0xFFFFFFFF; sc[0].bestScore = 0xFFFFFFFF; sc[0].iterations = 0; sc[0].improvements = 0; sc[0].rng = 1; m_Score.SetData(sc); m_CS.SetBuffer(m_KernelCopy, "_Score", m_Score); m_CS.SetBuffer(m_KernelMutate, "_Score", m_Score); m_CS.SetBuffer(m_KernelScore, "_Score", m_Score); } if (!m_Material) { m_Material = new Material(m_Shader); m_Material.SetBuffer("_DNA", m_DNA); } for (var it = 0; it < m_IterationsPerUpdate; ++it) { m_CS.Dispatch(m_KernelCopy, (m_Triangles + (int)m_GroupsizeCopy - 1) / (int)m_GroupsizeCopy, 1, 1); m_CS.Dispatch(m_KernelMutate, 1, 1, 1); Graphics.SetRenderTarget(m_RT); GL.Clear(false, true, Color.white); m_Material.SetInt("_StartVertex", 0); m_Material.SetPass(0); Graphics.DrawProcedural(MeshTopology.Triangles, m_Triangles * 3); m_CS.Dispatch(m_KernelScore, (sourceTex.width + (int)m_GroupsizeScoreX - 1) / (int)m_GroupsizeScoreX, (sourceTex.height + (int)m_GroupsizeScoreY - 1) / (int)m_GroupsizeScoreY, 1); } m_Score.GetData(sc); var fitness = (1.0 - sc[0].bestScore / (double)(sourceTex.width * sourceTex.height * 3 * 255)) * 100.0; var time = Time.realtimeSinceStartup; m_Text.text = $"fit {fitness:F3}% time {time:F2}s\niter {sc[0].iterations} impr {sc[0].improvements}\n{m_Log}"; var ifitness = (int)fitness; if (ifitness > m_GotFitness) { m_Log += $"got {fitness:F3}% at time {time:F2}, iters {sc[0].iterations}\n"; m_GotFitness = ifitness; Debug.Log(m_Log); } Graphics.SetRenderTarget(m_RTBest); GL.Clear(false, true, Color.white); m_Material.SetInt("_StartVertex", m_Triangles * 3); m_Material.SetPass(0); Graphics.DrawProcedural(MeshTopology.Triangles, m_Triangles * 3); }
//Membuat titik sampel beserta nilai density-nya //Creates sample points along its density value public void GenerateDensity() { Debug.ClearDeveloperConsole(); totalTimeElapsed = 0; timeDuration = 0; timeStart = 0; generatedMeshCount = numberOfGeneratedMeshObject.x * numberOfGeneratedMeshObject.y * numberOfGeneratedMeshObject.z; InitGeneratedMesh(); Vector3 offset = Vector3.zero; int index; //Buffer for sample points. Value for second parameter is based on Vector4 size in byte _pointsBuffer = new ComputeBuffer(_voxel.totalVertex, 16); //Buffer for line data. Value for second parameter is based on LineProperties struct's size in byte _linePropBuffer = new ComputeBuffer(_lineGenerator.line.Count, 52); //Buffer for line's node data. Value for second parameter is based on NodeProperties struct's size in byte _nodePositionBuffer = new ComputeBuffer(_lineGenerator.node.Count, 20); numThreadGroup.x = Mathf.CeilToInt(_voxel.numVertex.x / numThreads) + 1; numThreadGroup.y = Mathf.CeilToInt(_voxel.numVertex.y / numThreads) + 1; numThreadGroup.z = Mathf.CeilToInt(_voxel.numVertex.z / numThreads) + 1; for (int k = 0; k < numberOfGeneratedMeshObject.z; k++) { for (int j = 0; j < numberOfGeneratedMeshObject.y; j++) { for (int i = 0; i < numberOfGeneratedMeshObject.x; i++) { timeStart = (float)System.DateTime.Now.Second + ((float)System.DateTime.Now.Millisecond / 1000); offset.x = i * _voxel.boundaryWorldPos.x; offset.y = j * _voxel.boundaryWorldPos.y; offset.z = k * _voxel.boundaryWorldPos.z; index = i + (k * numberOfGeneratedMeshObject.x) + (j * (numberOfGeneratedMeshObject.x * numberOfGeneratedMeshObject.z)); SetGeneralInputs(_densityShader); _linePropBuffer.SetData(_lineGenerator.GetLineProps()); _nodePositionBuffer.SetData(_lineGenerator.GetNodes()); _densityShader.SetBuffer(0, "nodeProps", _nodePositionBuffer); _densityShader.SetBuffer(0, "lineProps", _linePropBuffer); _densityShader.SetBool("isWorldSpaceNoise", isWorldSpaceNoise); _densityShader.SetFloat("noiseIntensity", noiseIntensity); _densityShader.SetFloat("noiseScale", noiseScale); _densityShader.SetFloat("smoothingFactor", smoothingFactor); _densityShader.SetVector("offset", offset); _densityShader.Dispatch(0, numThreadGroup.x, numThreadGroup.y, numThreadGroup.z); //_densityShader.Dispatch(0,_voxel.numVoxel.x+1,_voxel.numVoxel.y+1,_voxel.numVoxel.z+1); _pointsDensity = new Vector4[_voxel.totalVertex]; _pointsBuffer.GetData(_pointsDensity); //generatedMeshObjectsHolder.transform.GetChild(index).GetComponent<GeneratedMeshProperties>().Initiate(); GenerateMesh(index); } } } //Debug.Log("Total time elapsed: "+ totalTimeElapsed); if (showGeneratedVertexInfo) { ShowVoidVertex(); } ReleaseBuffers(); }
private void Update() { // TODO: do this on the GPU or figure out way to keep everything in local coor on the GPU (by setting external and collisions to local) // modify data to world coordinates for (int i = 0; i < numParticles; i++) { positions[i] = transform.TransformPoint(positions[i]); velocities[i] = transform.TransformVector(velocities[i]); } positionsBuffer.SetData(positions); velocitiesBuffer.SetData(velocities); PBDClothSolver.SetVector("gravity", gravity); PBDClothSolver.SetFloat("invMass", invMass); PBDClothSolver.SetFloat("stretchStiffness", distanceStretchStiffness); PBDClothSolver.SetFloat("compressionStiffness", distanceCompressionStiffness); PBDClothSolver.SetFloat("bendingStiffness", bendingStiffness); // calculate the timestep nextFrameTime += Time.deltaTime; int iter = 0; while (nextFrameTime > 0) { if (nextFrameTime < timestep) { break; } float dt = Mathf.Min(nextFrameTime, timestep); nextFrameTime -= dt; iter++; // send the dt data to the GPU PBDClothSolver.SetFloat("dt", dt); // step 5: apply external forces PBDClothSolver.Dispatch(applyExternalForcesKernel, numGroups_Vertices, 1, 1); // step 6: damp velocity if (dampingMethod != DampingMethod.noDamping) { PBDClothSolver.Dispatch(dampVelocitiesKernel, numGroups_Vertices, 1, 1); } // step 7: apply explicit Euler to positions based on velocity PBDClothSolver.Dispatch(applyExplicitEulerKernel, numGroups_Vertices, 1, 1); // step 8: clear current collisions and generate new collisions SetupCollisionComputeBuffers(); // step 9-11: project constraints iterationNum times for (int j = 0; j < iterationNum; j++) { // TODO: maybe shuffle here // distance constraints PBDClothSolver.Dispatch(projectConstraintDeltasKernel, numGroups_AllConstraints, 1, 1); PBDClothSolver.Dispatch(averageConstraintDeltasKernel, numGroups_Vertices, 1, 1); // collision constraints if (numCollidableSpheres > 0) { PBDClothSolver.Dispatch(satisfySphereCollisionsKernel, numGroups_Vertices, 1, 1); } if (numCollidableCubes > 0) { PBDClothSolver.Dispatch(satisfyCubeCollisionsKernel, numGroups_Vertices, 1, 1); } } // satisfy pointConstraints if (numPointConstraints > 0) { if (enableMouseInteraction && tempPointConstraint != -1) { PBDClothSolver.SetBool("hasTempPointConstraint", true); PBDClothSolver.SetVector("deltaPointConstraint", deltaPointConstraint); PBDClothSolver.SetInt("tempPointConstraint", tempPointConstraint); } else { PBDClothSolver.SetBool("hasTempPointConstraint", false); PBDClothSolver.SetInt("tempPointConstraint", -1); } PBDClothSolver.Dispatch(satisfyPointConstraintsKernel, numGroups_PointConstraints, 1, 1); } // step 13 & 14: apply projected positions to actual vertices PBDClothSolver.Dispatch(updatePositionsKernel, numGroups_Vertices, 1, 1); // step 16: update all velocities using friction //ApplyFriction(); } // handle mouse drag inputs if (enableMouseInteraction) { if (Input.GetMouseButtonDown(0) && tempPointConstraint == -1) { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (GetComponent <MeshCollider>().Raycast(ray, out hit, float.MaxValue)) { int vertex = triangles[hit.triangleIndex].vertices[0]; tempPointConstraint = vertex; lastMousePos = Input.mousePosition; deltaPointConstraint = Vector3.zero; } else if (GetComponentInChildren <MeshCollider>().Raycast(ray, out hit, float.MaxValue)) { int vertex = triangles[hit.triangleIndex].vertices[0]; tempPointConstraint = vertex; lastMousePos = Input.mousePosition; deltaPointConstraint = Vector3.zero; } } else if (Input.GetMouseButtonUp(0)) { tempPointConstraint = -1; } else if (tempPointConstraint != -1) { deltaPointConstraint = Input.mousePosition - lastMousePos; deltaPointConstraint *= 0.001f; deltaPointConstraint.x *= -1; lastMousePos = Input.mousePosition; if (Input.GetKey(KeyCode.I)) { deltaPointConstraint.z -= 0.01f; } if (Input.GetKey(KeyCode.K)) { deltaPointConstraint.z += 0.01f; } if (Input.GetKey(KeyCode.J)) { deltaPointConstraint.x += 0.01f; } if (Input.GetKey(KeyCode.L)) { deltaPointConstraint.x -= 0.01f; } if (Input.GetKey(KeyCode.U)) { deltaPointConstraint.y += 0.01f; } if (Input.GetKey(KeyCode.O)) { deltaPointConstraint.y -= 0.01f; } } } // get data from GPU back to CPU positionsBuffer.GetData(positions); velocitiesBuffer.GetData(velocities); // recalculate the center of the mesh Vector3 newCenter = Vector3.zero; Vector3 delta = Vector3.zero; if (pointConstraintType == PointConstraintType.none) { newCenter = GetComponentInChildren <Renderer>().bounds.center; delta = newCenter - transform.position; } // modify data to back to local coordinates for (int i = 0; i < numParticles; i++) { positions[i] = transform.InverseTransformPoint(positions[i] - delta); velocities[i] = transform.InverseTransformVector(velocities[i]); } if (pointConstraintType == PointConstraintType.none) { transform.position = newCenter; } // update everything into Unity mesh.vertices = positions; mesh.RecalculateNormals(); mesh.RecalculateBounds(); reverseMesh.vertices = positions; Vector3[] reverseNormals = mesh.normals; for (int i = 0; i < reverseNormals.Length; i++) { reverseNormals[i] *= -1; } reverseMesh.normals = reverseNormals; GetComponent <MeshCollider>().sharedMesh = mesh; GetComponentInChildren <MeshCollider>().sharedMesh = reverseMesh; }
/// <summary> /// Batch update. Reconstruct all meshes needed by running GPU based Marching Cubes /// </summary> public void BatchUpdate() { for (int x = 0; x < width / blockSize; x++) { for (int y = 0; y < height / blockSize; y++) { for (int z = 0; z < length / blockSize; z++) { if (_blocks[x, y, z] == null) { continue; } if (_blocks[x, y, z].GetComponent <MeshFilter>().mesh != null) { _blocks[x, y, z].GetComponent <MeshFilter>().mesh.Clear(); } //if (_blocks[x, y, z].GetComponent<MeshCollider>().sharedMesh != null) // _blocks[x, y, z].GetComponent<MeshCollider>().sharedMesh.Clear(); } } } shaderSample.SetBuffer(_kernelCollectSurfaceBlock, "_Particles", sphSolver._bufferParticles); _bufferSufaceBlocks.SetData(_surfaceBlocksInit); shaderSample.SetBuffer(_kernelCollectSurfaceBlock, "_SurfaceMCBlocks", _bufferSufaceBlocks); shaderSample.Dispatch(_kernelCollectSurfaceBlock, sphSolver._sphthreadGroupNum, 1, 1); _bufferSufaceBlocks.GetData(_surfaceBlocksContainer); _nextUpdateblocks.Clear(); for (int i = 0; i < _surfaceBlocksContainer.Length; ++i) { if (_surfaceBlocksContainer[i] == 1) { int x = i / (blockDimY * blockDimZ); int y = (i - x * (blockDimY * blockDimZ)) / blockDimZ; int z = i - x * (blockDimY * blockDimZ) - y * blockDimZ; _nextUpdateblocks.Add(new Int3(x, y, z)); } } //for (int x = 0; x < blockDimX; ++x) // for (int y = 0; y < blockDimY; ++y) // for (int z = 0; z < blockDimZ; ++z) // _nextUpdateblocks.Add(new Int3(x, y, z)); if (_nextUpdateblocks.Count == 0) { return; } //GPU sampling ComputeBuffer bufferBlocks = new ComputeBuffer(_nextUpdateblocks.Count, sizeof(int) * 3); bufferBlocks.SetData(_nextUpdateblocks.ToArray()); //List<CSParticle> particlesCopy = new List<CSParticle>(); //int[] particlesStartIdx = new int[sphSolver.gridCountXYZ + 1]; //int startIdx = 0; //for (int x = 0; x < sphSolver.gridSize._x; ++x) // for (int y = 0; y < sphSolver.gridSize._y; ++y) // for (int z = 0; z < sphSolver.gridSize._z; ++z) // { // int idx = x * sphSolver.gridCountYZ + y * sphSolver.gridSize._z + z; // foreach (var particle in sphSolver.grid[idx].particles) // { // particlesCopy.Add(new CSParticle((float)particle.mass, 1f / (float)particle.density, // new Vector3((float)particle.position.x, (float)particle.position.y, (float)particle.position.z))); // } // particlesStartIdx[idx] = startIdx; // startIdx += sphSolver.grid[idx].particles.Count; // } //particlesStartIdx[particlesStartIdx.Length - 1] = sphSolver.currParticleNum; //_bufferParticlesStartIndex.SetData(particlesStartIdx); //_bufferParticles.SetData(particlesCopy.ToArray()); ComputeBuffer bufferSamples = new ComputeBuffer(_nextUpdateblocks.Count * (ag1BlockSize) * (ag1BlockSize) * (ag1BlockSize), sizeof(float)); ComputeBuffer bufferNormals = new ComputeBuffer(_nextUpdateblocks.Count * (ag1BlockSize) * (ag1BlockSize) * (ag1BlockSize), sizeof(float) * 3); shaderSample.SetBuffer(sampleKernel, "_Blocks", bufferBlocks); shaderSample.SetBuffer(sampleKernel, "_ParticleCellNumPrefixSum", sphSolver._bufferParticleNumPerCell); shaderSample.SetBuffer(sampleKernel, "_Particles", sphSolver._bufferParticles); shaderSample.SetBuffer(sampleKernel, "_Samples", bufferSamples); shaderSample.SetBuffer(sampleKernel, "_Normals", bufferNormals); shaderSample.Dispatch(sampleKernel, _nextUpdateblocks.Count, 1, 1); bufferBlocks.Release(); bufferBlocks = null; //marching-cube //STAGE I: collect triangle number ComputeBuffer bufferTriNum = new ComputeBuffer(1, sizeof(int)); bufferTriNum.SetData(new int[] { 0 }); ComputeBuffer bufferCornerFlags = new ComputeBuffer(_nextUpdateblocks.Count * blockSize * blockSize * blockSize, sizeof(int)); shaderCollectTriNum.SetBuffer(ctnKernel, "_Samples", bufferSamples); shaderCollectTriNum.SetBuffer(ctnKernel, "_CornerToTriNumTable", _bufferCornerToTriNumTable); shaderCollectTriNum.SetBuffer(ctnKernel, "_TriNum", bufferTriNum); shaderCollectTriNum.SetBuffer(ctnKernel, "_CornerFlags", bufferCornerFlags); shaderCollectTriNum.Dispatch(ctnKernel, _nextUpdateblocks.Count, 1, 1); int[] triNum = new int[1]; bufferTriNum.GetData(triNum); if (triNum[0] == 0) { //no triangles, early exit bufferNormals.Release(); bufferSamples.Release(); bufferTriNum.Release(); bufferCornerFlags.Release(); return; } //#if UNITY_EDITOR // //Debug.Log("triangles count " + triNum[0]); //#endif //STAGE II: do marching cube ComputeBuffer bufferMeshes = new ComputeBuffer(triNum[0], CSTriangle.stride); ComputeBuffer bufferTriEndIndex = new ComputeBuffer(1, sizeof(int)); bufferTriEndIndex.SetData(new int[] { 0 }); ComputeBuffer bufferTriBlockNum = new ComputeBuffer(_nextUpdateblocks.Count, sizeof(int)); int[] triBlockNum = new int[_nextUpdateblocks.Count]; bufferTriBlockNum.SetData(triBlockNum); shaderMarchingCube.SetBuffer(mcKernel, "_Samples", bufferSamples); shaderMarchingCube.SetBuffer(mcKernel, "_Normals", bufferNormals); shaderMarchingCube.SetBuffer(mcKernel, "_CornerFlags", bufferCornerFlags); shaderMarchingCube.SetBuffer(mcKernel, "_CornerToEdgeTable", _bufferCornerToEdgeTable); shaderMarchingCube.SetBuffer(mcKernel, "_CornerToVertTable", _bufferCornerToVertTable); shaderMarchingCube.SetBuffer(mcKernel, "_Meshes", bufferMeshes); shaderMarchingCube.SetBuffer(mcKernel, "_TriEndIndex", bufferTriEndIndex); shaderMarchingCube.SetBuffer(mcKernel, "_TriBlockNum", bufferTriBlockNum); //dispatch compute shader shaderMarchingCube.Dispatch(mcKernel, _nextUpdateblocks.Count, 1, 1); //split bufferMeshes to meshes for individual blocks CSTriangle[] csTriangles = new CSTriangle[triNum[0]];//triNum[0] is the counter bufferMeshes.GetData(csTriangles); bufferTriBlockNum.GetData(triBlockNum); int[] triBlockCounter = new int[triBlockNum.Length]; Vector3[][] vertices = new Vector3[_nextUpdateblocks.Count][]; Vector3[][] normals = new Vector3[_nextUpdateblocks.Count][]; for (int i = 0; i < _nextUpdateblocks.Count; i++) { vertices[i] = new Vector3[3 * triBlockNum[i]]; normals[i] = new Vector3[3 * triBlockNum[i]]; } foreach (var vt in csTriangles) { vertices[vt.block][triBlockCounter[vt.block]] = vt.position0 * engineScale; normals[vt.block][triBlockCounter[vt.block]] = vt.normal0; triBlockCounter[vt.block]++; vertices[vt.block][triBlockCounter[vt.block]] = vt.position1 * engineScale; normals[vt.block][triBlockCounter[vt.block]] = vt.normal1; triBlockCounter[vt.block]++; vertices[vt.block][triBlockCounter[vt.block]] = vt.position2 * engineScale; normals[vt.block][triBlockCounter[vt.block]] = vt.normal2; triBlockCounter[vt.block]++; } for (int i = 0; i < _nextUpdateblocks.Count; i++) { var x = _nextUpdateblocks[i]._x; var y = _nextUpdateblocks[i]._y; var z = _nextUpdateblocks[i]._z; _blocks[x, y, z].GetComponent <MeshFilter>().mesh.Clear(false); var mesh = _blocks[x, y, z].GetComponent <MeshFilter>().mesh; mesh.vertices = vertices[i]; int[] idx = new int[vertices[i].Length]; Buffer.BlockCopy(_incSequence, 0, idx, 0, vertices[i].Length * sizeof(int)); mesh.SetTriangles(idx, 0); mesh.normals = normals[i]; mesh.Optimize(); mesh.RecalculateBounds(); // _blocks[x, y, z].GetComponent<MeshFilter>().mesh = mesh; _blocks[x, y, z].GetComponent <MeshRenderer>().material = material; //_blocks[x, y, z].GetComponent<MeshCollider>().sharedMesh = mesh; } //Debug.Log("Time taken: " + (Time.realtimeSinceStartup - startTime) * 1000.0f); //#if UNITY_EDITOR // print("Time taken: " + (Time.realtimeSinceStartup - startTime) * 1000.0f); //#endif bufferNormals.Release(); bufferSamples.Release(); bufferTriNum.Release(); bufferCornerFlags.Release(); bufferMeshes.Release(); bufferTriEndIndex.Release(); bufferTriBlockNum.Release(); GC.Collect(); }
private void GenerateWavesSpectrum() { // Slope variance due to all waves, by integrating over the full spectrum. // Used by the BRDF rendering model float theoreticSlopeVariance = 0.0f; float k = 5e-3f; while (k < 1e3f) { float nextK = k * 1.001f; theoreticSlopeVariance += k * k * Spectrum(k, 0, true) * (nextK - k); k = nextK; } float[] spectrum01 = new float[m_fourierGridSize * m_fourierGridSize * 4]; float[] spectrum23 = new float[m_fourierGridSize * m_fourierGridSize * 4]; int idx; float i; float j; float totalSlopeVariance = 0.0f; Vector2 sample12XY; Vector2 sample12ZW; Vector2 sample34XY; Vector2 sample34ZW; Random.InitState(0); for (int x = 0; x < m_fourierGridSize; x++) { for (int y = 0; y < m_fourierGridSize; y++) { idx = x + y * m_fourierGridSize; i = (x >= m_fourierGridSize / 2) ? (float)(x - m_fourierGridSize) : (float)x; j = (y >= m_fourierGridSize / 2) ? (float)(y - m_fourierGridSize) : (float)y; sample12XY = GetSpectrumSample(i, j, m_gridSizes.x, Mathf.PI / m_gridSizes.x); sample12ZW = GetSpectrumSample(i, j, m_gridSizes.y, Mathf.PI * m_fsize / m_gridSizes.x); sample34XY = GetSpectrumSample(i, j, m_gridSizes.z, Mathf.PI * m_fsize / m_gridSizes.y); sample34ZW = GetSpectrumSample(i, j, m_gridSizes.w, Mathf.PI * m_fsize / m_gridSizes.z); spectrum01[idx * 4 + 0] = sample12XY.x; spectrum01[idx * 4 + 1] = sample12XY.y; spectrum01[idx * 4 + 2] = sample12ZW.x; spectrum01[idx * 4 + 3] = sample12ZW.y; spectrum23[idx * 4 + 0] = sample34XY.x; spectrum23[idx * 4 + 1] = sample34XY.y; spectrum23[idx * 4 + 2] = sample34ZW.x; spectrum23[idx * 4 + 3] = sample34ZW.y; i *= 2.0f * Mathf.PI; j *= 2.0f * Mathf.PI; totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.x, j / m_gridSizes.x, sample12XY); totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.y, j / m_gridSizes.y, sample12ZW); totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.z, j / m_gridSizes.z, sample34XY); totalSlopeVariance += GetSlopeVariance(i / m_gridSizes.w, j / m_gridSizes.w, sample34ZW); } } //Write floating point data into render texture ComputeBuffer buffer = new ComputeBuffer(m_fourierGridSize * m_fourierGridSize, sizeof(float) * 4); buffer.SetData(spectrum01); CBUtility.WriteIntoRenderTexture(m_spectrum01, 4, buffer, World.WriteData); buffer.SetData(spectrum23); CBUtility.WriteIntoRenderTexture(m_spectrum23, 4, buffer, World.WriteData); buffer.Release(); m_varianceShader.SetFloat("_SlopeVarianceDelta", 0.5f * (theoreticSlopeVariance - totalSlopeVariance)); m_varianceShader.SetFloat("_VarianceSize", (float)m_varianceSize); m_varianceShader.SetFloat("_Size", m_fsize); m_varianceShader.SetVector("_GridSizes", m_gridSizes); m_varianceShader.SetTexture(0, "_Spectrum01", m_spectrum01); m_varianceShader.SetTexture(0, "_Spectrum23", m_spectrum23); m_varianceShader.SetTexture(0, "des", m_variance); m_varianceShader.Dispatch(0, m_varianceSize / 4, m_varianceSize / 4, m_varianceSize / 4); //Find the maximum value for slope variance buffer = new ComputeBuffer(m_varianceSize * m_varianceSize * m_varianceSize, sizeof(float)); CBUtility.ReadFromRenderTexture(m_variance, 1, buffer, World.ReadData); float[] varianceData = new float[m_varianceSize * m_varianceSize * m_varianceSize]; buffer.GetData(varianceData); m_maxSlopeVariance = 0.0f; for (int v = 0; v < m_varianceSize * m_varianceSize * m_varianceSize; v++) { m_maxSlopeVariance = Mathf.Max(m_maxSlopeVariance, varianceData[v]); } buffer.Release(); }
private Texture3D ComputeSDF() { // Create the voxel texture. Texture3D voxels = new Texture3D(resolution, resolution, resolution, TextureFormat.RGBAHalf, false); voxels.anisoLevel = 1; voxels.filterMode = FilterMode.Bilinear; voxels.wrapMode = TextureWrapMode.Clamp; // Get an array of pixels from the voxel texture, create a buffer to // hold them, and upload the pixels to the buffer. Color[] pixelArray = voxels.GetPixels(0); ComputeBuffer pixelBuffer = new ComputeBuffer(pixelArray.Length, sizeof(float) * 4); pixelBuffer.SetData(pixelArray); // Get an array of triangles from the mesh. Vector3[] meshVertices = mesh.vertices; int[] meshTriangles = mesh.GetTriangles(subMeshIndex); Triangle[] triangleArray = new Triangle[meshTriangles.Length / 3]; for (int t = 0; t < triangleArray.Length; t++) { triangleArray[t].a = meshVertices[meshTriangles[3 * t + 0]] - mesh.bounds.center; triangleArray[t].b = meshVertices[meshTriangles[3 * t + 1]] - mesh.bounds.center; triangleArray[t].c = meshVertices[meshTriangles[3 * t + 2]] - mesh.bounds.center; } // Create a buffer to hold the triangles, and upload them to the buffer. ComputeBuffer triangleBuffer = new ComputeBuffer(triangleArray.Length, sizeof(float) * 3 * 3); triangleBuffer.SetData(triangleArray); // Instantiate the compute shader from resources. ComputeShader compute = (ComputeShader)Instantiate(Resources.Load("SDF")); int kernel = compute.FindKernel("CSMain"); // Upload the pixel buffer to the GPU. compute.SetBuffer(kernel, "pixelBuffer", pixelBuffer); compute.SetInt("pixelBufferSize", pixelArray.Length); // Upload the triangle buffer to the GPU. compute.SetBuffer(kernel, "triangleBuffer", triangleBuffer); compute.SetInt("triangleBufferSize", triangleArray.Length); // Calculate and upload the other necessary parameters. float maxMeshSize = Mathf.Max(Mathf.Max(mesh.bounds.size.x, mesh.bounds.size.y), mesh.bounds.size.z); float totalUnitsInTexture = maxMeshSize + 2.0f * padding; compute.SetInt("textureSize", resolution); compute.SetFloat("totalUnitsInTexture", totalUnitsInTexture); // Compute the SDF. compute.Dispatch(kernel, pixelArray.Length / 256 + 1, 1, 1); // Destroy the compute shader and release the triangle buffer. DestroyImmediate(compute); triangleBuffer.Release(); // Retrieve the pixel buffer and reapply it to the voxels texture. pixelBuffer.GetData(pixelArray); pixelBuffer.Release(); voxels.SetPixels(pixelArray, 0); voxels.Apply(); // Return the voxels texture. return voxels; }
void Update() { if (s_update_count++ == 0) { MPGPEmitter.UpdateAll(); MPGPForce.UpdateAll(); MPGPColliderBase.UpdateAll(); } if (m_writeback_to_cpu) { m_buf_particles[0].GetData(m_particles); m_buf_world_idata.GetData(m_world_idata); m_actions.ForEach((a) => { a.Invoke(); }); m_onetime_actions.ForEach((a) => { a.Invoke(); }); m_onetime_actions.Clear(); m_buf_particles[0].SetData(m_particles); m_buf_world_idata.SetData(m_world_idata); } m_world_data[0].num_max_particles = m_max_particles; m_world_data[0].SetWorldSize(transform.position, transform.localScale, (uint)m_world_div_x, (uint)m_world_div_y, (uint)m_world_div_z); m_world_data[0].timestep = Time.deltaTime * m_timescale; m_world_data[0].particle_size = m_particle_radius; m_world_data[0].particle_lifetime = m_lifetime; m_world_data[0].num_sphere_colliders = m_sphere_colliders.Count; m_world_data[0].num_capsule_colliders = m_capsule_colliders.Count; m_world_data[0].num_box_colliders = m_box_colliders.Count; m_world_data[0].num_forces = m_forces.Count; m_world_data[0].damping = m_damping; m_world_data[0].advection = m_advection; m_world_data[0].coord_scaler = m_coord_scaler; m_world_data[0].wall_stiffness = m_wall_stiffness; m_world_data[0].gbuffer_stiffness = m_gbuffer_stiffness; m_world_data[0].gbuffer_thickness = m_gbuffer_thickness; m_world_data[0].pressure_stiffness = m_pressure_stiffness; if (m_gbuffer_data != null) { var cam = m_gbuffer_data.GetCamera(); m_world_data[0].view_proj = m_gbuffer_data.GetMatrix_VP(); m_world_data[0].inv_view_proj = m_gbuffer_data.GetMatrix_InvVP(); m_world_data[0].rt_size = new Vector2(cam.pixelWidth, cam.pixelHeight); } m_sph_params[0].smooth_len = m_sph_smoothlen; m_sph_params[0].particle_mass = m_sph_particleMass; m_sph_params[0].pressure_stiffness = m_sph_pressureStiffness; m_sph_params[0].rest_density = m_sph_restDensity; m_sph_params[0].viscosity = m_sph_viscosity; m_buf_sphere_colliders.SetData(m_sphere_colliders.ToArray()); m_sphere_colliders.Clear(); m_buf_capsule_colliders.SetData(m_capsule_colliders.ToArray()); m_capsule_colliders.Clear(); m_buf_box_colliders.SetData(m_box_colliders.ToArray()); m_box_colliders.Clear(); m_buf_forces.SetData(m_forces.ToArray()); m_forces.Clear(); int num_cells = m_world_data[0].world_div_x * m_world_data[0].world_div_y * m_world_data[0].world_div_z; m_world_data[0].num_additional_particles = m_particles_to_add.Count; m_buf_world_data.SetData(m_world_data); MPGPWorldData csWorldData = m_world_data[0]; m_buf_sph_params.SetData(m_sph_params); // add new particles if (m_particles_to_add.Count > 0) { ComputeShader cs = m_cs_core; int kernel = kAddParticles; m_buf_particles_to_add.SetData(m_particles_to_add.ToArray()); cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "particles_to_add", m_buf_particles_to_add); cs.Dispatch(kernel, m_particles_to_add.Count / BLOCK_SIZE + 1, 1, 1); m_particles_to_add.Clear(); } { // clear cells { ComputeShader cs = m_cs_hashgrid; int kernel = 0; cs.SetBuffer(kernel, "cells_rw", m_buf_cells); cs.Dispatch(kernel, num_cells / BLOCK_SIZE, 1, 1); } // generate hashes { ComputeShader cs = m_cs_hashgrid; int kernel = 1; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "sort_keys_rw", m_buf_sort_data[0]); cs.Dispatch(kernel, m_max_particles / BLOCK_SIZE, 1, 1); } // sort keys { m_bitonic_sort.BitonicSort(m_buf_sort_data[0], m_buf_sort_data[1], (uint)csWorldData.num_max_particles); } // reorder particles { ComputeShader cs = m_cs_hashgrid; int kernel = 2; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "world_idata", m_buf_world_idata); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "particles_rw", m_buf_particles[1]); cs.SetBuffer(kernel, "sort_keys", m_buf_sort_data[0]); cs.SetBuffer(kernel, "cells_rw", m_buf_cells); cs.Dispatch(kernel, m_max_particles / BLOCK_SIZE, 1, 1); } // copy back { ComputeShader cs = m_cs_hashgrid; int kernel = 3; cs.SetBuffer(kernel, "particles", m_buf_particles[1]); cs.SetBuffer(kernel, "particles_rw", m_buf_particles[0]); cs.Dispatch(kernel, m_max_particles / BLOCK_SIZE, 1, 1); } } //{ // dbgSortData = new GPUSort.KIP[csWorldData.num_max_particles]; // cbSortData[0].GetData(dbgSortData); // uint prev = 0; // for (int i = 0; i < dbgSortData.Length; ++i) // { // if (prev > dbgSortData[i].key) // { // Debug.Log("sort bug: "+i); // break; // } // prev = dbgSortData[i].key; // } //} //dbgCellData = new CellData[num_cells]; //cbCells.GetData(dbgCellData); //for (int i = 0; i < num_cells; ++i ) //{ // if (dbgCellData[i].begin!=0) // { // Debug.Log("dbgCellData:" + dbgCellData[i].begin + "," + dbgCellData[i].end); // break; // } //} int num_active_blocks = m_max_particles / BLOCK_SIZE; // initialize intermediate data { ComputeShader cs = m_cs_core; int kernel = kPrepare; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // particle interaction if (m_solver == MPGPWorld.Interaction.Impulse) { ComputeShader cs = m_cs_core; int kernel = m_dimension == MPGPWorld.Dimension.Dimendion3D ? kProcessInteraction_Impulse : kProcessInteraction_Impulse2D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } else if (m_solver == MPGPWorld.Interaction.SPH) { ComputeShader cs = m_cs_core; int kernel = m_dimension == MPGPWorld.Dimension.Dimendion3D ? kProcessInteraction_SPH_Pass1 : kProcessInteraction_SPH_Pass12D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "sph_params", m_buf_sph_params); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); kernel = m_dimension == MPGPWorld.Dimension.Dimendion3D ? kProcessInteraction_SPH_Pass2 : kProcessInteraction_SPH_Pass22D; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "sph_params", m_buf_sph_params); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.Dispatch(kernel, num_active_blocks, 1, 1); } else if (m_solver == MPGPWorld.Interaction.None) { // do nothing } // gbuffer collision if (m_process_gbuffer_collision && m_gbuffer_data != null) { var depth = m_gbuffer_data.GetGBuffer_Depth(); var normal = m_gbuffer_data.GetGBuffer_Normal(); if (depth != null && normal != null) { ComputeShader cs = m_cs_core; int kernel = kProcessGBufferCollision; cs.SetTexture(kernel, "gbuffer_normal", normal); cs.SetTexture(kernel, "gbuffer_depth", depth); cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.Dispatch(kernel, num_active_blocks, 1, 1); } else { m_gbuffer_data.m_enable_inv_matrices = true; m_gbuffer_data.m_enable_prev_depth = true; m_gbuffer_data.m_enable_prev_normal = true; } } // colliders if (m_process_colliders) { ComputeShader cs = m_cs_core; int kernel = kProcessColliders; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.SetBuffer(kernel, "sphere_colliders", m_buf_sphere_colliders); cs.SetBuffer(kernel, "capsule_colliders", m_buf_capsule_colliders); cs.SetBuffer(kernel, "box_colliders", m_buf_box_colliders); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // forces if (m_process_forces) { ComputeShader cs = m_cs_core; int kernel = kProcessForces; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.SetBuffer(kernel, "cells", m_buf_cells); cs.SetBuffer(kernel, "forces", m_buf_forces); cs.Dispatch(kernel, num_active_blocks, 1, 1); } // integrate { ComputeShader cs = m_cs_core; int kernel = kIntegrate; cs.SetBuffer(kernel, "world_data", m_buf_world_data); cs.SetBuffer(kernel, "particles", m_buf_particles[0]); cs.SetBuffer(kernel, "pimd", m_buf_imd); cs.Dispatch(kernel, num_active_blocks, 1, 1); } }
protected override void Init() { base.Init(); MotionType = MotionType.MultiDepth; // Camera.main.fieldOfView = 30f; _touchIds = new Dictionary <int, ClickData>(); PosAndDir[] datas = new PosAndDir[ComputeBuffer.count]; ComputeBuffer.GetData(datas); List <PosAndDir> temp = new List <PosAndDir>(); List <PosAndDir> allDataList = new List <PosAndDir>(); //这里注意,posAndDir属于结构体,值拷贝 for (int i = 0; i < datas.Length; i++) { PosAndDir data = datas[i]; if (i < Common.PictureCount * 3) { temp.Add(data);//编号一样的单独拿出来 } else { data.position = Vector4.zero;//其他编号都隐藏 data.originalPos = Vector4.one; allDataList.Add(data); } } _zeroIndexCount = allDataList.Count; PosAndDir[] newData = temp.ToArray(); int stride = Marshal.SizeOf(typeof(DepthInfo)); _depthBuffer = new ComputeBuffer(3, stride); _depths = new DepthInfo[3]; //点击缓存 _clickPointBuff = new ComputeBuffer(1, Marshal.SizeOf(typeof(PosAndDir))); PosAndDir[] clickPoint = { new PosAndDir(-1) }; _clickPointBuff.SetData(clickPoint); int k = 0; float z = 6; float scaleY = 1;//y轴位置屏幕有内容的比率 //得到随机点的个数,第一层的随机点个数不允许低于40 //这个参数存在的意义是Common.Sample2D方法采样的时候会得不到正确的个数,有时候明显偏低,这个参数就是为了修正这个数据 //这个数据如果scaleY s 两个参数有变化,应该考虑第一层随机点个数的变化 int count = 40; List <Vector2> randomPos = new List <Vector2>(); for (int j = 0; j < newData.Length; j++) { if (j % Common.PictureCount == 0) { //距离相机的深度值 float tempZ = k * z - 4; k++; _screenPosLeftDown = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, tempZ - Camera.main.transform.position.z)); _screenPosLeftUp = Camera.main.ScreenToWorldPoint(new Vector3(0, Height, tempZ - Camera.main.transform.position.z)); _screenPosRightDown = Camera.main.ScreenToWorldPoint(new Vector3(Width, 0, tempZ - Camera.main.transform.position.z)); _screenPosRightUp = Camera.main.ScreenToWorldPoint(new Vector3(Width, Height, tempZ - Camera.main.transform.position.z)); float s = 1f; //不同层次的给定不同的缩放 float a = 1f; //不同层次的给定不同的透明度 if (k == 1) { s = 1f; a = 1f; scaleY = 0.55f; } else if (k == 2) { s = 1.2f; a = 0.45f; scaleY = 0.25f; } else if (k == 3) { s = 1.4f; a = 0.25f; scaleY = 0.18f; } else if (k == 4) { s = 1.6f; a = 0.45f; scaleY = 0.7f; } else if (k == 5) { s = 1.8f; a = 0.25f; scaleY = 0.6f; } while (true) { if (count >= randomPos.Count)//如果得到的个数比上一个还小,那是不正确的采样,必须重新采样 { // Debug.Log("x:" + _screenPosRightDown.x + " \r\n x1:" + _screenPosLeftDown.x + " \r\n y:" + _screenPosLeftUp.y + "\r\n y1:" + _screenPosLeftDown.y + " \r\n scaleY:" + scaleY + " \r\n s:" + s); randomPos = Common.Sample2D((_screenPosRightDown.x - _screenPosLeftDown.x) * 4, (_screenPosLeftUp.y - _screenPosLeftDown.y) * scaleY, s + 0.75f, 25); } else { count = randomPos.Count; break; } } Debug.Log("randomPos count is " + randomPos.Count + " 层级为=> " + (k - 1) + " tempZ is=>" + tempZ); _depths[k - 1] = new DepthInfo(k - 1, tempZ, s, a); } float rangeZ = Random.Range(-0.5f, 0.5f);//在同一层次,再随机不同的深度位置,不至于重叠一起,显得错落有致 Vector4 posTemp = newData[j].position; newData[j].position = new Vector4(posTemp.x, posTemp.y, posTemp.z, 1); Vector2 randomPoint; if (randomPos.Count > 0) { // Random.InitState(Random.Range(0, randomPos.Count)); int rangIndex = Random.Range(0, randomPos.Count); randomPoint = randomPos[rangIndex]; randomPos.RemoveAt(rangIndex); } else//如果多出来,则放到看不到的地方 { randomPoint = new Vector2(_screenPosLeftDown.x, Random.Range(1000f, 2000f)); } // Vector2 randomPoint = randomPos[j % randomPos.Count]; //计算Y轴的位置(1 - scaleY)为空余的位置(1 - scaleY)/2f上下空余的位置,(1 - scaleY)/2f*(_screenPosLeftUp.y - _screenPosLeftDown.y)空余位置的距离 float heightTmep = (1 - scaleY) / 2f * (_screenPosLeftUp.y - _screenPosLeftDown.y); randomPoint = new Vector2(randomPoint.x + _screenPosLeftDown.x, randomPoint.y + _screenPosLeftDown.y + heightTmep); newData[j].moveTarget = new Vector3(randomPoint.x, randomPoint.y + Common.HeightTemp, rangeZ); newData[j].uvOffset = new Vector4(1f, 1f, 0f, 0f); newData[j].uv2Offset = new Vector4(1f, 1f, 0f, 0f); int picIndex = 0; Vector2 size = PictureHandle.Instance.GetLevelIndexSize(j, k - 1, out picIndex);//得到缩放尺寸 float xScale = size.x / 512f; float yScale = size.y / 512f; float proportion = size.x / size.y; if (xScale >= 2 || yScale >= 2) { //如果超过2倍大小,则强制缩放到一倍大小以内,并以宽度为准,等比例减少 int a = (int)xScale; xScale = xScale - (a) + 2f; yScale = xScale / proportion; } newData[j].initialVelocity = new Vector3(xScale, yScale, 0f);//填充真实宽高 newData[j].picIndex = picIndex; newData[j].bigIndex = picIndex; //x存储层次的索引,y存储透明度, z存储,x轴右边的边界值,为正数 ,最后一个为随机深度 newData[j].velocity = new Vector4(k - 1, 1f, _screenPosRightDown.x * 4f, 0); Vector4 otherData = new Vector4(); newData[j].originalPos = otherData; } TextureInstanced.Instance.ChangeInstanceMat(CurMaterial); CurMaterial.enableInstancing = true; TextureInstanced.Instance.CurMaterial.SetVector("_WHScale", new Vector4(1f, 1f, 1f, 1f)); allDataList.AddRange(newData); ComputeBuffer.SetData(allDataList.ToArray()); _depthBuffer.SetData(_depths); ComputeShader.SetBuffer(dispatchID, "depthBuffer", _depthBuffer); ComputeShader.SetBuffer(dispatchID, "positionBuffer", ComputeBuffer); ComputeShader.SetFloat("Width", Screen.width); ComputeShader.SetFloat("Height", Screen.height); Matrix4x4 camMatri = Camera.main.projectionMatrix; ComputeShader.SetFloat("m32", camMatri.m32); ComputeShader.SetFloat("m00", camMatri.m00); ComputeShader.SetFloat("m11", camMatri.m11); ComputeShader.SetVector("camPos", Camera.main.transform.position); // ComputeShader.SetFloats(dispatchID, "positionBuffer", ComputeBuffer); // _depthPictureMove = new MultiDepthPictureMove(newData,_depths,Canvas); //ComputeShader.SetBuffer(InitID, "positionBuffer", ComputeBuffer); //ComputeShader.SetBuffer(InitID, "depthBuffer", _depthBuffer); TextureInstanced.Instance.CurMaterial.SetBuffer("positionBuffer", ComputeBuffer); TextureInstanced.Instance.CurMaterial.SetTexture("_TexArr", TextureInstanced.Instance.TexArr); MoveSpeed = 50f;//更改更快的插值速度 ComputeShader.SetFloat("MoveSpeed", MoveSpeed); ComputeShader.SetFloat("dis", 800); ComputeShader.SetBuffer(dispatchID, "clickPointsBuff", _clickPointBuff); //触摸点最大为十个 List <Vector3> clicks = new List <Vector3>(); for (int i = 0; i < 10; i++) { clicks.Add(Vector3.one * 100000); } _clickBuff = new ComputeBuffer(10, 12); _clickBuff.SetData(clicks.ToArray()); ComputeShader.SetBuffer(dispatchID, "clicks", _clickBuff); InitDisPatch(InitID); }
protected override void Dispatch(ComputeBuffer system) { // MouseButtonDownAction(); Vector3[] temp = new Vector3[_clickBuff.count]; //_clickBuff.GetData(temp); //传输过去前,先重置数据 // for (int i = 0; i < temp.Length; i++) { temp[i] = Vector3.one * 1000000; } int n = 0; foreach (KeyValuePair <int, ClickData> keyValuePair in _touchIds) { Vector3 pos = keyValuePair.Value.Position; //Debug.Log(pos); // pos = Camera.main.ScreenToWorldPoint(new Vector3(pos.x, pos.y, 6));//6 深度是相机到物体的深度 是第一排物体的离相机的距离 temp[n] = pos; n++; } LeftDownTip.position = temp[0]; _clickBuff.SetData(temp); ComputeShader.SetBuffer(dispatchID, "clicks", _clickBuff); //if (Input.GetMouseButtonDown(1)) //{ // ComputeShader.SetVector("rangeRot", new Vector4(_zeroIndexCount + 115, _zeroIndexCount + 130, _zeroIndexCount + 50, _zeroIndexCount + 157)); //} //if (Input.GetMouseButtonUp(1)) //{ // ComputeShader.SetVector("rangeRot", new Vector4(-1, -1, -1, -1)); //} Ray ray; // Debug.Log(_clickPoint + " " + Input.mousePosition); ray = Camera.main.ScreenPointToRay(_clickPoint); Vector3 clickPos = Vector3.one * 100000; RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo)) { clickPos = hitInfo.transform.position; } if (_clickPoint.z < 0) { _clickPoint = Camera.main.ScreenToWorldPoint(new Vector3(_clickPoint.x, _clickPoint.y, 6)); } else { _clickPoint = Vector3.one * 1000000; } //_depthPictureMove.Excute(temp); ComputeShader.SetVector("clickPoint", _clickPoint); ComputeShader.SetFloat("deltaTime", Time.deltaTime); //Camera.main.ResetTransparencySortSettings(); //Camera.main.transparencySortAxis = Vector3.right; //Camera.main.transparencySortMode = TransparencySortMode.CustomAxis; Dispatch(dispatchID, system); if (_clickPoint.z < 1000000)//相当于有点击事件才触发 { PosAndDir[] datas = new PosAndDir[1]; _clickPointBuff.GetData(datas); int index = datas[0].picIndex; Vector3 temp1 = Camera.main.ScreenToWorldPoint(new Vector3(400, 500, 10)); // Debug.Log("click WorldToScreenPos is " + datas[0].moveDir + " aip实现是 " + temp1); PictureHandle.Instance.GetYearInfo(datas[0], Canvas.transform); _clickPoint = Vector3.one * 1000000;//重置数据 } }
public void WithDataExtracted(Action action) { data.GetData(managedData); action(); data.SetData(managedData); }
//updating the terrain with compute shaders on the GPU public void UpdateTerrainGPU(Chunk chunk) { //create buffers for GPU call CreateBuffers(); //int PointsPerAxis = VoxelsPerAxis + 1; float voxelSpacing = ChunkSize / (float)VoxelsPerAxis; Vector3Int coord = chunk.Pos; Vector3 chunkCentre = GetChunkCentre(coord); //get world size Vector3 worldSize = new Vector3(NumOfChunks.x, NumOfChunks.y, NumOfChunks.z) * ChunkSize; //generate the noise noiseGenerator.Generate(voxelBuffer, VoxelsPerAxis, ChunkSize, worldSize, chunkCentre, voxelSpacing, noiseType); //generate the mesh points MarchingCubes.UpdateTerrainGPU(MarchingCubesCompute, voxelBuffer, triangleBuffer, VoxelsPerAxis, ISOValue); // Get number of triangles in the triangle buffer ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0); int[] triCountArray = { 0 }; //update the mesh with the populated triangle buffer triCountBuffer.GetData(triCountArray); int numTris = triCountArray[0]; // Get triangle data from shader Triangle[] tris = new Triangle[numTris]; triangleBuffer.GetData(tris, 0, 0, numTris); //clear the buffers immediatly ReleaseBuffers(); //clear the meash ready for update Mesh mesh = chunk.mesh; mesh.Clear(); var vertices = new Vector3[numTris * 3]; var meshTriangles = new int[numTris * 3]; //set verts & tris for mesh for (int i = 0; i < numTris; i++) { for (int j = 0; j < 3; j++) { meshTriangles[i * 3 + j] = i * 3 + j; vertices[i * 3 + j] = tris[i][j]; } } mesh.vertices = vertices; mesh.triangles = meshTriangles; //point everything in the right direction mesh.RecalculateNormals(); //rerun the setup to recalc collisions if player is in that chunk //position of player Vector3 PlayerPos = player.transform.position; float PlayerBase = player.GetComponent <SphereCollider>().radius; //chunk player is in Vector3Int ChunkOccupied = Vector3Int.RoundToInt((PlayerPos - new Vector3(0, PlayerBase, 0)) / ChunkSize); //generate all collisions on start if fixed time if (FixedMapSize) { chunk.SetUp(GenerateCollisions, material); } else { //only generate collisions on the chunk the player is in // (or directly above or below as this was causing mesh failures with the physics timing and player was falling through) bool GenCollisions = false; if (VectorEqu(ChunkOccupied, chunk.Pos, new Vector3(0, 1, 0))) { GenCollisions = true; } chunk.SetUp(GenCollisions, material); } //handle garbage collection when app stops running if (!Application.isPlaying) { ReleaseBuffers(); } }
public static List <Vector4> GetClusters(List <Vector4> atoms, int numCentroids) { if (ComputeShaderManager.Instance.KMeansCS == null) { throw new Exception("KMeans compute shader not assigned"); } if (numCentroids <= 0) { throw new Exception("Num centroids too low"); } var centroids = new List <Vector4>(); var centroidStep = Mathf.CeilToInt(atoms.Count / (float)numCentroids); for (int i = 0; i < numCentroids; i++) { if (i * centroidStep < atoms.Count) { centroids.Add(atoms[i * centroidStep]); } else { centroids.Add(atoms[UnityEngine.Random.Range(0, atoms.Count)]); } } var centroidBuffer = new ComputeBuffer(numCentroids, 4 * sizeof(float)); centroidBuffer.SetData(centroids.ToArray()); var pointBuffer = new ComputeBuffer(atoms.Count, 4 * sizeof(float)); pointBuffer.SetData(atoms.ToArray()); var membershipBuffer = new ComputeBuffer(atoms.Count, sizeof(int)); ComputeShaderManager.Instance.KMeansCS.SetInt("_NumPoints", atoms.Count); ComputeShaderManager.Instance.KMeansCS.SetInt("_NumCentroids", numCentroids); for (int i = 0; i < 5; i++) { ComputeShaderManager.Instance.KMeansCS.SetBuffer(0, "_PointBuffer", pointBuffer); ComputeShaderManager.Instance.KMeansCS.SetBuffer(0, "_CentroidBuffer", centroidBuffer); ComputeShaderManager.Instance.KMeansCS.SetBuffer(0, "_MembershipBuffer", membershipBuffer); ComputeShaderManager.Instance.KMeansCS.Dispatch(0, Mathf.CeilToInt(atoms.Count / 64.0f), 1, 1); ComputeShaderManager.Instance.KMeansCS.SetBuffer(1, "_PointBuffer", pointBuffer); ComputeShaderManager.Instance.KMeansCS.SetBuffer(1, "_NewCentroidBuffer", centroidBuffer); ComputeShaderManager.Instance.KMeansCS.SetBuffer(1, "_NewMembershipBuffer", membershipBuffer); ComputeShaderManager.Instance.KMeansCS.Dispatch(1, Mathf.CeilToInt(numCentroids / 64.0f), 1, 1); } var newCentroids = new Vector4[numCentroids]; centroidBuffer.GetData(newCentroids); pointBuffer.Release(); centroidBuffer.Release(); membershipBuffer.Release(); return(newCentroids.ToList()); }
protected override void Init() { base.Init(); _screenPosLeftDown = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, Z - Camera.main.transform.position.z)); _screenPosLeftUp = Camera.main.ScreenToWorldPoint(new Vector3(0, Height, Z - Camera.main.transform.position.z)); _screenPosRightDown = Camera.main.ScreenToWorldPoint(new Vector3(Width, 0, Z - Camera.main.transform.position.z)); _screenPosRightUp = Camera.main.ScreenToWorldPoint(new Vector3(Width, Height, Z - Camera.main.transform.position.z)); int instanceCount = TextureInstanced.Instance.InstanceCount; PosAndDir[] datas = new PosAndDir[ComputeBuffer.count]; ComputeBuffer.GetData(datas); //根据种类个数生成盒子,先手动完成,盒子分配,有时间在完善=>开发出自动分配均匀大小的盒子填满窗口 //这里以生成8个盒子还展开 List <Rect> rects = new List <Rect>(); if (CategoryCount == 8) { //生成八个盒子,横列4个,竖列2个 float width = Width / 4f; //480 float height = Height / 2f; //540 //x,y 为倍数 Rect rect0 = new Rect(0f, 0f, width, height); Rect rect1 = new Rect(1f, 0f, width, height); Rect rect2 = new Rect(2f, 0f, width, height); Rect rect3 = new Rect(3f, 0f, width, height); Rect rect4 = new Rect(0f, 1f, width, height); Rect rect5 = new Rect(1f, 1f, width, height); Rect rect6 = new Rect(2f, 1f, width, height); Rect rect7 = new Rect(3f, 1f, width, height); rects.Add(rect0); rects.Add(rect1); rects.Add(rect2); rects.Add(rect3); rects.Add(rect4); rects.Add(rect5); rects.Add(rect6); rects.Add(rect7); } //每个盒子分配得到的面片个数 int count = instanceCount / (int)CategoryCount;//8192 Vector2 scale = Vector2.zero; for (int i = 0; i < rects.Count; i++) { Rect rect = rects[i]; float width = rect.width; float height = rect.height; float fitedge = (Mathf.Sqrt((width * height * 1f) / count)); //适合的边长, int row = (int)(width / fitedge); //求得大概行横列的个数,即一横有多少个 int column = (int)(height / fitedge); //求得竖列大概的个数,即一竖有多少个 float smallWidth = width * 1f / row; //求得小矩形屏幕分辨率的宽 float smallHeight = height * 1f / column; //求得小矩形屏幕分辨率的高, //求得小矩形的宽和高后,填满大矩形的个数跟每个盒子分配的面片个数不一致, //我们以求得的宽高后的盒子为准,多余的面片我们舍去 //row*column 为实际上用到的quad个数 //小矩形的宽高转化为世界宽度和高度,注意Z轴 Vector3 origin = Camera.main.ScreenToWorldPoint(new Vector3(0f, 0f, Z - Camera.main.transform.position.z)); //世界位置小矩形的宽 Vector3 wpos = Camera.main.ScreenToWorldPoint(new Vector3(smallWidth, 0f, Z - Camera.main.transform.position.z)); //世界位置小矩形的高 Vector3 hpos = Camera.main.ScreenToWorldPoint(new Vector3(0f, smallHeight, Z - Camera.main.transform.position.z)); //得到小矩形在世界坐标中应得到的宽度 float wwidth = wpos.x - origin.x; //得到小矩形哎世界坐标中得到的高度 float wheight = hpos.y - origin.y; //世界位置大矩形的宽的位置 Vector3 widthBigpos = Camera.main.ScreenToWorldPoint(new Vector3(rect.width, 0f, Z - Camera.main.transform.position.z)); //世界位置大矩形的高的位置 Vector3 heightBigpos = Camera.main.ScreenToWorldPoint(new Vector3(0f, rect.height, Z - Camera.main.transform.position.z)); //得到大矩形在世界坐标中应得到的宽度 float wwidthBig = widthBigpos.x - origin.x; //得到大矩形哎世界坐标中得到的高度 float wheightBig = heightBigpos.y - origin.y; //因为quad边长为1,对quab进行缩放加工,quad的位置的Z轴位置一定要正确 // Quab.transform.localScale = new Vector3(wwidth, wheight, 1f); scale = new Vector2(wwidth, wheight);//把面片缩放倍数弹出去 int actual = row * column;//实际有作用的粒子个数 //进一步加工uv y=>rows x=>horizontalColumn //得到一个新的uvwz, float u = 1f / row; float v = 1f / column; float delay = Random.Range(3, 8); //把小矩形填充整个大矩形 int columnTempCount = 0;//横列个数 y轴概念 for (int j = 0; j < actual; j++) { int index = i * count + j;//buff数组中的索引位置 // Vector3 pos = Vector3.zero; if (j != 0 && j % row == 0) { columnTempCount++; } int rowTempCount = j - columnTempCount * row;//竖列个数 x轴概念 Vector3 pos = new Vector3(origin.x, origin.y, 0) + //这里的xy,存放的是倍数 new Vector3(wwidthBig * rect.position.x, wheightBig * rect.position.y, 0) + new Vector3(wwidth * rowTempCount + wwidth / 2, wheight * columnTempCount + wheight / 2f, Z); datas[index].moveTarget = pos; datas[index].originalPos = Vector4.one; // datas[index].position = Vector4.one; datas[index].indexRC = new Vector2(rowTempCount, columnTempCount); datas[index].picIndex = i; datas[index].bigIndex = i; //分类编号 Vector4 otherData = new Vector4(); //切换图片索要缓存的数据 otherData.x = delay; //延迟播放的时间 otherData.y = 1f; //Random.Range(0.1f,1f);//切换图片的时间 otherData.z = 0f; //时间缓存 otherData.w = 0f; //插值值 datas[index].velocity = otherData; datas[index].initialVelocity = Vector3.zero; //缓存器 float w = u * rowTempCount; //rowsCount float z = v * columnTempCount; //columnCount datas[index].uvOffset = new Vector4(u, v, w, z); #region 设置第二套UV,写死规定每个小矩形在切分成九个小矩形,这里只设置UV切分 float row2 = row / 3f; //小小矩形的横轴个数 float column2 = column / 3f; //小小矩形竖轴个数 float u2 = 1f / row2; float v2 = 1f / column2; int indexrow = (int)(rowTempCount * 1f / row2) + 1; //小矩形里小小矩形的x轴个数 int indexColumn = (int)(columnTempCount * 1f / column2) + 1; //小矩形里小小矩形的y轴的个数 float w2 = ((rowTempCount % row2) * 1f / row2); float z2 = ((columnTempCount % column2) * 1f / column2); datas[index].uv2Offset = new Vector4(u2, v2, w2, z2); datas[index].bigIndex = i + (indexColumn - 1) * 3 + indexrow;//分类编号*3是因为一横有三个 #endregion } int useless = count - actual;//剩下的没有用到的面片, //全部缩小至0,位置也归零 for (int j = 0; j < useless; j++) { int index = actual + j; datas[index].position = Vector4.zero; //datas[index].moveTarget = Vector3.zero; //datas[index].originalPos = Vector4.zero; } } TextureInstanced.Instance.ChangeInstanceMat(null); TextureInstanced.Instance.CurMaterial.SetVector("_WHScale", new Vector4(scale.x, scale.y, 1, 1)); ComputeBuffer.SetData(datas); ComputeShader.SetBuffer(dispatchID, "positionBuffer", ComputeBuffer); ComputeShader.SetBuffer(InitID, "positionBuffer", ComputeBuffer); MoveSpeed = 50f;//更改更快的插值速度 ComputeShader.SetFloat("MoveSpeed", MoveSpeed); }
public static void ICP_iteration(Vector3[] startPoints, Vector3[] stopPoints, out Quaternion Qe, out Vector3 Te, out Vector3[] projectedStopPoints, out int[] match_idx_array) { //Debug.Log("ICP iteration!"); int N = startPoints.Length; if (stopPoints.Length != N) { Debug.Log("ICP ITERATION CANT WORK BECAUSE START POINT LENGHT AND STOP POINT LENGTH ARE NOT THE SAME"); } Qe = Quaternion.identity; Te = new Vector3(); projectedStopPoints = new Vector3[stopPoints.Length]; ComputeBuffer start_point_buffer = new ComputeBuffer(startPoints.Length, 3 * sizeof(float)); ComputeBuffer stop_point_buffer = new ComputeBuffer(stopPoints.Length, 3 * sizeof(float)); start_point_buffer.SetData(startPoints); stop_point_buffer.SetData(stopPoints); int matchImage_kh = icp_shader.FindKernel("matchImage"); icp_shader.SetBuffer(matchImage_kh, "start_point_buffer", start_point_buffer); icp_shader.SetBuffer(matchImage_kh, "stop_point_buffer", stop_point_buffer); icp_shader.SetFloat("result_scale", result_scale); if (rt == null || rt.width != N || rt.width != N) { rt = new RenderTexture(N, N, 24, RenderTextureFormat.ARGBFloat); rt.enableRandomWrite = true; rt.filterMode = FilterMode.Point; rt.Create(); } icp_shader.SetTexture(matchImage_kh, "match_tex", rt); icp_shader.Dispatch(matchImage_kh, ((int)(N / 8)) + 1, ((int)(N / 8)) + 1, 1); debugCube.GetComponent <Renderer>().material = new Material(Shader.Find("Unlit/Texture")); debugCube.GetComponent <Renderer>().material.mainTexture = rt; //match points using matchImage: int matchPoints_kh = icp_shader.FindKernel("matchPoints"); ComputeBuffer match_idx_buffer = new ComputeBuffer(startPoints.Length, sizeof(int)); icp_shader.SetBuffer(matchPoints_kh, "start_point_buffer", start_point_buffer); icp_shader.SetBuffer(matchPoints_kh, "stop_point_buffer", stop_point_buffer); icp_shader.SetBuffer(matchPoints_kh, "match_idx_buffer", match_idx_buffer); icp_shader.SetTexture(matchPoints_kh, "match_tex", rt); icp_shader.SetFloat("neighbor_threshold", neighbor_threshold); icp_shader.SetInt("num_points", startPoints.Length); icp_shader.Dispatch(matchPoints_kh, (startPoints.Length / 64) + 1, 1, 1); match_idx_array = new int[startPoints.Length]; match_idx_buffer.GetData(match_idx_array); List <Vector3> startMatchList = new List <Vector3>(); List <Vector3> stopMatchList = new List <Vector3>(); List <Vector2> matchIdxList = new List <Vector2>(); for (int i = 0; i < startPoints.Length; i++) { if (match_idx_array[i] >= 0) { startMatchList.Add(startPoints[i]); stopMatchList.Add(stopPoints[match_idx_array[i]]); matchIdxList.Add(new Vector2(i, match_idx_array[i])); } } /* * Debug.Log("Found Neighbor matches: " + startMatchList.Count); * for(int i = 0; i<startMatchList.Count; i++) * { * Debug.Log("Point " + i + ": dist: " + (startMatchList[i] - stopMatchList[i]).magnitude + " midx: " + matchIdxList[i] + " p1: " + startMatchList[i] + " p2: " + stopMatchList[i]); * } */ if (ICP.in_plane_only) { estimateInPlaneTransform(startMatchList.ToArray(), stopMatchList.ToArray(), out Qe, out Te); } else { estimateTransform(startMatchList.ToArray(), stopMatchList.ToArray(), out Qe, out Te); } //Debug.Log("estimated Q: " + Qe + " Estimated Te: " + Te); //reproject stop points: Matrix4x4 projection = Matrix4x4.TRS(Te, Qe, new Vector3(1.0f, 1.0f, 1.0f)); //projection = Matrix4x4.TRS(new Vector3(0.0f, 0.5f, 0.0f), Quaternion.identity, new Vector3(1.0f, 1.0f, 1.0f)); //Debug.Log("projection matrix: " + projection); int projectPoints_kh = icp_shader.FindKernel("projectPoints"); ComputeBuffer reprojected_stop_point_buffer = new ComputeBuffer(stopPoints.Length, 3 * sizeof(float)); icp_shader.SetBuffer(projectPoints_kh, "stop_point_buffer", stop_point_buffer); icp_shader.SetBuffer(projectPoints_kh, "reprojected_stop_point_buffer", reprojected_stop_point_buffer); icp_shader.SetMatrix("matFromStopToStart", projection.inverse); icp_shader.Dispatch(projectPoints_kh, (stopPoints.Length / 64) + 1, 1, 1); reprojected_stop_point_buffer.GetData(projectedStopPoints); start_point_buffer.Dispose(); stop_point_buffer.Dispose(); reprojected_stop_point_buffer.Dispose(); match_idx_buffer.Dispose(); }
/// <summary> /// 改变状态,直接把大矩形填满整个屏幕,其他大矩形则透明掉 /// </summary> public void ChangeState(int classNumber) { if (Type != MotionType.ClassiFicationMotion) { return; } PosAndDir[] datas = new PosAndDir[ComputeBuffer.count]; ComputeBuffer.GetData(datas); List <PosAndDir> temp = new List <PosAndDir>(); List <PosAndDir> allDataList = new List <PosAndDir>(); //这里注意,posAndDir属于结构体,值拷贝 for (int i = datas.Length - 1; i >= 0; i--) { PosAndDir data = datas[i]; if (datas[i].bigIndex == classNumber) { temp.Add(data);//编号一样的单独拿出来 } else { data.position = Vector4.zero;//其他编号都隐藏 allDataList.Add(data); } } PosAndDir[] newData = temp.ToArray(); //根据分辨率展开图片 写死每个大矩形的宽高 int widthCount = Width / 96; //每个图片宽99像素 int heightCount = Height / 108; //每个图片高108素 List <Rect> rects = new List <Rect>(); int tempHeithtCount = 0;//y轴上的个数 for (int i = 0; i < widthCount * heightCount; i++) { if (i != 0 && i % widthCount == 0) { tempHeithtCount++; } int tempWidthCount = i - tempHeithtCount * widthCount;//轴上的个数 Rect rect = new Rect(tempWidthCount, tempHeithtCount, 96f, 108f); rects.Add(rect); } //每个盒子分配得到的面片个数 会有概率盒子分配过剩,记得把过剩的处理 int count = newData.Length / rects.Count; Vector2 scale = Vector2.zero; for (int i = 0; i < rects.Count; i++) { #region 处理小矩形 Rect rect = rects[i]; float width = rect.width; float height = rect.height; float fitedge = (Mathf.Sqrt((width * height * 1f) / count)); //适合的边长, int row = (int)(width / fitedge); //求得大概行横列的个数,即一横有多少个 int column = (int)(height / fitedge); //求得竖列大概的个数,即一竖有多少个 float smallWidth = width * 1f / row; //求得小矩形屏幕分辨率的宽 float smallHeight = height * 1f / column; //求得小矩形屏幕分辨率的高, //求得小矩形的宽和高后,填满大矩形的个数跟每个盒子分配的面片个数不一致, //我们以求得的宽高后的盒子为准,多余的面片我们舍去 //row*column 为实际上用到的quad个数 //小矩形的宽高转化为世界宽度和高度,注意Z轴 Vector3 origin = Camera.main.ScreenToWorldPoint(new Vector3(0f, 0f, Z - Camera.main.transform.position.z)); //世界位置小矩形的宽 Vector3 wpos = Camera.main.ScreenToWorldPoint(new Vector3(smallWidth, 0f, Z - Camera.main.transform.position.z)); //世界位置小矩形的高 Vector3 hpos = Camera.main.ScreenToWorldPoint(new Vector3(0f, smallHeight, Z - Camera.main.transform.position.z)); //得到小矩形在世界坐标中应得到的宽度 float wwidth = wpos.x - origin.x; //得到小矩形哎世界坐标中得到的高度 float wheight = hpos.y - origin.y; //世界位置大矩形的宽的位置 Vector3 widthBigpos = Camera.main.ScreenToWorldPoint(new Vector3(rect.width, 0f, Z - Camera.main.transform.position.z)); //世界位置大矩形的高的位置 Vector3 heightBigpos = Camera.main.ScreenToWorldPoint(new Vector3(0f, rect.height, Z - Camera.main.transform.position.z)); //得到大矩形在世界坐标中应得到的宽度 float wwidthBig = widthBigpos.x - origin.x; //得到大矩形哎世界坐标中得到的高度 float wheightBig = heightBigpos.y - origin.y; //因为quad边长为1,对quab进行缩放加工,quad的位置的Z轴位置一定要正确 // Quab.transform.localScale = new Vector3(wwidth, wheight, 1f); scale = new Vector2(wwidth, wheight);//把面片缩放倍数弹出去 int actual = row * column;//实际有作用的粒子个数 //进一步加工uv y=>rows x=>horizontalColumn //得到一个新的uvwz, float u = 1f / row; float v = 1f / column; float delay = Random.Range(3, 8); //把小矩形填充整个大矩形 int rowsCount = 0;//横列个数 y轴概念 for (int j = 0; j < count; j++) { int index = i * count + j;//buff数组中的索引位置 if (j >= actual)//多余的面片不应该显示 { newData[index].position = Vector4.zero; //newData[index].moveTarget = Vector3.zero; //newData[index].originalPos = Vector4.zero; continue; } // Vector3 pos = Vector3.zero; if (j != 0 && j % row == 0) { rowsCount++; } int columnCount = j - rowsCount * row;//竖列个数 x轴概念 Vector3 pos = new Vector3(origin.x, origin.y, 0) + //这里的xy,存放的是倍数 new Vector3(wwidthBig * rect.position.x, wheightBig * rect.position.y, 0) + new Vector3(wwidth * columnCount + wwidth / 2, wheight * rowsCount + wheight / 2f, Z); newData[index].moveTarget = pos; newData[index].originalPos = Vector4.one; newData[index].indexRC = new Vector2(columnCount, rowsCount); newData[index].picIndex = i % TextureInstanced.Instance.TexArr.depth; newData[index].bigIndex = i % TextureInstanced.Instance.TexArr.depth; //分类编号 Vector4 otherData = new Vector4(); //切换图片索要缓存的数据 otherData.x = delay; //延迟播放的时间 otherData.y = 1f; //Random.Range(0.1f,1f);//切换图片的时间 otherData.z = 0f; //时间缓存 otherData.w = 0f; //插值值 newData[index].velocity = otherData; float w = u * columnCount; float z = v * rowsCount;//rowsCount newData[index].uvOffset = new Vector4(u, v, w, z); newData[index].uv2Offset = new Vector4(u, v, w, z); } #endregion } //计算剩余的不用的面片隐藏掉 int surplusCount = newData.Length - count * rects.Count; if (surplusCount > 0) { for (int i = newData.Length - 1; i >= newData.Length - surplusCount; i--) { newData[i].position = Vector4.zero; } } TextureInstanced.Instance.CurMaterial.SetVector("_WHScale", new Vector4(scale.x, scale.y, 1, 1)); allDataList.AddRange(newData); ComputeBuffer.SetData(allDataList.ToArray()); ComputeShader.SetBuffer(dispatchID, "positionBuffer", ComputeBuffer); ComputeShader.SetBuffer(InitID, "positionBuffer", ComputeBuffer); MoveSpeed = 50f;//更改更快的插值速度 ComputeShader.SetFloat("MoveSpeed", MoveSpeed); InitDisPatch(InitID); }
public void DetectBlobs() { var kernel = cclCompute.FindKernel("init"); cclCompute.SetTexture(kernel, "inTex", inputTex); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.SetInt("numMaxLabel", numMaxLabels); cclCompute.SetInt("texWidth", width); cclCompute.SetInt("texHeight", height); cclCompute.Dispatch(kernel, width / 8, height / 8, 1); kernel = cclCompute.FindKernel("columnWiseLabel"); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.Dispatch(kernel, width / 8, 1, 1); var itr = Mathf.Log(width, 2); var div = 2; for (var i = 0; i < itr; i++) { kernel = cclCompute.FindKernel("mergeLabels"); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.SetInt("div", div); cclCompute.Dispatch(kernel, Mathf.Max(width / (2 << i) / 8, 1), 1, 1); div *= 2; } kernel = cclCompute.FindKernel("clearLabelFlag"); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.SetBuffer(kernel, "labelBuffer", labelAppendBuffer); cclCompute.SetBuffer(kernel, "labelFlg", labelFlgBuffer); cclCompute.Dispatch(kernel, width * height / 8, 1, 1); kernel = cclCompute.FindKernel("setRootLabel"); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.SetBuffer(kernel, "labelFlg", labelFlgBuffer); cclCompute.Dispatch(kernel, width / 8, height / 8, 1); labelAppendBuffer.SetCounterValue(0); kernel = cclCompute.FindKernel("countLabel"); cclCompute.SetBuffer(kernel, "labelFlg", labelFlgBuffer); cclCompute.SetBuffer(kernel, "labelAppend", labelAppendBuffer); cclCompute.Dispatch(kernel, width * height / 8, 1, 1); kernel = cclCompute.FindKernel("clearLabelData"); cclCompute.SetBuffer(kernel, "labelDataBuffer", labelDataBuffer); cclCompute.Dispatch(kernel, numPerLabel * numMaxLabels / 8, 1, 1); for (var i = 0; i < numMaxLabels; i++) { cclCompute.SetInt("labelIdx", i); cclCompute.SetInt("numPerLabel", numPerLabel); labelDataAppendBuffer.SetCounterValue(0); kernel = cclCompute.FindKernel("clearLabelData"); cclCompute.SetBuffer(kernel, "labelDataBuffer", labelDataAppendBuffer); cclCompute.Dispatch(kernel, numPerLabel / 8, 1, 1); kernel = cclCompute.FindKernel("appendLabelData"); cclCompute.SetBuffer(kernel, "labelBuffer", labelAppendBuffer); cclCompute.SetTexture(kernel, "labelTex", labelTex); cclCompute.SetBuffer(kernel, "labelDataAppend", labelDataAppendBuffer); cclCompute.Dispatch(kernel, width / 8, height / 8, 1); kernel = cclCompute.FindKernel("setLabelData"); cclCompute.SetBuffer(kernel, "inLabelDataBuffer", labelDataAppendBuffer); cclCompute.SetBuffer(kernel, "labelDataBuffer", labelDataBuffer); cclCompute.Dispatch(kernel, numPerLabel / 8, 1, 1); } kernel = cclCompute.FindKernel("buildBlobData"); cclCompute.SetBuffer(kernel, "inLabelDataBuffer", labelDataBuffer); cclCompute.SetBuffer(kernel, "labelDataBuffer", accumeLabelDataBuffer); cclCompute.Dispatch(kernel, 1, numMaxLabels, 1); ComputeBuffer.CopyCount(labelAppendBuffer, labelArgBuffer, sizeof(uint)); labelArgBuffer.GetData(args); accumeLabelDataBuffer.GetData(labelData); }
void Update() { if (!isRunningTask) { if (!EditorApplication.isPlaying && animation != null) { animation["BitAnimator.RuntimeAnimation"].time = audio.time; animation.Sample(); } if (!isRunningTask && !EditorApplication.isPaused && target != null && target.core != null && target.recordSlots.Count > 0 && animation != null && audio != null) { target.animationTime = audio.time; if (texture == null) { texture = new RenderTexture(512, 256, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); texture.enableRandomWrite = true; texture.Create(); target.core.texture = texture; } BitAnimator.RecordSlot slot = target.recordSlots[selectedSlot]; BitAnimator.SetMode(ref mode, target.calculateLoudness, target.energyCorrection); target.core.mode = mode; target.core.resolveFactor = target.deconvolution; target.core.SetRemap(slot.remap); float mul = autoMultiply * multiply; ComputeBuffer viewValues = null; switch (plotGraphic) { case PlotGraphic.Histogram: viewValues = target.core.RenderHistogram( texture, audio.time, mul, slot.startFreq, slot.endFreq, slot.ampSmoothness, smoothFrequency); break; case PlotGraphic.Peaks: viewValues = target.core.RenderPeaks( texture, audio.time, scale, mul, slot.startFreq, slot.endFreq, slot.ampSmoothness, smoothFrequency, slot.damping); break; case PlotGraphic.Spectrum: viewValues = target.core.RenderSpectrum( texture, audio.time, scale, mul, slot.startFreq, slot.endFreq, slot.ampSmoothness, smoothFrequency); break; /*case PlotGraphic.Tones: * target.core.RenderMainTone( * texture, * audio.time, * scale, * mul, * slot.ampSmoothness, * smoothFrequency); * break; * case PlotGraphic.Wave: * rms = target.core.RenderWave(texture, audio.time, 2.0f, mul, slot.ampSmoothness, smoothFrequency); break;*/ } if (viewValues != null) { float[] values = new float[target.core.spectrumChunks]; viewValues.GetData(values); Array.Sort(values); median = values[target.core.spectrumChunks / 2]; maximum = Math.Max(0.00001f, values[target.core.spectrumChunks - 1]); rms = target.core.GetRMS(values); if (resetInNextFrame) { if (float.IsInfinity(multiply) || float.IsNaN(multiply)) { multiply = 1.0f; } if (float.IsInfinity(autoMultiply) || float.IsNaN(autoMultiply)) { autoMultiply = 1.0f; } if (float.IsInfinity(maximum) || float.IsNaN(maximum)) { maximum = 1.0f; } autoMultiply = 0.95f / (maximum / autoMultiply / multiply); resetInNextFrame = false; } if (audio.isPlaying && (mode & ComputeProgram.VisualizationMode.RuntimeNormalize) != 0) { float delta = 0.95f / (maximum / autoMultiply / multiply) - autoMultiply; if (delta < 0) { float k = 1.0f - Mathf.Exp(-Time.deltaTime * autoNormilizeSpeed); autoMultiply += k * delta; } } } Repaint(); } } }
IEnumerator SetupParticles() { calculating = true; lck = new object(); maxRange = Mathf.NegativeInfinity; if (anim != null) { StopCoroutine(anim); } int totalFrames = 30; int defaultParticlesPerES = particleCount / expressionSets.Count; //number of frames used for each expression set. int framesPerES = totalFrames / expressionSets.Count; num_threads = SystemInfo.processorCount; int missingParticles = 0; threadResults = new List <Particle[]>(); int expressionNumber = 0; foreach (ExpressionSet es in expressionSets) { particlesPerES = defaultParticlesPerES + missingParticles; missingParticles = 0; expressionNumber++; //soft copy of the expressionSet. Do not edit actual expressions using this. ExpressionSet expressionSet = es.ShallowCopy(); //remove unused parameters string[] keys = new string[expressionSet.ranges.Keys.Count]; expressionSet.ranges.Keys.CopyTo(keys, 0); foreach (string op in keys) { bool used = false; foreach (ExpressionSet.ExpOptions key in expressionSet.expressions.Keys) { if (expressionSet.expressions[key].tokens.Contains(op)) { used = true; } } if (!used && expressionSet.ranges.Count > 1) { expressionSet.RemoveRange(op); } } int depth = expressionSet.ranges.Count; int width = (int)Mathf.Pow(particlesPerES, 1f / (float)depth); List <int[]> samples = SetupSamples(depth, width); int thread_chunk = Mathf.CeilToInt(samples.Count / 4); missingParticles += particlesPerES - samples.Count; Thread[] threads = new Thread[num_threads]; int t = 0; for (t = 0; t < num_threads; t++) { int tc = t; int TIDc = tc; threads[t] = new Thread(() => ThreadedEvaluate(samples.GetRange(tc * thread_chunk, Math.Min(thread_chunk, samples.Count - tc * thread_chunk)), expressionSet, TIDc)); threads[t].Start(); } while (framesPerES-- != 0) { yield return(null); } for (t = 0; t < num_threads; t++) { threads[t].Join(); } framesPerES = totalFrames / expressionSets.Count; } List <Particle> temp = new List <Particle>(); foreach (Particle[] array in threadResults) { temp.AddRange(array); } Particle lastParticle = temp[temp.Count - 1]; for (int i = 0; i < missingParticles; i++) { temp.Add(lastParticle); } dest = temp.ToArray(); for (int i = 0; i < dest.Length; i++) { Vector3 pos = (maxRange == 0) ? Vector3.zero : dest[i].position * 10f / maxRange; dest[i].position = pos; dest[i].color = new Color(Mathf.Pow((pos.x + 10) / 20, 2), Mathf.Pow((pos.y + 10) / 20, 2), Mathf.Pow((pos.z + 10) / 20, 2)); } xAxis.Max = maxRange; xAxis.Min = -maxRange; yAxis.Max = maxRange; yAxis.Min = -maxRange; zAxis.Max = maxRange; zAxis.Min = -maxRange; currentScale = (maxRange == 0) ? 0 : 10 / maxRange; pBuffer.GetData(particles); sBuffer.SetData(particles); dBuffer.SetData(dest); animProgress = 0; calculating = false; }
void OnSceneGUI(SceneView sceneView) { if (Selection.activeGameObject == null) { return; } var gameobject = Selection.activeGameObject; Mesh mesh = null; var renderer = gameobject.GetComponent <MeshFilter>(); if (renderer != null) { mesh = renderer.sharedMesh; } var skinnedrenderer = gameobject.GetComponent <SkinnedMeshRenderer>(); if (skinnedrenderer != null) { mesh = skinnedrenderer.sharedMesh; } if (mesh == null) { return; } var transform = gameobject.transform.localToWorldMatrix; gpu_vertices.SetData(mesh.vertices); gpu_normals.SetData(mesh.normals); gpu_colours.SetData(mesh.colors); pointMaterial.SetBuffer("points", gpu_vertices); pointMaterial.SetBuffer("normals", gpu_normals); pointMaterial.SetBuffer("colours", gpu_colours); //pointMaterial.SetBuffer("flags", gpu_flags); //must use SetRandomWriteTarget instead. Graphics.SetRandomWriteTarget(1, gpu_flags, true); pointMaterial.SetMatrix("ObjectToWorld", transform); pointMaterial.SetFloat("Size", size); var mousePosition = Event.current.mousePosition; mousePosition.y = sceneView.camera.pixelHeight - mousePosition.y; var tool = new Vector4(mousePosition.x, mousePosition.y, brushSize, painting ? 1 : -1); pointMaterial.SetVector("Tool", tool); pointMaterial.SetInt("CullBackfacing", cullBackfacing ? 1 : 0); pointMaterial.SetPass(0); Graphics.DrawProcedural(MeshTopology.Points, mesh.vertexCount); Handles.BeginGUI(); if (mouseOverWindow is SceneView) { if (Event.current.type == EventType.Repaint) { DrawCircleBrush(Color.white, brushSize); } } Handles.EndGUI(); int controlid = GUIUtility.GetControlID(FocusType.Passive); if (Event.current.button == 0) { switch (Event.current.type) { case EventType.MouseDown: case EventType.MouseDrag: gpu_flags.GetData(cpu_flags); for (int i = 0; i < mesh.vertexCount; i++) { if (((Flags)cpu_flags[i] & Flags.Selected) > 0) { selected.Add(i); } } GUIUtility.hotControl = controlid; Event.current.Use(); break; } } sceneView.Repaint(); }
private Texture3D ComputeSDF() { // Create the voxel texture. Texture3D voxels = new Texture3D(resolution, resolution, resolution, TextureFormat.RGBAHalf, false); voxels.anisoLevel = 1; voxels.filterMode = FilterMode.Trilinear; voxels.wrapMode = TextureWrapMode.Clamp; // Get an array of pixels from the voxel texture, create a buffer to // hold them, and upload the pixels to the buffer. Color[] pixelArray = voxels.GetPixels(0); ComputeBuffer pixelBuffer = new ComputeBuffer(pixelArray.Length, sizeof(float) * 4); pixelBuffer.SetData(pixelArray); // Get an array of triangles from the mesh. Vector3[] meshVertices = mesh.vertices; int[] meshTriangles = mesh.GetTriangles(subMeshIndex); Triangle[] triangleArray = new Triangle[meshTriangles.Length / 3]; for (int t = 0; t < triangleArray.Length; t++) { triangleArray[t].a = meshVertices[meshTriangles[3 * t + 0]]; // - mesh.bounds.center; triangleArray[t].b = meshVertices[meshTriangles[3 * t + 1]]; // - mesh.bounds.center; triangleArray[t].c = meshVertices[meshTriangles[3 * t + 2]]; // - mesh.bounds.center; } // Create a buffer to hold the triangles, and upload them to the buffer. ComputeBuffer triangleBuffer = new ComputeBuffer(triangleArray.Length, sizeof(float) * 3 * 3); triangleBuffer.SetData(triangleArray); // Instantiate the compute shader from resources. // ComputeShader compute = (ComputeShader)Instantiate(Resources.Load("SDF")); ComputeShader compute = AssetDatabase.LoadAssetAtPath <ComputeShader>("Assets/shaders/SDF.compute"); int kernel = compute.FindKernel("CSMain"); // Upload the pixel buffer to the GPU. compute.SetBuffer(kernel, "pixelBuffer", pixelBuffer); compute.SetInt("pixelBufferSize", pixelArray.Length); // Upload the triangle buffer to the GPU. compute.SetBuffer(kernel, "triangleBuffer", triangleBuffer); compute.SetInt("triangleBufferSize", triangleArray.Length); // Calculate and upload the other necessary parameters. compute.SetInt("textureSize", resolution); Vector3 minExtents = Vector3.zero; Vector3 maxExtents = Vector3.zero; foreach (Vector3 v in mesh.vertices) { for (int i = 0; i < 3; i++) { minExtents[i] = Mathf.Min(minExtents[i], v[i]); maxExtents[i] = Mathf.Max(maxExtents[i], v[i]); } } compute.SetVector("minExtents", minExtents - Vector3.one * padding); compute.SetVector("maxExtents", maxExtents + Vector3.one * padding); Debug.Log("Extents : " + (minExtents - Vector3.one * padding).ToString() + "~" + (maxExtents + Vector3.one * padding).ToString()); // Debug.Log(minExtents - Vector3.one*padding); // Debug.Log(maxExtents + Vector3.one*padding); // Compute the SDF. compute.Dispatch(kernel, pixelArray.Length / 256 + 1, 1, 1); // Destroy the compute shader and release the triangle buffer. // DestroyImmediate(compute); triangleBuffer.Release(); // Retrieve the pixel buffer and reapply it to the voxels texture. pixelBuffer.GetData(pixelArray); pixelBuffer.Release(); voxels.SetPixels(pixelArray, 0); voxels.Apply(); // Return the voxels texture. return(voxels); }
public void UpdateChunkMesh(Chunk chunk, bool?blocking = null) { int numVoxelsPerAxis = numPointsPerAxis - 1; int numThreadsPerAxis = Mathf.CeilToInt(numVoxelsPerAxis / (float)threadGroupSize); float pointSpacing = boundsSize / (numPointsPerAxis - 1); bool blockGpu = blocking ?? blockingGpu; Vector3Int coord = chunk.coord; Vector3 centre = CentreFromCoord(coord); Vector3 worldBounds = new Vector3(numChunks.x, numChunks.y, numChunks.z) * boundsSize; densityGenerator.Generate(pointsBuffer, numPointsPerAxis, boundsSize, worldBounds, centre, offset, pointSpacing); void SetupShader() { triangleBuffer.SetCounterValue(0); shader.SetBuffer(0, "points", pointsBuffer); shader.SetBuffer(0, "triangles", triangleBuffer); shader.SetInt("numPointsPerAxis", numPointsPerAxis); shader.SetFloat("isoLevel", isoLevel); shader.Dispatch(0, numThreadsPerAxis, numThreadsPerAxis, numThreadsPerAxis); } ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0); void HandleReadBack() { int[] triCountArray = { 0 }; triCountBuffer.GetData(triCountArray); int numTris = triCountArray[0]; if (numTris > maxTris || tris == null || vertices == null || meshTriangles == null) { maxTris = numTris; tris = new Triangle[numTris]; vertices = new Vector3[numTris * 3]; meshTriangles = new int[numTris * 3]; } // Get triangle data from shader triangleBuffer.GetData(tris, 0, 0, numTris); Mesh mesh = chunk.mesh; mesh.Clear(); for (int i = 0; i < numTris; i++) { for (int j = 0; j < 3; j++) { meshTriangles[i * 3 + j] = i * 3 + j; vertices[i * 3 + j] = tris[i][j]; } } mesh.vertices = vertices; mesh.triangles = meshTriangles; var scale = chunk.GetComponent <Transform>().localScale; mesh.SetUVs(0, UvCalculator.CalculateUVs(vertices, scale.magnitude)); NormalSolver.RecalculateNormals(mesh, normalDegrees); chunk.UpdateColliders(); } if (!blockGpu) { chunk.asyncOp0 = null; chunk.asyncOp1 = null; chunk.asyncOp2 = null; var async0 = AsyncGPUReadback.Request(pointsBuffer, delegate(AsyncGPUReadbackRequest a0) { SetupShader(); var async1 = AsyncGPUReadback.Request(triangleBuffer, delegate(AsyncGPUReadbackRequest a1) { // Get number of triangles in the triangle buffer ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0); var async2 = AsyncGPUReadback.Request(triCountBuffer, delegate(AsyncGPUReadbackRequest a2) { HandleReadBack(); }); chunk.asyncOp2 = async2; }); chunk.asyncOp1 = async1; }); chunk.asyncOp0 = async0; } else { SetupShader(); ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0); HandleReadBack(); } }
public void BigUploads() { if (!SystemInfo.supportsComputeShaders) { Assert.Ignore("Skipped due to platform/computer not supporting compute shaders"); return; } var initialData = new ExampleStruct[4 * 1024]; for (int i = 0; i < initialData.Length; ++i) { initialData[i] = new ExampleStruct { someData = i }; } var buffer = new ComputeBuffer(initialData.Length, UnsafeUtility.SizeOf <ExampleStruct>()); buffer.SetData(initialData); var uploader = new SparseUploader(buffer); var newData = new ExampleStruct[312]; for (int i = 0; i < newData.Length; ++i) { newData[i] = new ExampleStruct { someData = i + 3000 }; } var newData2 = new ExampleStruct[316]; for (int i = 0; i < newData2.Length; ++i) { newData2[i] = new ExampleStruct { someData = i + 4000 }; } var tsu = uploader.Begin(UnsafeUtility.SizeOf <ExampleStruct>() * (newData.Length + newData2.Length), 2); unsafe { fixed(void *ptr = newData) { tsu.AddUpload(ptr, newData.Length * 4, 512 * 4); } fixed(void *ptr2 = newData2) { tsu.AddUpload(ptr2, newData2.Length * 4, 1136 * 4); } } uploader.EndAndCommit(tsu); var resultingData = new ExampleStruct[initialData.Length]; buffer.GetData(resultingData); for (int i = 0; i < resultingData.Length; ++i) { if (i < 512) { Assert.AreEqual(i, resultingData[i].someData); } else if (i < 824) { Assert.AreEqual(i - 512 + 3000, resultingData[i].someData); } else if (i < 1136) { Assert.AreEqual(i, resultingData[i].someData); } else if (i < 1452) { Assert.AreEqual(i - 1136 + 4000, resultingData[i].someData); } else { Assert.AreEqual(i, resultingData[i].someData); } } uploader.Dispose(); buffer.Dispose(); }
protected override void Compute() { const string method = nameof(Compute); logger.Log(Logger.EventType.Method, $"{Context(method)}: started."); stopwatch.Record(Category.Buffer, SetShaderConstants); // get kernel handles. stopwatch.Start(Category.Shader); var handlePart1 = shader.FindKernel("get_dists_part1"); var handleAbsorptions = shader.FindKernel("get_absorptions"); stopwatch.Stop(Category.Shader); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Retrieved kernel handles."); // make buffers. var outputBufferCell = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var outputBufferSample = new ComputeBuffer(coordinates.Length, sizeof(float) * 2); var absorptionsBuffer = new ComputeBuffer(coordinates.Length, sizeof(float) * 3); logger.Log(Logger.EventType.Data, $"{Context(method)}: Created buffers."); stopwatch.Record(Category.Buffer, () => { _inputBuffer.SetData(coordinates); // set buffers for part1 kernel. shader.SetBuffer(handlePart1, "coordinates", _inputBuffer); shader.SetBuffer(handlePart1, "distances_sample", outputBufferSample); shader.SetBuffer(handlePart1, "distances_cell", outputBufferCell); }); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Wrote data to buffers."); // compute part1 distances. logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: part1 distances kernel dispatch."); stopwatch.Record(Category.Shader, () => shader.Dispatch(handlePart1, threadGroupsX, 1, 1)); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: part1 distances kernel return."); var absorptions = new Vector3[_nrCoordinates]; Array.Clear(absorptions, 0, absorptions.Length); stopwatch.Record(Category.Buffer, () => shader.SetBuffer(handleAbsorptions, "coordinates", _inputBuffer)); // for each angle: for (int j = 0; j < _nrAnglesTheta; j++) { var j1 = j; stopwatch.Record(Category.Buffer, () => { shader.SetFloats("rot", (float)Math.Cos(Math.PI - GetThetaAt(j1)), (float)Math.Sin(Math.PI - GetThetaAt(j1))); shader.SetBuffer(handleAbsorptions, "distances_sample", outputBufferSample); shader.SetBuffer(handleAbsorptions, "distances_cell", outputBufferCell); shader.SetBuffer(handleAbsorptions, "absorptions", absorptionsBuffer); }); stopwatch.Record(Category.Shader, () => shader.Dispatch(handleAbsorptions, threadGroupsX, 1, 1)); stopwatch.Record(Category.Buffer, () => absorptionsBuffer.GetData(absorptions)); _absorptionFactors[j] = GetAbsorptionFactor(absorptions); } logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Calculated all absorptions."); // release buffers. stopwatch.Record(Category.Buffer, () => { _inputBuffer.Release(); outputBufferCell.Release(); outputBufferSample.Release(); absorptionsBuffer.Release(); }); logger.Log(Logger.EventType.ShaderInteraction, $"{Context(method)}: Shader buffers released."); logger.Log(Logger.EventType.Method, $"{Context(method)}: done."); }
public void TestComputeShader(Vector3 postion, float[] heightmap) { Init_perm(0); int f_sizeX = 10; int f_sizeZ = 10; int perMeterX = 4; int perMeterZ = 4; int voxelOffset_x = 10; int voxelOffset_y = 10; Heightmap = heightmap; intermediate = new Plant[f_sizeX * perMeterX * f_sizeZ * perMeterZ]; int indexBuff_size = f_sizeX * perMeterX * f_sizeZ * perMeterZ * 8 * 3; Debug.Log("indexBuff_size: " + indexBuff_size); vertexData = new VertexData[indexBuff_size]; indices = GenIndices(f_sizeX * perMeterX, f_sizeZ * perMeterZ); ComputeBuffer buffer = new ComputeBuffer(heightmap.Length, sizeof(float)); buffer.SetData(heightmap); ComputeBuffer output_buff = new ComputeBuffer(intermediate.Length, Plant.GetSize()); output_buff.SetData(intermediate); //ComputeBuffer g_buff = new ComputeBuffer(indexBuff_size, sizeof(int)); GraphicsBuffer g_buff = new GraphicsBuffer(GraphicsBuffer.Target.Index, indices.Length, sizeof(int)); g_buff.SetData(indices); ComputeBuffer v_buff = new ComputeBuffer(indexBuff_size, VertexData.GetSize()); v_buff.SetData(vertexData); int k = shader.FindKernel("CSMain"); int c_k = shader.FindKernel("CompileMesh"); shader.SetInt("sizeX", SmoothVoxelSettings.ChunkSizeX); shader.SetInt("sizeZ", SmoothVoxelSettings.ChunkSizeZ); shader.SetInt("f_sizeX", f_sizeX); shader.SetInt("f_sizeZ", f_sizeZ); shader.SetInt("perMeterX", perMeterX); shader.SetInt("perMeterZ", perMeterZ); shader.SetInt("voxel_offset_x", voxelOffset_x); shader.SetInt("voxel_offset_z", voxelOffset_y); shader.SetBuffer(k, "heightmap", buffer); shader.SetBuffer(k, "intermediate", output_buff); shader.SetBuffer(c_k, "intermediate", output_buff); //shader.SetBuffer(c_k, "indices", g_buff); shader.SetBuffer(c_k, "vertex", v_buff); shader.Dispatch(k, f_sizeX * 4, 1, f_sizeZ * 4); shader.Dispatch(c_k, 1, 1, 1); v_buff.GetData(vertexData); g_buff.GetData(indices); verts = new List <Vector3>(); uv = new List <Vector2>(); normals = new List <Vector3>(); for (int i = 0; i < indexBuff_size; i++) { verts.Add(vertexData[i].Vertex); uv.Add(vertexData[i].UV); normals.Add(vertexData[i].Normal); } rend = GetComponent <MeshRenderer>(); rend.material.SetPass(0); rend.material.SetBuffer("_Vertex", v_buff); rend.material.SetTexture("_permutation", perm_tex); MeshFilter filter = gameObject.GetComponent <MeshFilter>(); Mesh mesh = new Mesh(); mesh.vertices = new Vector3[indexBuff_size];//verts.ToArray(); mesh.triangles = indices; //mesh.uv = uv.ToArray(); Vector3 corner = postion; //new Bounds() Bounds b = new Bounds(corner + new Vector3(SmoothVoxelSettings.MeterSizeX / 2 - 0.5f, SmoothVoxelSettings.MeterSizeY / 2 - 0.5f, SmoothVoxelSettings.MeterSizeZ / 2 - 0.5f), new Vector3(SmoothVoxelSettings.MeterSizeX + 1, SmoothVoxelSettings.MeterSizeY + 1, SmoothVoxelSettings.MeterSizeZ + 1)); mesh.bounds = b; filter.sharedMesh = mesh; inited = true; //Vector3 corner = postion + new Vector3(voxelOffset_x, 0, voxelOffset_y); //Bounds b = new Bounds(corner + new Vector3(f_sizeX / 2, SmoothVoxelSettings.ChunkSizeY / 2, f_sizeZ / 2), new Vector3(f_sizeX / 2, SmoothVoxelSettings.ChunkSizeY / 2, f_sizeZ / 2)); //Graphics.DrawProcedural(rend.material, b, MeshTopology.Triangles, indexBuff_size); // Graphics.DrawProceduralIndirect(rend.material, b, MeshTopology.Triangles, g_buff); //Graphics.DrawProcedural(rend.material, b, MeshTopology.Triangles, g_buff, indices.Length); return; output_buff.GetData(intermediate); List <int> tris = new List <int>(); for (int x = 0; x < f_sizeX * 4; x++) { for (int z = 0; z < f_sizeZ * 4; z++) { Plant res = intermediate[x * (f_sizeZ * 4) + z]; int offset = verts.Count; verts.AddRange(res.q1.GetVerts()); tris.AddRange(res.q1.GetTris(offset)); uv.AddRange(res.q1.GetUVs()); verts.AddRange(res.q2.GetVerts()); tris.AddRange(res.q2.GetTris(offset)); uv.AddRange(res.q2.GetUVs()); verts.AddRange(res.q3.GetVerts()); tris.AddRange(res.q3.GetTris(offset)); uv.AddRange(res.q3.GetUVs()); //Debug.DrawRay(verts[0], res.normal, Color.green, 1000000); //Debug.Log("|" + res.q1.ToString() + " " + res.q2.ToString() + " " + res.q3.ToString() + " | "); //Vector4 res = output[x * (20 * 4) + z]; //Vector3 normal = res; //float height = res.w; //Vector3 point = new Vector3(x / 4f, height, z / 4f); //Debug.DrawRay(point, normal, Color.green, 1000000); /*if (x % 8 == 0 && * z % 8 == 0) * { * Vector3 t1 = GetTangent(normal, Vector3.forward); * Vector3 t2 = GetTangent(normal, Vector3.right); * * Quaternion q1 = Quaternion.LookRotation(normal, Vector3.up); * //Quaternion q2 = Quaternion.LookRotation(t2, Vector3.up); * * * * Debug.DrawRay(point, normal, Color.green, 1000000); * //Debug.DrawRay(point, t1, Color.blue, 1000000); * //Debug.DrawRay(point, t2, Color.red, 1000000); * //Quaternion quat = q1 * q2; * //Instantiate(obj, point, q1); * }*/ } } Debug.Log("Num tris: " + tris.Count); mesh.vertices = verts.ToArray(); mesh.triangles = tris.ToArray(); mesh.uv = uv.ToArray(); mesh.RecalculateNormals(); filter.sharedMesh = mesh; }
public void BuildMesh() { float startTime = Time.realtimeSinceStartup; // NOISE VOLUME! RenderTexture DensityVolume = new RenderTexture(16, 16, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.sRGB); DensityVolume.volumeDepth = 16; DensityVolume.isVolume = true; DensityVolume.enableRandomWrite = true; DensityVolume.filterMode = FilterMode.Bilinear; DensityVolume.wrapMode = TextureWrapMode.Repeat; DensityVolume.Create(); int mgen_id = CShaderSimplex.FindKernel("FillEmpty"); // uses renderTexture rather than StructuredBuffer? CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume); // Links RenderTexture to the "Result" RWTexture in the compute shader? CShaderSimplex.Dispatch(mgen_id, 1, 1, 16); // run computeShader "FillEmpty" with 1 x 1 x 31 threadGroups? mgen_id = CShaderSimplex.FindKernel("Simplex3d"); CShaderSimplex.SetTexture(mgen_id, "Result", DensityVolume); CShaderSimplex.Dispatch(mgen_id, 1, 1, 16); // Fill shared RenderTexture with GPU simplex Noise ComputeBuffer cBufferSegmentTransform = new ComputeBuffer(critterSegmentTransforms.Length, sizeof(float) * (3 + 3 + 4)); cBufferSegmentTransform.SetData(critterSegmentTransforms); int kernelID = CShaderBuildMC.FindKernel("CSMain"); CShaderBuildMC.SetBuffer(kernelID, "segmentTransformBuffer", cBufferSegmentTransform); CShaderBuildMC.SetTexture(kernelID, "noise_volume", DensityVolume); // Noise 3D texture //Debug.Log(DensityVolume.colorBuffer.ToString()); // Figure out how many chunks are needed: int numChunksX = Mathf.CeilToInt(GlobalBoundingBoxDimensions.x / (cellResolution * 8f)); int numChunksY = Mathf.CeilToInt(GlobalBoundingBoxDimensions.y / (cellResolution * 8f)); int numChunksZ = Mathf.CeilToInt(GlobalBoundingBoxDimensions.z / (cellResolution * 8f)); //Debug.Log("numChunks: (" + numChunksX.ToString() + ", " + numChunksY.ToString() + ", " + numChunksZ.ToString() + ")"); int totalNumChunks = numChunksX * numChunksY * numChunksZ; Poly[][] PolyArrayArray = new Poly[totalNumChunks][]; // This will hold the mesh data from the chunks calculated on the GPU int[] numPolysArray = new int[totalNumChunks]; int totalNumPolys = 0; // Get each chunk! int chunkIndex = 0; for (int x = 0; x < numChunksX; x++) { for (int y = 0; y < numChunksY; y++) { for (int z = 0; z < numChunksZ; z++) { // Figure out chunk offset amount: Vector3 chunkOffset = new Vector3(cellResolution * 8f * x, cellResolution * 8f * y, cellResolution * 8f * z) + GlobalBoundingBoxOffset - (GlobalBoundingBoxDimensions / 2f); int[] numPolys = new int[1]; ComputeBuffer cBufferNumPoly = new ComputeBuffer(1, sizeof(int)); cBufferNumPoly.SetData(numPolys); int id = CShaderBuildMC.FindKernel("CSMain"); CShaderBuildMC.SetInt("_CalcNumPolys", 1); // only calculate how many tris so I can correctly size the poly buffer CShaderBuildMC.SetFloat("_GlobalOffsetX", chunkOffset.x); CShaderBuildMC.SetFloat("_GlobalOffsetY", chunkOffset.y); CShaderBuildMC.SetFloat("_GlobalOffsetZ", chunkOffset.z); CShaderBuildMC.SetFloat("_CellSize", cellResolution); CShaderBuildMC.SetVector("_ColorPrimary", colorPrimary); CShaderBuildMC.SetVector("_ColorSecondary", colorSecondary); CShaderBuildMC.SetFloat("_ColorNoiseScale", colorNoiseScale); CShaderBuildMC.SetFloat("_ColorSmlAmplitude", colorSmlAmplitude); CShaderBuildMC.SetFloat("_ColorMedAmplitude", colorMedAmplitude); CShaderBuildMC.SetFloat("_ColorLrgAmplitude", colorLrgAmplitude); CShaderBuildMC.SetFloat("_ColorContrast", colorContrast); CShaderBuildMC.SetFloat("_ColorThreshold", colorThreshold); CShaderBuildMC.SetVector("_SkinNoiseScale", skinNoiseScale); CShaderBuildMC.SetFloat("_SkinNoiseAmplitude", skinNoiseAmplitude); CShaderBuildMC.SetVector("_SkinLocalTaper", skinLocalTaper); CShaderBuildMC.SetVector("_SkinLocalSinFreq", skinLocalSinFreq); CShaderBuildMC.SetVector("_SkinLocalSinAmp", skinLocalSinAmp); // Local Segment-space modifications, sin, taper, etc. CShaderBuildMC.SetBuffer(id, "numPolyBuffer", cBufferNumPoly); CShaderBuildMC.Dispatch(id, 1, 1, 1); // calc num polys cBufferNumPoly.GetData(numPolys); // get numPolys //Debug.Log("Chunk: " + (z + (numChunksZ * y) + (numChunksZ * numChunksY * x)).ToString() + ", cBufferNumPoly.GetData(numPolys): " + numPolys[0].ToString() + ", chunkOffset: " + chunkOffset.ToString()); totalNumPolys += numPolys[0]; numPolysArray[chunkIndex] = numPolys[0]; if (numPolys[0] > 0) // only do this if there was at least 1 triangle in the test pass { Poly[] polyArray = new Poly[numPolys[0]]; int cBufferStride = sizeof(float) * (18 + 9 + 6) + sizeof(int) * (6); ComputeBuffer cBuffer = new ComputeBuffer(numPolys[0], cBufferStride); // 18 floats x 4 bytes/float = 72 + COLORS! 9 x 4 = 36 = 108 + BONES! 6x4 = 24 + 6 xint... cBuffer.SetData(polyArray); CShaderBuildMC.SetBuffer(id, "buffer", cBuffer); CShaderBuildMC.SetInt("_CalcNumPolys", 0); // Actually calc tris CShaderBuildMC.Dispatch(id, 1, 1, 1); cBuffer.GetData(polyArray); // return data from GPU PolyArrayArray[chunkIndex] = polyArray; cBuffer.Dispose(); } cBufferNumPoly.Dispose(); chunkIndex++; } } } CritterDecorationsTest.decorationStruct[] points = new CritterDecorationsTest.decorationStruct[totalNumPolys]; //Construct mesh using received data int vindex = 0; int decindex = 0; // Why same number of tris as vertices? == // because all triangles have duplicate verts - no shared vertices? Vector3[] vertices = new Vector3[totalNumPolys * 3]; Color[] colors = new Color[totalNumPolys * 3]; int[] tris = new int[totalNumPolys * 3]; Vector2[] uvs = new Vector2[totalNumPolys * 3]; Vector3[] normals = new Vector3[totalNumPolys * 3]; BoneWeight[] weights = new BoneWeight[totalNumPolys * 3]; //Parse triangles for (int i = 0; i < PolyArrayArray.Length; i++) { if (numPolysArray[i] > 0) // only do this if there was at least 1 triangle in the test pass { for (int ix = 0; ix < numPolysArray[i]; ix++) { Vector3 vPos; Vector3 vOffset = new Vector3(0, 0, 0); //??? offsets all vertices by this amount, but why 30?? //A1,A2,A3 vPos = new Vector3(PolyArrayArray[i][ix].A1, PolyArrayArray[i][ix].A2, PolyArrayArray[i][ix].A3) + vOffset; vertices[vindex] = vPos * _Scale; normals[vindex] = new Vector3(PolyArrayArray[i][ix].NA1, PolyArrayArray[i][ix].NA2, PolyArrayArray[i][ix].NA3); tris[vindex] = vindex; uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x); colors[vindex] = new Color(PolyArrayArray[i][ix].CAR, PolyArrayArray[i][ix].CAG, PolyArrayArray[i][ix].CAB, 1.0f); weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexA0; weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexA1; weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightA0; weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightA1; points[decindex].pos = vPos; points[decindex].normal = normals[vindex]; points[decindex].color = new Vector3(colors[vindex].r, colors[vindex].g, colors[vindex].b); decindex++; vindex++; //B1,B2,B3 vPos = new Vector3(PolyArrayArray[i][ix].B1, PolyArrayArray[i][ix].B2, PolyArrayArray[i][ix].B3) + vOffset; vertices[vindex] = vPos * _Scale; normals[vindex] = new Vector3(PolyArrayArray[i][ix].NB1, PolyArrayArray[i][ix].NB2, PolyArrayArray[i][ix].NB3); tris[vindex] = vindex; uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x); colors[vindex] = new Color(PolyArrayArray[i][ix].CBR, PolyArrayArray[i][ix].CBG, PolyArrayArray[i][ix].CBB, 1.0f); weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexB0; weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexB1; weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightB0; weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightB1; vindex++; //C1,C2,C3 vPos = new Vector3(PolyArrayArray[i][ix].C1, PolyArrayArray[i][ix].C2, PolyArrayArray[i][ix].C3) + vOffset; vertices[vindex] = vPos * _Scale; normals[vindex] = new Vector3(PolyArrayArray[i][ix].NC1, PolyArrayArray[i][ix].NC2, PolyArrayArray[i][ix].NC3); tris[vindex] = vindex; uvs[vindex] = new Vector2(vertices[vindex].z, vertices[vindex].x); colors[vindex] = new Color(PolyArrayArray[i][ix].CCR, PolyArrayArray[i][ix].CCG, PolyArrayArray[i][ix].CCB, 1.0f); weights[vindex].boneIndex0 = PolyArrayArray[i][ix].BoneIndexC0; weights[vindex].boneIndex1 = PolyArrayArray[i][ix].BoneIndexC1; weights[vindex].weight0 = PolyArrayArray[i][ix].BoneWeightC0; weights[vindex].weight1 = PolyArrayArray[i][ix].BoneWeightC1; vindex++; } } } //We have got all data and are ready to setup a new mesh! Mesh newMesh = new Mesh(); newMesh.vertices = vertices; newMesh.uv = uvs; //Unwrapping.GeneratePerTriangleUV(NewMesh); newMesh.triangles = tris; newMesh.normals = normals; //NewMesh.RecalculateNormals(); newMesh.colors = colors; newMesh.Optimize(); // Set up SKINNING!!!: Transform[] bones = new Transform[critter.critterSegmentList.Count]; Matrix4x4[] bindPoses = new Matrix4x4[critter.critterSegmentList.Count]; // Try just using existing critter's GameObjects/Transforms: for (int seg = 0; seg < critter.critterSegmentList.Count; seg++) { bones[seg] = critter.critterSegmentList[seg].transform; bindPoses[seg] = bones[seg].worldToLocalMatrix * transform.localToWorldMatrix; // ????????????????? // the bind pose is the inverse of inverse transformation matrix of the bone, when the bone is in the bind pose .... unhelpful .... } newMesh.boneWeights = weights; newMesh.bindposes = bindPoses; SkinnedMeshRenderer skinnedMeshRenderer = this.GetComponent <SkinnedMeshRenderer>(); skinnedMeshRenderer.bones = bones; skinnedMeshRenderer.sharedMesh = newMesh; skinnedMeshRenderer.enabled = true; cBufferSegmentTransform.Release(); critterDecorationsTest.TurnOn(points); float calcTime = Time.realtimeSinceStartup - startTime; Debug.Log("MeshCreated! " + calcTime.ToString()); }