-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Anisotropic Kuwahara Filter #68
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Large diffs are not rendered by default.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using GraphProcessor; | ||
using UnityEngine; | ||
using UnityEngine.Rendering; | ||
|
||
namespace Mixture | ||
{ | ||
[System.Serializable][NodeMenuItem("Operators/Anisotropic Kuwahara Filter")] | ||
public class AnisotropicKuwaharaFilter : ComputeShaderNode | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you write a bit of documentation on this node using the [Documentation] attribute? |
||
{ | ||
protected override string computeShaderResourcePath => "Mixture/AnisotropicKuwaharaFilter"; | ||
|
||
public override string name => "Anisotropic Kuwahara Filter"; | ||
|
||
public override Texture previewTexture => output; | ||
public override bool showDefaultInspector => true; | ||
[Input("Source")] public Texture source; | ||
[Input("TFM")] public Texture tfm; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to avoid using abbreviations in node parameters :) |
||
[Output] public CustomRenderTexture output; | ||
[ShowInInspector] public int passCount = 2; | ||
[ShowInInspector] public int kuwaharaRadius = 5; | ||
[ShowInInspector] public float kuwaharaAlpha = 1.0f; | ||
[ShowInInspector] public int kuwaharaQ = 1; | ||
[ShowInInspector] public float strokeScale = 0.5f; | ||
[ShowInInspector] public bool useZeta; | ||
[ShowInInspector] public float zeta; | ||
[ShowInInspector] public float sharpness = 8; | ||
[ShowInInspector] public float hardness = 8; | ||
[ShowInInspector] public float zeroCrossing = 0.58f; | ||
private RenderTexture inputCopy; | ||
|
||
private int kuwaharaComputeKernel; | ||
|
||
protected override void Enable() | ||
{ | ||
base.Enable(); | ||
UpdateTempRenderTexture(ref output); | ||
kuwaharaComputeKernel = computeShader.FindKernel("AnisotropicKuwahara"); | ||
} | ||
|
||
|
||
private void ValidateTempRenderTexture() | ||
{ | ||
if (inputCopy == null || inputCopy.width != output.width || | ||
inputCopy.height != output.height) | ||
{ | ||
inputCopy?.Release(); | ||
inputCopy = new RenderTexture(output.width, output.height, 0, output.format); | ||
inputCopy.enableRandomWrite = true; | ||
inputCopy.Create(); | ||
} | ||
} | ||
|
||
protected override void Disable() | ||
{ | ||
base.Disable(); | ||
inputCopy?.Release(); | ||
} | ||
|
||
protected override bool ProcessNode(CommandBuffer cmd) | ||
{ | ||
if (!base.ProcessNode(cmd) || tfm == null || source == null) | ||
return false; | ||
ValidateTempRenderTexture(); | ||
for (int i = 0; i < passCount; i++) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is an acceptable range of value for the pass count? It's to know if it's worth avoiding the copy inside the loop or not. |
||
{ | ||
// Copy previous output | ||
cmd.Blit(i == 0 ? source : output, inputCopy); | ||
|
||
cmd.SetComputeTextureParam(computeShader, kuwaharaComputeKernel, "_Source", inputCopy); | ||
cmd.SetComputeTextureParam(computeShader, kuwaharaComputeKernel, "_TFM", tfm); | ||
cmd.SetComputeTextureParam(computeShader, kuwaharaComputeKernel, "_Output", output); | ||
cmd.SetComputeIntParam(computeShader, "_KuwaharaRadius", kuwaharaRadius); | ||
cmd.SetComputeFloatParam(computeShader, "_KuwaharaAlpha", kuwaharaAlpha); | ||
cmd.SetComputeFloatParam(computeShader, "_KuwaharaQ", kuwaharaQ); | ||
cmd.SetComputeFloatParam(computeShader, "_StrokeScale", strokeScale); | ||
cmd.SetComputeFloatParam(computeShader, "_Hardness", hardness); | ||
cmd.SetComputeFloatParam(computeShader, "_ZeroCrossing", zeroCrossing); | ||
cmd.SetComputeFloatParam(computeShader, "_Zeta", | ||
useZeta ? zeta : 2.0f / 2.0f / (kuwaharaRadius / 2.0f)); | ||
DispatchCompute(cmd, kuwaharaComputeKernel, output.width, output.height, 1); | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using GraphProcessor; | ||
|
||
namespace Mixture | ||
{ | ||
[System.Serializable, NodeMenuItem("Operator/Edge Tengent Flow")] | ||
public class EdgeTengentFlow : FixedShaderNode | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you write a bit of documentation on this node using the [Documentation] attribute? |
||
{ | ||
public override string name => "Edge Tengent Flow"; | ||
public override string shaderName => "Hidden/Mixture/EdgeTengentFlow"; | ||
public override bool displayMaterialInspector => true; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.CompilerServices; | ||
using GraphProcessor; | ||
using UnityEngine; | ||
using UnityEngine.Rendering; | ||
|
||
namespace Mixture | ||
{ | ||
[System.Serializable][NodeMenuItem("Operator/Line Integral Convolution")] | ||
public class LineIntegralConvolution : ComputeShaderNode | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here for doc :) |
||
{ | ||
protected override string computeShaderResourcePath => "Mixture/LineIntegralConvolution"; | ||
|
||
public override string name => "Line Integral Convolution"; | ||
public override Texture previewTexture => LIC; | ||
[Input("TFM")] public Texture tfm; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. abbreviation |
||
[Input("Noise")] public Texture noise; | ||
[Input("Gaussian Kernel")][SerializeField] private ComputeBuffer gaussianKernel; | ||
[Input("Kernel Radius")][SerializeField] private int kernelRadius; | ||
[Output] public CustomRenderTexture LIC; | ||
|
||
private int lic; | ||
protected override void Enable() | ||
{ | ||
base.Enable(); | ||
lic = computeShader.FindKernel("LIC"); | ||
UpdateTempRenderTexture(ref LIC); | ||
} | ||
|
||
|
||
protected override bool ProcessNode(CommandBuffer cmd) | ||
{ | ||
if (!base.ProcessNode(cmd) || tfm == null || noise == null || gaussianKernel == null) | ||
return false; | ||
cmd.SetComputeBufferParam(computeShader, lic, "__Kernel", gaussianKernel); | ||
cmd.SetComputeTextureParam(computeShader, lic, "__TFM", tfm); | ||
cmd.SetComputeTextureParam(computeShader, lic, "__Noise", noise); | ||
cmd.SetComputeTextureParam(computeShader, lic, "_LIC", LIC); | ||
cmd.SetComputeIntParam(computeShader, "__KernelRadius", kernelRadius); | ||
|
||
DispatchCompute(cmd, computeShader, lic, tfm.width, tfm.height, 1); | ||
return true; | ||
} | ||
} | ||
|
||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
using UnityEngine; | ||
using GraphProcessor; | ||
using UnityEngine.Rendering; | ||
|
||
namespace Mixture | ||
{ | ||
[System.Serializable, NodeMenuItem("Utility/Gaussian Kernel")] | ||
public class GaussianKernelNode : MixtureNode | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doc :) |
||
{ | ||
[Input] [SerializeField] private int kernelRadius; | ||
|
||
[Input] [SerializeField] private float kernelSigma; | ||
|
||
[Output] public ComputeBuffer kernelBuffer; | ||
[Output("Kernel Radius")] public int kernelRadiusOutput; | ||
|
||
public override string name => "Gaussian Kernel"; | ||
|
||
public override bool showDefaultInspector => true; // Make the serializable field visible in the node UI. | ||
|
||
private int currentRadius; | ||
private float currentSigma; | ||
|
||
protected override bool ProcessNode(CommandBuffer cmd) | ||
{ | ||
if (!base.ProcessNode(cmd)) | ||
return false; | ||
|
||
UpdateKernel(kernelRadius, kernelSigma); | ||
kernelRadiusOutput = kernelRadius; | ||
return true; | ||
} | ||
|
||
private void UpdateKernel(int newRadius, float newSigma) | ||
{ | ||
if (kernelBuffer == null || | ||
!kernelBuffer.IsValid() || | ||
!Mathf.Approximately(newRadius, currentRadius) || | ||
!Mathf.Approximately(newSigma, currentSigma)) | ||
{ | ||
kernelBuffer?.Dispose(); | ||
this.currentRadius = newRadius; | ||
this.currentSigma = newSigma; | ||
kernelBuffer = CreateKernel(newRadius, newSigma); | ||
} | ||
} | ||
|
||
private static ComputeBuffer CreateKernel(int gaussianRadius, float gaussianSigma) | ||
{ | ||
var kernel = OneDimensinalKernel(gaussianRadius, gaussianSigma);// GenerateGaussianKernel(gaussianRadius, gaussianSigma); | ||
var buffer = new ComputeBuffer(kernel.Length, sizeof(float), ComputeBufferType.Default); | ||
buffer.SetData(kernel); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use CommandBuffer.SetBufferData instead otherwise the execution of the graph and the data will be out of sync. |
||
return buffer; | ||
} | ||
|
||
private static float[] OneDimensinalKernel(int radius, float sigma) | ||
{ | ||
float[] kernelResult = new float[radius * 2 + 1]; | ||
float sum = 0.0f; | ||
for(int t = 0; t< radius; t++) | ||
{ | ||
double newBlurWalue = 0.39894 * Mathf.Exp(-0.5f * t*t / (sigma * sigma)) / sigma; | ||
kernelResult[radius+t] = (float)newBlurWalue; | ||
kernelResult[radius-t] = (float)newBlurWalue; | ||
if(t!=0) | ||
sum += (float)newBlurWalue*2.0f; | ||
else | ||
sum += (float)newBlurWalue; | ||
} | ||
// normalize kernels | ||
for(int k = 0; k< radius*2 +1; k++) | ||
{ | ||
kernelResult[k]/=sum; | ||
} | ||
return kernelResult; | ||
} | ||
|
||
protected override void Disable() | ||
{ | ||
base.Disable(); | ||
kernelBuffer?.Dispose(); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the license of this image?