Creating textures with compute shader not giving no results.

I am trying to create 3 textures with each pixel having random color. I have it working on CPU but I am trying to port it to GPU using compute shader. Its not working and my textures are just not being created.

C#

//Create world map textures (GPU aka compute shader)
        if (bUseComputeShader)
        {
                //Create render texture X
                var rTextureX = new RenderTexture(worldMapTextureSize,worldMapTextureSize, 0, RenderTextureFormat.RFloat)
                {
                    enableRandomWrite = true
                };
                rTextureX.Create();

                 //Create render texture Y
                var rTextureY = new RenderTexture(worldMapTextureSize,worldMapTextureSize, 0, RenderTextureFormat.RFloat)
                {
                    enableRandomWrite = true
                };
                rTextureY.Create();

                 //Create render texture Z
                var rTextureZ = new RenderTexture(worldMapTextureSize,worldMapTextureSize, 0, RenderTextureFormat.RFloat)
                {
                    enableRandomWrite = true
                };
                rTextureZ.Create();

                //Do shader paramaters (0 is kernel index of world textures)(Make sure thread data is exact *8,1,1* as compute shader)
                computeShader.SetTexture(0, "entityWorldTextureX", rTextureX);
                computeShader.SetTexture(0, "entityWorldTextureY", rTextureY);
                computeShader.SetTexture(0, "entityWorldTextureZ", rTextureZ);
                computeShader.Dispatch(0, worldMapTextureSize / 8, worldMapTextureSize / 8, 1);

                //Create world map texture X
                worldMapTextureX = new Texture2D(worldMapTextureSize,worldMapTextureSize, TextureFormat.RGB24, false);
                RenderTexture.active = rTextureX;
                worldMapTextureX.ReadPixels(new Rect(0, 0,rTextureX.width, rTextureX.height), 0, 0);
                worldMapTextureX.Apply();

                //Create world map texture y
                worldMapTextureY = new Texture2D(worldMapTextureSize,worldMapTextureSize, TextureFormat.RGB24, false);
                RenderTexture.active = rTextureY;
                worldMapTextureY.ReadPixels(new Rect(0, 0,rTextureY.width, rTextureY.height), 0, 0);
                worldMapTextureY.Apply();

                //Create world map texture z
                worldMapTextureZ = new Texture2D(worldMapTextureSize,worldMapTextureSize, TextureFormat.RGB24, false);
                RenderTexture.active = rTextureZ;
                worldMapTextureZ.ReadPixels(new Rect(0, 0,rTextureZ.width, rTextureZ.height), 0, 0);
                worldMapTextureZ.Apply();
        }

C# Draw Textures

//Used to debug our world map texture
    void OnGUI()
    {
        if (!bWorldMapGUIEnabled)
            return;

        const float size = 128;
        const float margin = 10;
        GUI.DrawTexture(new Rect(0,0,size,size), worldMapTextureX);
        GUI.DrawTexture(new Rect(0,size + margin,size,size), worldMapTextureY);
        GUI.DrawTexture(new Rect(0, size + size + margin + margin,size,size), worldMapTextureZ);
    }

Compute shader

RWTexture2D<float4> entityWorldTextureX;
RWTexture2D<float4> entityWorldTextureY;
RWTexture2D<float4> entityWorldTextureZ;

[numthreads(8,8,1)]
void CSCreateEntityWorldTextures (uint3 id : SV_DispatchThreadID)
{
     //Set world texture X pixel
    float r = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    float g = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    float b = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    entityWorldTextureX[id.xy] = float4(r,g,b,1);

    //Set world texture Y pixel
    r = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    g = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    b = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    entityWorldTextureY[id.xy] = float4(r,g,b,1);

     //Set world texture Z pixel
    r = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    g = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    b = frac(sin(dot(float2(0.1,1),float2(12.9898,78.233)))*43758.5453123);
    entityWorldTextureZ[id.xy] = float4(r,g,b,1);
}

So I got some results on gpu but not what I want. First I will show cpu results which is what I want.
you can see 3 random textures being generated on left side screen. Each pixel is just a random color.

C#

