Advertisement

Computer shader of average filter on depth buffer using unity

Started by November 08, 2020 11:20 AM
0 comments, last by AhmedSaleh 4 years, 2 months ago

Hello,

I'm having difficulty porting a filter that I wrote in C# and It's pretty slow and I would like to convert it to a compute shader.

  1. Right now I get compilation error and I also don't know how would compute shader work on that algorithm.
  2. I'm not sure If doing the average calculation is correct as it is right now ?

The original code:

   public unsafe  void DRSFilter( byte *  src, byte * dst, uint data_delta, uint history_scan_depth)
    {
        if (history_scan_depth > history_capacity)
        {
            history_scan_depth = history_capacity;
        }

        for (int i = 0; i < layer_size; i++)
        {
            byte b = src[i];
            uint avrg = 0;
            for (int k = 0; k < history_scan_depth; k++)
            {
                avrg += history[k * layer_size + i];

            }
            average[i] = (byte)(avrg / history_scan_depth);

            if (Math.Abs(b - average[i]) < data_delta)
            {
                dst[i] = b;
            }


            history[layer * layer_size + i] = b;
        }

        layer++;
        if (layer == history_scan_depth)
        {
            layer = 0;
        }
    }

The new trial of compute shader in unity:

Shader Initialization:

   private const int width = 1280;
   private const int height = 720;
   private int history_capacity = 3;
   private int layer_size = width * height * 6;
   private int layer = 0;
   public int history_scan_depth = 50;
   public int data_delta = 50;
   private int[] history;
   private int[] average;
   public ComputeShader shader;
   private int handleDepthFilter;
   private Texture depthFiltered;
   history = new int[history_capacity * layer_size];
   average = new int[layer_size];
   shader.SetInt("history_scan_depth", history_scan_depth);
   shader.SetInt("data_delta", data_delta);
   shader.SetInt("history_capacity", history_capacity);
   shader.SetInt("layer_size", layer_size);
   shader.SetInt("layer", layer);

  ComputeBuffer history_buffer = new ComputeBuffer(history_capacity * layer_size, sizeof(int));
  ComputeBuffer average_buffer = new ComputeBuffer(layer_size, sizeof(int));

  history_buffer.SetData(history);
  average_buffer.SetData(average);

  shader.SetBuffer(handleDepthFilter, "history_buffer", history_buffer);
  shader.SetBuffer(handleDepthFilter, "average_buffer", average_buffer);

 _outputTexture = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32);
 _outputTexture.enableRandomWrite = true;
 _outputTexture.Create()

Shader Code:


#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;
Texture2D<float4> Texture;
RWStructuredBuffer<int> history_buffer;
RWStructuredBuffer<int> average_buffer;
int history_scan_depth;
int history_capacity;
int data_delta;
int layer;
int layer_size;

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
   // TODO: insert actual code here!
   if (history_scan_depth > history_capacity)
   {
       history_scan_depth = history_capacity;
   }

   float4 b = Texture[id.xy];
   

   uint avrg = 0;
   for (int k = 0; k < history_scan_depth; k++)
   {
       avrg += history_buffer[k * layer_size + id.xy];

   }
   average_buffer[id] = (byte)(avrg / history_scan_depth);

   if (abs(b - average[id.xy) < data_delta)
   {
       Result[id] = b;
   }


   history_buffer[layer * layer_size + .xy] = b;


   _layer++;
   if (_layer == history_scan_depth)
   {
       _layer = 0;
   }
}

Shader dispatching:

 private void ImageUpdated(ref Texture2D zedTextureDepth)
   {

      Texture2D copyDepthRW = duplicateTexture(zedTextureDepth);
      shader.SetTexture(handleDepthFilter, "Texture", copyDepthRW);
      shader.SetTexture(handleDepthFilter, "Result", _outputTexture);
      shader.Dispatch(handleDepthFilter, (width) / 8,
          (height) / 8, 1);}
   }
   
Game Programming is the process of converting dead pictures to live ones .

This topic is closed to new replies.

Advertisement