Hello, I'm new to Compute Shaders, I want to write a compute shader that modifies the texture by applying the color overlay filter effect. I tested the formula in C# and it works, but I'm unable to test it in Compute Shader as I keep receiving errors when I try to set a texture. The texture has read and write enabled. These are the errors that I receive: 1. Attempting to bind Texture ID 1395 as UAV, the texture wasn't created with the UAV usage flag set! UnityEngine.ComputeShader:SetTexture(Int32, String, Texture) 2. IndexOutOfRangeException: Invalid kernelIndex (0) passed, must be non-negative less than 1. UnityEngine.ComputeShader.SetTexture (System.Int32 kernelIndex, System.String name, UnityEngine.Texture texture) (at <e98ed0368295432e8c11e52d6243ee11>:0) If I set a render texture it works fine, but I want to set a texture instead of a render texture. C# Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Test : MonoBehaviour { [SerializeField] Image output = null; [SerializeField] Texture texture = null; [SerializeField] Color overlay = Color.white; [SerializeField] ComputeShader compute = null; private Texture final; private int kernel; void Start() { kernel = compute.FindKernel("CSMain"); //final = new RenderTexture(image.sprite.texture.width, image.sprite.texture.height, 24); //final.enableRandomWrite = true; //final.Create(); } void Update() { final = texture; compute.SetTexture(kernel, "Result", final); compute.SetVector("color", overlay); compute.Dispatch(kernel, output.sprite.texture.width / 8, output.sprite.texture.height / 8, 1); output.sprite = Sprite.Create(final as Texture2D, Rect.zero, Vector2.zero); } } Compute Shader Code (CSharp): #pragma kernel CSMain RWTexture2D<float4> Result; float3 color; [numthreads(8, 8, 1)] void CSMain(uint3 id : SV_DispatchThreadID) { float r = Result[float2(id.x, id.y)].r > .5f ? 2.0f * Result[float2(id.x, id.y)].r * color.x : 1.0f - 2.0f * (1.0f - Result[float2(id.x, id.y)].r) * (1.0f - color.x); float g = Result[float2(id.x, id.y)].g > .5f ? 2.0f * Result[float2(id.x, id.y)].g * color.y : 1.0f - 2.0f * (1.0f - Result[float2(id.x, id.y)].g) * (1.0f - color.y); float b = Result[float2(id.x, id.y)].b > .5f ? 2.0f * Result[float2(id.x, id.y)].b * color.z : 1.0f - 2.0f * (1.0f - Result[float2(id.x, id.y)].b) * (1.0f - color.z); Result[id.xy] = float4(r, g, b, 1.0); }
So I modified the scripts and it works now. The problem is that I still need to call readpixels and apply methods which are expensive.. :/ C# Code (CSharp): using UnityEngine; using UnityEngine.UI; public class Test : MonoBehaviour { [SerializeField] Image output = null; [SerializeField] Texture texture = null; [SerializeField] Color overlay = Color.white; [SerializeField] ComputeShader compute = null; private RenderTexture final; private Texture2D generated; private int kernel; private bool hasKernel = false; private Color applied = Color.white; void Start() { kernel = compute.FindKernel("CSMain"); hasKernel = compute.HasKernel("CSMain"); generated = new Texture2D(texture.width, texture.height); final = new RenderTexture(texture.width, texture.height, 24) { enableRandomWrite = true }; final.Create(); } void Update() { if (!hasKernel) return; bool hasChanged = overlay != applied; compute.SetTexture(kernel, "Result", final); compute.SetTexture(kernel, "ImageInput", texture); compute.SetVector("color", overlay); compute.Dispatch(kernel, texture.width / 8, texture.height / 8, 1); if (hasChanged) { RenderTexture.active = final; //Expensive part generated.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); generated.Apply(); output.sprite = Sprite.Create(generated, new Rect(0.0f, 0.0f, texture.width, texture.height), new Vector2(0.5f, 0.5f), 100.0f); } applied = overlay; } } CS Code (CSharp): // Each #kernel tells which function to compile; you can have many kernels #pragma kernel CSMain RWTexture2D<float4> Result; Texture2D<float4> ImageInput; float3 color; [numthreads(8, 8, 1)] void CSMain(uint3 id : SV_DispatchThreadID) { float r = ImageInput[float2(id.x, id.y)].r > .5f ? 2.0f * ImageInput[float2(id.x, id.y)].r * color.x : 1.0f - 2.0f * (1.0f - ImageInput[float2(id.x, id.y)].r) * (1.0f - color.x); float g = ImageInput[float2(id.x, id.y)].g > .5f ? 2.0f * ImageInput[float2(id.x, id.y)].g * color.y : 1.0f - 2.0f * (1.0f - ImageInput[float2(id.x, id.y)].g) * (1.0f - color.y); float b = ImageInput[float2(id.x, id.y)].b > .5f ? 2.0f * ImageInput[float2(id.x, id.y)].b * color.z : 1.0f - 2.0f * (1.0f - ImageInput[float2(id.x, id.y)].b) * (1.0f - color.z); Result[id.xy] = float4(r, g, b, 1.0); }