I am making a picture analyzer which needs the accurate values of color. When I tried to parse float values from compute shader to my script via **Texture2D**, it's not accurate. For example, when parsing float **0.5** via the r channel texture, it will first convert to value **127**, which represents "**half of a channel**". Then in my script, I use Texture2D.GetPixel(x, y) to read the color, it will convert **127** to **127/255** back. So **float 0.5 from compute shader to my script will be converted to 0.498039……**, which isn't I expected.
Therefore, I want to **use an array to read the output value but not the texture**.
However, It has some problem. I do a test. Here are my codes:
###Compute shader
#pragma kernel CSMain
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D input;
RWStructuredBuffer output;
[numthreads(16,16,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
// TODO: insert actual code here!
uint index = id.x * 16 + id.y;
//There should be some operations here, then I get the final value
//Operations.....................
//Then get the result here
float4 finalValue = input[id.xy];
output[index] = finalValue;
}
###Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestParse : MonoBehaviour
{
public ComputeShader shader;
public RenderTexture input;
public Material material;
private Vector4[] output;
private ComputeBuffer buffer;
private int kernel;
private Texture2D texture;
// Start is called before the first frame update
void Start()
{
output = new Vector4[16 * 16];
buffer = new ComputeBuffer(16 * 16, 4 * sizeof(float));
kernel = shader.FindKernel("CSMain");
input.enableRandomWrite = true;
shader.SetTexture(kernel, "input", input);
shader.SetBuffer(kernel, "output", buffer);
texture = new Texture2D(16, 16, TextureFormat.RGBA32, false);
texture.filterMode = FilterMode.Point;
material.SetTexture("_MainTex", texture);
}
// Update is called once per frame
void Update()
{
shader.Dispatch(kernel, 16, 16, 1);
buffer.GetData(output);
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index = i * 16 + j;
texture.SetPixel(i, j, new Color(output[index].x, output[index].y, output[index].z, output[index].w));
}
}
texture.Apply();
}
private void OnDisable()
{
buffer.Release();
}
}
In this example, I can parse the **RenderTexture** to the compute shader, then copy the value to a **Vector4** array, then set the color of the test **Texture2D** based on the array. So in theory, the colors of the test **Texture2D** will be the same as the colors of the input **RenderTexture**.
However, this is what I get:
![alt text][1]
![alt text][2]
[1]: /storage/temp/143954-computeshadererror.png
[2]: /storage/temp/143955-gif-animation-001.gif
Does anyone knows how to solve this problem? If it can't be solve, do you know why? Thanks.
↧