Search Unity

Finally, I can export compute shaders only builds, but the output's origin is off

Discussion in 'Shaders' started by asperatology, May 3, 2019.

  1. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981


    While attempting to debug the compute shader, I don't understand why the output render texture is positioned, so the origin is (0, 0) at the bottom left corner of the whole program, and not the black rectangle area.

    (And yes, I had Standard shader lighting on the black rectangle area).

    I'm trying to do a compute shader only build from Unity, exporting the build out as a packaged executable, and this is how I got.

    Any tips and tricks to fix the compute shader, please let me know.

    Mandelbrot compute shader:

    Code (CSharp):
    1. // Each #kernel tells which function to compile; you can have many kernels
    2. #pragma kernel Mandelbrot
    3.  
    4. // Create a RenderTexture with enableRandomWrite flag and set it
    5. // with cs.SetTexture
    6. RWTexture2D<float4> Result;
    7.  
    8. //Boundaries in the fractal space that are currently visible on the screen.
    9. RWStructuredBuffer<double> Area;
    10.  
    11. //A set of colors that has been prepared on the CPU side, and is written to the GPU.
    12. RWStructuredBuffer<float4> Color;
    13.  
    14. [numthreads(32,32,1)]
    15. void Mandelbrot(uint3 id : SV_DispatchThreadID) {
    16.     uint width, height;
    17.     Result.GetDimensions(width, height);
    18.  
    19.     // delta.x = (CenterX + Width / 2) - (CenterX - Width / 2)
    20.     // delta.y = (CenterY + Height / 2) - (CenterY - Height / 2)
    21.     double2 delta = double2(Area[2] - Area[0], Area[3] - Area[1]);
    22.  
    23.     //Initial point/pixel coordinates
    24.     double2 pixel = double2(Area[0] + ((int) id.x) * delta.x / double(width), Area[1] + ((int) id.y) * delta.y / double(height));
    25.  
    26.     //Previous iteration of the point/pixel coordinates.
    27.     double2 Old = pixel;
    28.     double2 New = double2(0.0, 0.0);
    29.     double Length = 0.0;
    30.  
    31.     //Iteration loop
    32.     uint iteration = 0;
    33.     for (; iteration < 255; iteration++) {
    34.         New = double2(Old.x * Old.x - Old.y * Old.y + pixel.x, 2.0 * Old.x * Old.y + pixel.y);
    35.         Old = New;
    36.         Length = Old.x * Old.x + Old.y * Old.y;
    37.         if (Length >= 16.0f)
    38.             break;
    39.     }
    40.  
    41.     //Output
    42.     Result[id.xy] = Color[iteration % 256];
    43. }
    44.  
    MandelbrotComponent.cs, the C# script that enables the compute shader to blit to the screen.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MandelbrotComponent : MonoBehaviour {
    6.     //Zoom factor of the Mandelbrot.
    7.     public double depthFactor = 1.0;
    8.  
    9.     //Center of the viewport rect.
    10.     public double centerX = 0.0;
    11.     public double centerY = 0.0;
    12.  
    13.     //Middle mouse button control.
    14.     public bool moveButton;
    15.  
    16.     //Compute shader.
    17.     public ComputeShader mandelbrotShader;
    18.     protected int shaderKernel = 0;
    19.  
    20.     //Render Texture output
    21.     protected RenderTexture outputRenderTexture;
    22.     protected Material material;
    23.  
    24.     //Compute buffers
    25.     protected ComputeBuffer areaRectBuffer;
    26.     protected ComputeBuffer colorsBuffer;
    27.     protected double[] areaRectArray;
    28.     protected Color[] colorsArray;
    29.  
    30.     public void Start() {
    31.         //Setting up the render texture.
    32.         this.outputRenderTexture = new RenderTexture(Screen.width, Screen.height, 24) {
    33.             enableRandomWrite = true,
    34.             filterMode = FilterMode.Point
    35.         };
    36.         this.outputRenderTexture.Create();
    37.  
    38.         //Set up the material
    39.         MeshRenderer renderer = this.GetComponent<MeshRenderer>();
    40.         this.material = renderer.material;
    41.  
    42.         //Compute buffers setup
    43.         this.areaRectArray = new double[4] {
    44.             -2.0, -2.0, 2.0, 2.0
    45.         };
    46.         this.areaRectBuffer = new ComputeBuffer(this.areaRectArray.Length, sizeof(double));
    47.         this.areaRectBuffer.SetData(this.areaRectArray);
    48.         this.colorsArray = new Color[256];
    49.         for (int i = 0; i < this.colorsArray.Length; i++) {
    50.             this.colorsArray[i] = new Color(0.0f, 0.0f, 0.0f, 1f);
    51.             if (0 <= i && i < 128)
    52.                 this.colorsArray[i] += new Color(0f, 0f, Mathf.PingPong(i * 4f, 256f) / 256f, 1f);
    53.             if (64 <= i && i < 192)
    54.                 this.colorsArray[i] += new Color(0f, Mathf.PingPong((i - 64) * 4f, 256f) / 256f, 0f, 1f);
    55.             if (128 <= i && i < 256)
    56.                 this.colorsArray[i] += new Color(Mathf.PingPong(i * 4f, 256f) / 256f, 0f, 0f, 1f);
    57.         }
    58.         this.colorsBuffer = new ComputeBuffer(this.colorsArray.Length, 4 * 4);
    59.         this.colorsBuffer.SetData(this.colorsArray);
    60.  
    61.         //Setting up the shader.
    62.         if (!this.mandelbrotShader)
    63.             this.mandelbrotShader = Resources.Load<ComputeShader>("Mandelbrot");
    64.         this.shaderKernel = this.mandelbrotShader.FindKernel("Mandelbrot");
    65.         this.mandelbrotShader.SetBuffer(this.shaderKernel, "Area", this.areaRectBuffer);
    66.         this.mandelbrotShader.SetBuffer(this.shaderKernel, "Color", this.colorsBuffer);
    67.         this.mandelbrotShader.SetTexture(this.shaderKernel, "Result", this.outputRenderTexture);
    68.         this.mandelbrotShader.Dispatch(this.shaderKernel, 32, 32, 1);
    69.         this.material.mainTexture = this.outputRenderTexture;
    70.     }
    71.  
    72.     public void Update() {
    73.         if (this.InputHandler()) {
    74.             this.mandelbrotShader.Dispatch(this.shaderKernel, 32, 32, 1);
    75.             this.material.mainTexture = this.outputRenderTexture;
    76.         }
    77.     }
    78.  
    79.     public void OnDestroy() {
    80.         this.areaRectBuffer.Release();
    81.         this.colorsBuffer.Release();
    82.     }
    83.  
    84.     private bool InputHandler() {
    85.         const double BorderChange = 2.0;
    86.  
    87.         bool result = false;
    88.  
    89.         if (Input.mouseScrollDelta.y != 0) {
    90.             this.depthFactor -= 0.2 * this.depthFactor * Input.mouseScrollDelta.y;
    91.             result = true;
    92.         }
    93.  
    94.         //Scroll mouse button held down
    95.         if (Input.GetMouseButtonDown(2))
    96.             this.moveButton = true;
    97.         if (Input.GetMouseButtonUp(2))
    98.             this.moveButton = false;
    99.         if (this.moveButton) {
    100.             float mouseXAxis = Input.GetAxis("Mouse X");
    101.             float mouseYAxis = Input.GetAxis("Mouse Y");
    102.             if (mouseXAxis != 0f || mouseYAxis != 0f) {
    103.                 result = true;
    104.             }
    105.             this.centerX -= 100 / ((double) Screen.width) * this.depthFactor * mouseXAxis;
    106.             this.centerY -= 100 / ((double) Screen.height) * this.depthFactor * mouseYAxis;
    107.         }
    108.  
    109.         if (result) {
    110.             this.areaRectArray[0] = this.centerX - this.depthFactor * BorderChange;
    111.             this.areaRectArray[1] = this.centerY - this.depthFactor * BorderChange;
    112.             this.areaRectArray[2] = this.centerX + this.depthFactor * BorderChange;
    113.             this.areaRectArray[3] = this.centerY + this.depthFactor * BorderChange;
    114.             this.areaRectBuffer.SetData(this.areaRectArray);
    115.         }
    116.  
    117.         return result;
    118.     }
    119. }
    120.