Get Colors from RenderTexture faster!
Hey there!
I need to pull Colors from my RenderTexture (8x8 pixels) and I am doing that by reading it into a Texture2d first and then using GetPixel on that.
displayCamera.targetTexture = rt;
displayCamera.Render ();
RenderTexture.active = rt;
// WAY TOO SLOW
targetTexture.ReadPixels (new Rect (0, 0, xResolution, yResolution), 0, 0);
targetTexture.Apply ();
As you can see I already pointed out the problematic bottleneck line.
It uses about 35 ms on my CPU time, even though the Texture2D is also only 8x8 pixels large. Now I know it has to do with juggling the pixels between GPU and CPU, but is there really not any other way to just get pixel colors from a RenderTexture (or in my original interest, a MovieTexture) every frame?
If you know a way with shaders or something else, please help me! There seems to be no solution...
Okay, I read a lot and got to the conclusion that OpenGL is faster, or so everybody says. I tried for past few hours, but there seems to be a major problem in my understanding of how this works. I get a color, but it is like random noise, so I must be reading the buffer wrong. Please help!
[SerializeField] Light displayLight;
Camera displayCamera;
[SerializeField] ParticleSystemRenderer particles;
[SerializeField] int xResolution = 8;
[SerializeField] int yResolution = 8;
[SerializeField] Renderer display$$anonymous$$odelRenderer;
[SerializeField] bool play$$anonymous$$ovie = false;
$$anonymous$$ovieTexture movie;
void Awake(){
displayCamera = GetComponent<Camera> ();
if (play$$anonymous$$ovie) {
movie = ($$anonymous$$ovieTexture)display$$anonymous$$odelRenderer.material.GetTexture ("_Emission$$anonymous$$ap");
movie.loop = true;
movie.Play ();
}
displayCamera.aspect = 4f / 3f;
}
[DllImport("opengl32")]
public static extern void glReadPixels (int x, int y, int width, int height, int format, int type, IntPtr buffer);
void Update () {
displayCamera.Render();
}
const int GL_RGB = 0x1908;
const int GL_UNSIGNED_BYTE = 0x1401;
public byte[] destination;
public class ColorBuffer
{
int stackpointer = 0;
float red = 0f;
float green = 0f;
float blue = 0f;
public void save(byte input){
int position = stackpointer % 3;
switch (position) {
case 0:
red += input;
break;
case 1:
green += input;
break;
case 2:
blue += input;
break;
default:
break;
}
stackpointer++;
}
public Color load(){
return new Color (
((red / (stackpointer / 3f)) / 255f),
((green / (stackpointer / 3f)) / 255f),
((blue / (stackpointer / 3f)) / 255f)
);
}
}
void OnPostRender(){
int size = xResolution * yResolution * 3;
IntPtr buffer = $$anonymous$$arshal.AllocHGlobal (size);
byte[] bytes = new byte[size];
glReadPixels(0, 0, xResolution, yResolution, GL_RGB, GL_UNSIGNED_BYTE, buffer);
$$anonymous$$arshal.Copy(buffer, bytes, 0, size);
ColorBuffer cb = new ColorBuffer();
for (int i = 0; i < size; i++)
cb.save(bytes[i]);
Color newColor = cb.load ();
displayLight.color = newColor;
Debug.Log("Color: " +
newColor.r.ToString("F2") + ", " +
newColor.g.ToString("F2") + ", " +
newColor.b.ToString("F2") + ", " +
newColor.a.ToString("F2"));
$$anonymous$$arshal.FreeHGlobal(buffer);
}
Answer by gwelkind · Nov 03, 2021 at 07:52 PM
You might want a compute shader. It depends on what you're trying to do wit hit.
Your answer
Follow this Question
Related Questions
Rendering Camera to PNG produces completely grey image. 1 Answer
Convert Texture to Texture2d takes a lot of time in android device. 0 Answers
Trying to Take a Snapshot of Only a Portion of the Screen In-Game 0 Answers
Read Pixels to Texture2D in EditorWindow make unity crash 2 Answers
Using 3D Render Texture with camera 0 Answers