- Home /
Use RenderTexture to sample pixels from camera?
I have a camera. How do I sample pixels from this camera? What call do I make to the camera to get a texture of what the camera is going to render?
Answer by _Gkxd · Aug 26, 2015 at 07:27 PM
I did actually have to do this in one of my projects, where I used some off-screen rendering to detect mouse clicks on non-standard objects (cubic bezier curves to be precise). As far as I know, there is no way of directly accessing the data inside a RenderTexture, since the data is stored on the GPU. You have to transfer it to a Texture2D in order to actually sample the texture on the CPU (in scripts).
Here is a relevant code snippet from that project that does this (attached to a camera object):
public Camera offscreenCamera; // The camera that will do the offscreen rendering
// Initialize everything properly in Start/Awake
private RenderTexture curveSelectTargetTexture; // The target texture
private Texture2D curveSelectTexture; // The texture we sample from
private bool shouldDoRendering; // Prevents the process from happening every frame
void OnPostRender() {
if (shouldDoRendering) {
// Make sure that the the target texture actually exists
if (!curveSelectTargetTexture.IsCreated()) {
curveSelectTargetTexture.Create();
}
// Set camera to render to our target texture
offscreenCamera.targetTexture = curveSelectTargetTexture;
/* Offscreen rendering was done here (removed from this code snippet) */
// The following line transfers the data from the RenderTexture to the Texture2D
curveSelectTexture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
Color colorOfPixelAtMouse = curveSelectTexture.GetPixel((int)Input.mousePosition.x, (int)Input.mousePosition.y);
// Some other processing that is irrelevant
}
}
Note that the pixels in the Texture2D will be anti-aliased. You can disable this by disabling anti-aliasing in the quality settings, but then your game would not have anti-aliasing. You can also disable anti-aliasing by making the camera use deferred rendering, though I have encountered a bug where anti-aliasing still occurs in orthographic view.
If you are rendering visuals, then this doesn't really matter, but if you are rendering information (which is what I had to do), then you will need to either disable anti-aliasing or filter out garbage information caused by anti-aliasing.
You will probably be most interested in the line that contains GetPixel
.
Thanks. That's a brilliant example. I'll try it out. :)
Okey so hm that didn't work. Is the RenderTexture even used? I just get 0, 0, 0, 1 as the RGBA color.
You can use the following line to see if the Texture2D actually contains anything:
System.IO.File.WriteAllBytes(Application.dataPath + "/../SomeTestFileName.png", curveSelectTexture.EncodeToPNG());
This will save an image in your project folder whenever it's called. Be sure not to call this every frame, or your program will crash.
$$anonymous$$y guess is that you're not rendering anything. After you set the target texture of the camera, you have to do some rendering so that the target texture actually contains things.
I realized I didn't even need to use a RenderTexture! As I just needed the color (I didn't need to draw it), I could just do this:
void OnPostRender(){
cameraTex2D.ReadPixels(new Rect(0, 0, screenWidth, screenHeight), 0, 0);
Color sampledPixelColor = cameraTex2D.GetPixel(pixelPositionX, pixelPositionY);
// Do something with sampled color.
}
Thank you for your help though! :)
Answer by Thomas-Mountainborn · Aug 26, 2015 at 06:57 PM
Use OnRenderImage.
That seems pretty neat but how do I grab a specific pixel from the src RenderTexture?
Your answer
