Accumulate Graphics.Blit on CPU RAM

Hey everyone!

I’m quite lost on this one, not really sure where the issue is.
There are two issues:

  • Not being able to accumulate Graphics.Blit stamps
  • Not being able to get the accumulated Graphics.Blit on the CPU memory

I solved the first issue at some point, but it resurfaced, and I don’t know why.
But even when I was able to accumulate Graphics.Blit stamps, those only showed up

  • in the Game view, not
  • in the Scene view or
  • when Saving it to a .png.

Are there some known issues regarding this?
If someone wants to have a look, I attached the project.
Only the stamps from the last Blit show up.

Here is the code I am using:

using System.Collections; using System.Collections.Generic;
using System.IO;
using UnityEngine; using UnityEngine.UI;
public class DrawToCPU : MonoBehaviour {
string exportFolder = "";
void Awake () {
    exportFolder = Application.persistentDataPath + "/PngExport/";
    if (!Directory.Exists(exportFolder)) {Directory.CreateDirectory(exportFolder);}
    draw = Draw();
    StartCoroutine(draw);
}
Vector2 blitScale = new Vector2(5.0f,5.0f);
Vector2[] blitOffsets = new Vector2[4]{
    new Vector2(-1.25f,-1.25f),
    new Vector2(-1.25f,-3.75f),
    new Vector2(-3.75f,-1.25f),
    new Vector2(-3.75f,-3.75f)
};
Color WhiteA0 = new Color(1.0f,1.0f,1.0f,0.0f);
public Texture2D stamp, result;
public RenderTexture rend, temp;
IEnumerator draw;
IEnumerator Draw () {
    GL.Clear(false,false,WhiteA0);
    for (int i = 0; i < 4; i++) {
        temp = RenderTexture.GetTemporary(2048,2048);
        Graphics.Blit(stamp, temp, blitScale, blitOffsets[i]);
        Graphics.Blit(temp, rend);
        //RenderTexture.ReleaseTemporary(temp);
        Debug.Log("Drawn to " + blitOffsets[i]);
        yield return new WaitForSeconds(0.5f);
    }
    result = GPUtoCPU(rend);
    Save(result,exportFolder);
}
Texture2D GPUtoCPU (RenderTexture rend) {
    RenderTexture curr = RenderTexture.active;
    RenderTexture.active = rend;
    Texture2D img = new Texture2D(rend.width,rend.height);
    img.ReadPixels(new Rect(0,0,img.width,img.height),0,0);
    img.Apply();
    RenderTexture.active = curr;
    return img;
}
void Save (Texture2D img, string exportFolder) {
    string filePath = string.Empty;
    filePath = exportFolder + "Image.png";
    FileStream fs = new FileStream(filePath, FileMode.Create);
    byte[] imgBytes = img.EncodeToPNG();
    fs.Write(imgBytes,0,imgBytes.Length);
    fs.Close();
    Debug.Log("File saved to " + exportFolder);
}
}

Best wishes,
Shu

8670879–1168068–BlitStamps.zip (49.3 KB)

How to report your problem productively in the Unity3D forums:

http://plbm.com/?p=220

This is the bare minimum of information to report:

  • what you want (something to do with “stamps” perhaps? What?)
  • what you tried
  • what you expected to happen <---- very important!
  • what actually happened, especially any errors you see
  • links to documentation you used to cross-check your work (CRITICAL!!!)

You may edit your post above.

Not quite sure I can follow.
Aside from not linking the docs (which I’m not sure what exactly I would refer to, since I find the docs quite limited there, especially not including any show cases regarding what I’m aiming for), I guess my post included all the info?
But I’ll try again anyway:

I’m sorry, I guess I don’t know what “Accumulate Graphics.Blit on CPU” means.

I have used Graphics.Blit() and I have used RenderTextures.

I’ve never mixed / matched them, but I imagine it’s possible.

As for “accumulate” on a “CPU” that’s not a thing I know of. CPUs have tiny amounts of RAM, virtually nothing, so there’s certainly no images being accumulated on CPUs.

I think he wants to do the render texture using cpu and accumulate something ? A queue? A queue of things to render accumulated on the cpu?

a queue of things to render
But perform rendering on cpu
Instead of graphics blit

but he talks from the context that he only knows how to do graphics blit

Is this true?

Maybe I’m just not wording it right to make it understandable. I’ll try again:

I have:

Stamp (Texture2D) like this (black background is transparent, I just put it there for illustration purposes, so you can see the white shape):

RenderTexture:
Using Graphics.Blit, I am able to print a scaled down version of the stamp onto the RenderTexture. But further Graphics.Blit clear the previous ones. Instead, I want them to accumulate.
(Within code: IEnumerator Draw)

Result (Texture2D) - The RenderTexture resides on GPU only memory, so I need to get it back* using Texture2D.Readpixels to be able to access it via CPU (C#) and encode it to .png. The result should look like this:
(Within code:
Texture2D GPUtoCPU (RenderTexture rend)
and
void Save (Texture2D img, string exportFolder))

"
A render texture only has a data representation on the GPU and you need to use Texture2D.ReadPixels to transfer its contents to CPU memory
"
( Unity - Scripting API: RenderTexture )

AHA! I get it now…

I do this on my lotto scratcher: it starts from the gray texture image and as you scratch it goes to the original image.

Full source and project setup linked in comments.

https://www.youtube.com/watch?v=N_Ia9_LpV2M

1 Like

Ah so this is a management issue.

You simply need to make a list of things you are going to put in render and in one final post render apply the combined changes in one hit.
So it would involve sending it to a script for logging and then this script could be your final in the execution order and then that slams the post render down

I love a good scribble tool. I really do.

Thanks, @Kurt-Dekker ! That’s great! Didn’t have time to look into it yet (holidays), but it sure is comparable functionality!