private static void FillVoxels(CommandBuffer commandBuffer, VoxelizationResources resources, VoxelsData data, Mesh mesh) { var projections = new Matrix4x4[3] { GetProjection(data, 0, 2), // project on X GetProjection(data, 1, 2), // project on Y GetProjection(data, 2, 2) // project on Z }; commandBuffer.SetGlobalMatrixArray(VoxelizationResources.PROJECTIONS, projections); // set shader parameters commandBuffer.SetGlobalVector(VoxelizationResources.VOLUME_SIZE, new Vector4(data.Voxels.width, data.Voxels.height, data.Voxels.volumeDepth, 0)); // pixel shader actual output is the 3d texture commandBuffer.SetRandomWriteTarget(1, data.VoxelsRTId); // trigger rasterization to fill highest resolution voxels commandBuffer.BeginSample(FILL_VOXELS); commandBuffer.DrawMesh(mesh, Matrix4x4.identity, resources.VoxelizationMaterial); commandBuffer.EndSample(FILL_VOXELS); }
/// <summary> /// Voxelize the surface of a mesh. Only color is constructed at the moment. /// </summary> /// <param name="commandBuffer">Command buffer receiving gpu instuctions</param> /// <param name="data">Voxelization results</param> /// <param name="mesh">Mesh to voxelize</param> public static void VoxelizeSurface(CommandBuffer commandBuffer, VoxelizationResources resources, VoxelsData data, Mesh mesh) { Begin(commandBuffer, resources, data, mesh); FillVoxels(commandBuffer, resources, data, mesh); FindFilledVoxelInstances(commandBuffer, resources, data, mesh); // generate voxels mips // TODO End(commandBuffer, resources, data, mesh); }
private static void FindFilledVoxelInstances(CommandBuffer commandBuffer, VoxelizationResources resources, VoxelsData data, Mesh mesh) { // reset number of filled voxels data.FilledVoxelInstances.SetCounterValue(0); // set compute shader parameters var cs = resources.VoxelizationPostProcessShader; var kernel = resources.FindFilledVoxelsKernel; cs.SetTexture(kernel, VoxelizationResources.VOXELS, data.Voxels); cs.SetBuffer(kernel, VoxelizationResources.FILLED_VOXELS_INSTANCES, data.FilledVoxelInstances); cs.SetInts(VoxelizationResources.VOLUME_SIZE, new int[] { data.Voxels.width, data.Voxels.height, data.Voxels.volumeDepth }); var volumeBounds = data.VolumeBounds; // transform index space to mesh local space // lhs system; matrix must be read from // last to first var indexToPosition = // finally mesh local space Matrix4x4.Translate(volumeBounds.center) * // [-0.5, 0.5] space [-0.5 * volumeSize, 0.5 * volumeSize] Matrix4x4.Scale(volumeBounds.size) * // [0, 1] space to [-0.5, 0.5] space Matrix4x4.Translate(new Vector3(-0.5f, -0.5f, -0.5f)) * // voxel space to [0, 1] space Matrix4x4.Scale(new Vector3(1.0f / data.Voxels.width, 1.0f / data.Voxels.height, 1.0f / data.Voxels.volumeDepth)) * // move by half a voxel Matrix4x4.Translate(new Vector3(0.5f, 0.5f, 0.5f)); cs.SetMatrix(VoxelizationResources.INDEX_TO_POSITION, indexToPosition); (var tgX, var tgY, var tgZ) = resources.FindFilledVoxelsThreadGroupsSize; commandBuffer.BeginSample(FIND_FILLED_VOXELS); commandBuffer.ClearRandomWriteTargets(); commandBuffer.DispatchCompute(cs, kernel, NumGroup(data.Voxels.width, tgX), NumGroup(data.Voxels.height, tgY), NumGroup(data.Voxels.volumeDepth, tgZ)); commandBuffer.EndSample(FIND_FILLED_VOXELS); }
private static void Begin(CommandBuffer commandBuffer, VoxelizationResources resources, VoxelsData data, Mesh mesh) { // reset command buffer // must render states are setup in the shader so no need to set everything commandBuffer.Clear(); commandBuffer.DisableScissorRect(); // for debugging purposes, bind a render target to examine shader behaviour // to be removed // TODO: find out how to set null render target // viewport is implicitly set var vp = data.ViewportSize; commandBuffer.GetTemporaryRT(TEMP_RT, vp.x, vp.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat); commandBuffer.SetRenderTarget(TEMP_RT); }
private static void End(CommandBuffer commandBuffer, VoxelizationResources resources, VoxelsData data, Mesh mesh) { commandBuffer.ReleaseTemporaryRT(TEMP_RT); }