Quantcast
Channel: Questions in topic: "compute shader"
Viewing all articles
Browse latest Browse all 287

Reading from RWTexture2D in compute shader Unity

$
0
0
I'm learning compute shader with Unity, but I've encountered a bug when transferring RenderTexture to the compute shader. Basically, there're 2 texture being transferred, `renderTexture` and `copyTex`. The steps are as follow: 1. `copyTex` copy from `renderTexture` with `Graphics.CopyTexture()` 2. Both are transferred to compute shader, and a new `renderTexture` would be calculated from `copyTex` 3. Compute shader finished, `renderTexture` is used to display, then everything looped again But for some reason, the `copyTex` after transferred to the compute shader is blank. This is the main C# code: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ComputeShaderTest : MonoBehaviour { public ComputeShader computeShader; public RenderTexture renderTexture; private RenderTexture copyTex; [SerializeField] private Image image; [SerializeField] private Vector2Int size = new Vector2Int(512, 512); private Texture2D tex; void Start() { InitializeRenderTexture(); StartCoroutine(SlowTest()); } private void InitializeRenderTexture() { if (!renderTexture) { renderTexture = new RenderTexture(size.x, size.y, 24); renderTexture.enableRandomWrite = true; renderTexture.Create(); copyTex = new RenderTexture(size.x, size.y, 24); copyTex.enableRandomWrite = true; copyTex.Create(); } //populate texture2d with all white and black patch in middle Vector2Int pos = new Vector2Int(size.x / 2, size.y / 2); tex = new Texture2D(size.x, size.y, TextureFormat.RGB24, false); for (int i = 0; i < size.x; i++) { for (int j = 0; j < size.y; j++) { tex.SetPixel(i, j, Color.white); } } for (int i = pos.x-10; i < pos.x+10; i++) { for (int j = pos.y-10; j < pos.y+10; j++) { tex.SetPixel(i, j, Color.black); } } tex.Apply(); //copy to rendertexture RenderTexture.active = renderTexture; Graphics.Blit(tex, renderTexture); } IEnumerator SlowTest() { UpdateTexture2D(); while(true) { yield return new WaitForSeconds(1f); TouchTest(); Debug.Log("Passed"); UpdateTexture2D(); } } private void UpdateTexture2D() { RenderTexture.active = renderTexture; tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0); tex.Apply(); image.material.mainTexture = tex; } private void TouchTest() { Vector2Int pos = new Vector2Int(size.x/2, size.y/2); Graphics.CopyTexture(renderTexture, copyTex); computeShader.SetInt("posX", pos.x); computeShader.SetInt("posY", pos.y); computeShader.SetInt("resolution", size.x); computeShader.SetTexture(0, "Result", renderTexture); computeShader.SetTexture(0, "Copy", copyTex); computeShader.Dispatch(0, renderTexture.width / 8, renderTexture.height / 8, 1); } } And the compute shader: #pragma kernel CSMain RWTexture2D Result; RWTexture2D Copy; int posX; int posY; int resolution; int dx[9] = {-1, 1, 1, 0, 1, -1, -1, 0, 0}; int dy[9] = {1, 0, 1, 1, -1, 0, -1, -1, 0}; [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID) { int x = id.x, y = id.y; if (x != 0 && x != resolution - 1 && y != 0 && y != resolution - 1) { if (Copy[id.xy].a > 0.5) //white { Result[id.xy] = float4(1, 0, 0, 1); //set to red } } } I can conclude the `copyTex` is blank because right after copy, I tested it with this piece of code: RenderTexture.active = copyTex; tex.ReadPixels(new Rect(0, 0, copyTex.width, copyTex.height), 0, 0); tex.Apply(); image.material.mainTexture = tex; and everything show up fine; but after the compute shader ran and the `renderTexture` got display, every pixels were red (which means the if statement activated, and all those pixels are previously white). So texture can't be manipulated to transfer data and I have to use a custom `RWStructuredBuffer` instead or I mess up somewhere?

Viewing all articles
Browse latest Browse all 287

Trending Articles