public static void SetupHistogramPreviewMaterial(HistogramData data) { data.previewMaterial.SetInt("_HistogramBucketCount", data.bucketCount); data.previewMaterial.SetBuffer("_HistogramReadOnly", data.histogram); data.previewMaterial.SetBuffer("_HistogramDataReadOnly", data.histogramData); data.previewMaterial.SetFloat("_Mode", (int)data.mode); }
public static void AllocateHistogramData(int histogramBucketCount, HistogramMode mode, out HistogramData data) { data = new HistogramData(); data.bucketCount = histogramBucketCount; data.mode = mode; data.histogram = new ComputeBuffer(histogramBucketCount, sizeof(uint) * 4, ComputeBufferType.Structured); data.histogramData = new ComputeBuffer(1, sizeof(uint) * 2, ComputeBufferType.Structured); data.previewMaterial = new Material(Shader.Find("Hidden/HistogramPreview")) { hideFlags = HideFlags.HideAndDontSave }; _dataCount++; }
public static void ComputeHistogram(CommandBuffer cmd, Texture input, HistogramData data) { using (new ProfilingScope(cmd, new ProfilingSampler("Generate Histogram"))) { MixtureUtils.SetupComputeTextureDimension(cmd, histogramCompute, input.dimension); // Clear buffers cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeBufferParam(histogramCompute, clearKernel, "_Histogram", data.histogram); int dispatchCount = input.width * input.height * TextureUtils.GetSliceCount(input) / 64; // Limit computing to 8K textures int yCount = Mathf.Clamp(dispatchCount / dispatchGroupSizeX / 64, 1, dispatchGroupSizeX); int xCount = Mathf.Clamp(dispatchCount / yCount / 8, 1, dispatchGroupSizeX); cmd.SetComputeIntParam(histogramCompute, "_DispatchSizeX", dispatchGroupSizeX); cmd.DispatchCompute(histogramCompute, clearKernel, xCount, yCount, 1); // Find luminance min / max in the texture // TODO: handle texture 3D and Cube cmd.SetComputeTextureParam(histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.SetComputeBufferParam(histogramCompute, computeLuminanceBufferKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeVectorParam(histogramCompute, "_InputTextureSize", new Vector4(input.width, input.height, TextureUtils.GetSliceCount(input), 0)); cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, computeLuminanceBufferKernel, "_Input", input); cmd.DispatchCompute(histogramCompute, computeLuminanceBufferKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input)); ReduceLuminanceBuffer(cmd, dispatchCount); // Generate histogram data in compute buffer cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_ImageLuminance", luminanceBuffer); cmd.SetComputeBufferParam(histogramCompute, generateHistogramKernel, "_Histogram", data.histogram); cmd.SetComputeTextureParam(histogramCompute, generateHistogramKernel, "_Input", input); cmd.SetComputeIntParam(histogramCompute, "_HistogramBucketCount", data.bucketCount); cmd.SetComputeVectorParam(histogramCompute, "_RcpTextureSize", new Vector4(1.0f / input.width, 1.0f / input.height, 1.0f / TextureUtils.GetSliceCount(input), 0)); MixtureUtils.SetTextureWithDimension(cmd, histogramCompute, generateHistogramKernel, "_Input", input); cmd.DispatchCompute(histogramCompute, generateHistogramKernel, Mathf.Max(1, input.width / 8), Mathf.Max(1, input.height / 8), TextureUtils.GetSliceCount(input)); cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_HistogramData", data.histogramData); cmd.SetComputeBufferParam(histogramCompute, computeHistogramDataKernel, "_Histogram", data.histogram); cmd.DispatchCompute(histogramCompute, computeHistogramDataKernel, Mathf.Max(1, data.bucketCount / 64), 1, 1); // Request histogram data back for inspector cmd.RequestAsyncReadback(luminanceBuffer, 8, 0, (c) => { var d = c.GetData <float>(); if (d.Length > 0) { data.minLuminance = d[0]; data.maxLuminance = d[1]; } }); } }
public static void Dispose(HistogramData data) { if (data == null) { return; } _dataCount--; data.histogram?.Dispose(); data.histogramData?.Dispose(); CoreUtils.Destroy(data.previewMaterial); if (_dataCount == 0) { luminanceBuffer.Dispose(); } }
public HistogramView(HistogramData data, MixtureGraphView graphView, int height = 200) { var modeField = new EnumField("Histogram Mode", data.mode); modeField.RegisterValueChangedCallback(e => { graphView.RegisterCompleteObjectUndo("Changed histogram Mode"); data.mode = (HistogramMode)e.newValue; }); Add(modeField); var drawHistogram = new DrawHistogram(data, height); Add(drawHistogram); var minMaxLabel = new Label(); Add(minMaxLabel); schedule.Execute(() => { minMaxLabel.text = $"Luminance min: {data.minLuminance:F3}, max: {data.maxLuminance:F3}"; }).Every(20); }
public void UpdateHistogramData(HistogramData data) => this.data = data;
public DrawHistogram(HistogramData data, int height = 200) { this.data = data; style.flexGrow = 1; style.height = height; }