//create world map texture X
            var worldMapTexture = new Texture2D(worldMapTextureSize,worldMapTextureSize);
            for (int x = 0; x < worldMapTextureSize; x++)
                for (int y = 0; y < worldMapTextureSize; y++)
                    worldMapTexture.SetPixel(x,y, UnityEngine.Random.ColorHSV(0.2f, 1f, 0.2f, 1f, 0.2f, 1f));
            worldMapTexture.Apply();

            //create world map render texture x from above texture
            worldMapRenderTextureX = new RenderTexture(worldMapTextureSize / 2 ,worldMapTextureSize / 2,0);
            Graphics.Blit(worldMapTexture, worldMapRenderTextureX);

            //create world map texture y
             for (int x = 0; x < worldMapTextureSize; x++)
                for (int y = 0; y < worldMapTextureSize; y++)
                    worldMapTexture.SetPixel(x,y, UnityEngine.Random.ColorHSV(0.2f, 1f, 0.2f, 1f, 0.2f, 1f));
            worldMapTexture.Apply();

            //create world map render texture x from above texture
            worldMapRenderTextureY = new RenderTexture(worldMapTextureSize / 2 ,worldMapTextureSize / 2,0);
            Graphics.Blit(worldMapTexture, worldMapRenderTextureY);

             //create world map texture y
             for (int x = 0; x < worldMapTextureSize; x++)
                for (int y = 0; y < worldMapTextureSize; y++)
                    worldMapTexture.SetPixel(x,y, UnityEngine.Random.ColorHSV(0.2f, 1f, 0.2f, 1f, 0.2f, 1f));
            worldMapTexture.Apply();

            //create world map render texture x from above texture
            worldMapRenderTextureZ = new RenderTexture(worldMapTextureSize / 2 ,worldMapTextureSize / 2,0);
            Graphics.Blit(worldMapTexture, worldMapRenderTextureZ);

Now here is gpu results. I am just getting red textures for some reason.

Compute shader

RWTexture2D<float4> entityWorldTextureX;
RWTexture2D<float4> entityWorldTextureY;
RWTexture2D<float4> entityWorldTextureZ;

[numthreads(8,1,1)]
void CSCreateEntityWorldTextures (uint3 id : SV_DispatchThreadID)
{
    //rand (is range)
    float2 rand = float2(0,1);

    //Set world texture X pixel
    float r = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    float g = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    float b = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    float a = 1;
    entityWorldTextureX[id.xy] = float4(r,g,b,a);

    //Set world texture Y pixel
    r = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    g = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    b = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    a = 1;
    entityWorldTextureY[id.xy] = float4(r,g,b,a);

    //Set world texture Y pixel
    r = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    g = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    b = frac(sin(dot(rand .xy, float2(12.9898, 78.233))) * 43758.5453);
    a = 1;
    entityWorldTextureZ[id.xy] = float4(r,g,b,a);
}

So the function just does not seem to work at all. Its return all black textures. Not sure what I am doing wrong. Perhaps its numthreads or something?

Compute shader
[numthreads(8,8,1)]
void CSCreateEntityWorldTextures (uint3 id : SV_DispatchThreadID)
{
    //Should be gray
    entityWorldTextureX[id.xy] = float4(0.5, 0.5, 0.5, 1);

    //Should be blue
    entityWorldTextureY[id.xy] = float4(0,1,0,1);

    //Should be green
    entityWorldTextureZ[id.xy] = float4(0,0,1,1);
}

C#

computeShader.Dispatch(0, worldMapTextureSize / 8, worldMapTextureSize / 8, 1);

At glance seems you are creating your render textures as RFloat, which only contain a single channel, but your compute shader expects a texture with four channels. Maybe that’s the problem?

1 Like

Thanks. I got it working. I was creating render texts in C# wrong by typo.

I had

 worldMapRenderTextureX = new RenderTexture(worldMapTextureSize,0, worldMapTextureSize);

Supposed to be

 worldMapRenderTextureX = new RenderTexture(worldMapTextureSize,worldMapTextureSize,24);

Not sure how typo happened when I did it right in CPU version.

Thanks anyway.